搭建一个企业级的Vue工程!

239 阅读3分钟

虽然Vue CLI可以快速生成项目,但是对于企业需要扩展特定的功能变得极其复杂,并不适合定制化的开发,所以企业中通常是开发人员自己通过构建工具去配置打包项目。下面演示Vue工程的配置代码。

图片

webpack配置分为了4个:公共的以base命名,开发环境的以dev命名,生产环境的以pro命名,以dll命名的是称为动态连接库是提高打包速度用。

上来直接撸代码,我就不再具体介绍哪个loader怎么用了,因为npm官网介绍的比我还清楚。


// webpack.base.conf.js
const path = require('path')
const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const AddAssetHtmlPlugin = require('add-asset-html-webpack-plugin')
const ProgressBarPlugin = require('progress-bar-webpack-plugin')
const VueLoaderPlugin = require('vue-loader/lib/plugin')
const dir = process.cwd()

module.exports = {
  entry: {
    app: path.resolve(dir, 'src/main.js')
  },
  resolve: {
    extensions: [
      '.js', '.vue', '.less', '.css'
    ],
    alias: {
      'src': path.resolve(dir, 'src')
    }
  },
  module: {
    rules: [
      {
        test: /\.(jsx?|babel|es6)$/,
        include: dir,
        exclude: /node_modules/,
        loader: 'babel-loader'
      },
      {
        test: /\.vue$/,
        loader: 'vue-loader',
        options: {
          compilerOptions: {
            preserveWhitespace: false
          }
        }
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: path.resolve(dir, 'template.html'),
      chunks: ['app']
    }),
    new webpack.DllReferencePlugin({
      manifest: path.resolve(dir, 'manifest.json')
    }),
    new AddAssetHtmlPlugin({ filepath: path.resolve(dir, 'dist/vendor.dll.js') }),
    new ProgressBarPlugin(),
    new VueLoaderPlugin()
  ]
}
// webpack.dev.conf.js
const webpack = require('webpack')
const path = require('path')
const Merge = require('webpack-merge')
const dir = process.cwd()
const baseConfig = require('./webpack.base.conf')

module.exports = Merge(baseConfig, {
  mode: 'development',
  output: {
    filename: 'js/[name]_[hash].js',
    path: path.resolve(dir, 'dist')
  },
  devtool: 'source-map',
  plugins: [
    new webpack.DefinePlugin({
      NODE_ENV: JSON.stringify('development')
    })
  ],
  module: {
    rules: [
      {
        enforce: 'pre',
        test: /\.vue$/,
        loader: 'eslint-loader',
        exclude: /node_modules/,
        include: path.resolve(dir, 'src'),
        options: {
          formatter: require('eslint-friendly-formatter'),
          cache: true,
          emitWarning: true,
          emitError: true
        }
      },
      {
        test: /\.(png|svg|jpe?g)$/i,
        loader: 'url-loader',
        options: {
          esModule: false
        }
      },
      {
        test: /\.(woff|woff2|eot|ttf|otf)$/i,
        loader: 'file-loader',
        options: {
          esModule: false
        }
      },
      {
        test: /\.(css|less)$/,
        use: [
          {
            loader: 'style-loader',
            options: {}
          },
          {
            loader: 'css-loader',
            options: {
              sourceMap: true
            }
          },
          {
            loader: 'less-loader',
            options: {
              sourceMap: true
            }
          }
        ]
      }
    ]
  },
  devServer: {
    host: 'localhost',
    port: 8000,
    hot: true,
    open: true,
    overlay: {
      errors: true,
      warnings: true
    },
    contentBase: path.resolve(dir, 'dist')
  },
  cache: true
})

在这里提一句关于动态连接库的事情,动态连接库就是把一些不会更改的包进行提前打包,之后再打包就会建立引用关系,就直接引用之前打好的包,不再进行二次打包了。


// webpack.dll.conf.js
const webpack = require('webpack')
const path = require('path')
const dir = process.cwd()

module.exports = {
  mode: 'production',
  entry: {
    vendor: ['vue', 'vuex', 'vue-router']
  },
  output: {
    library:  'familybucket',
    filename: '[name].dll.js'
  },
  plugins: [
    new webpack.DllPlugin({
      name: 'familybucket',
      path: path.resolve(dir, 'manifest.json')
    })
  ]
}

// webpack.pro.conf.js
const webpack = require('webpack')
const path = require('path')
const Merge = require('webpack-merge')
const dir = process.cwd()
const baseConfig = require('./webpack.base.conf')
const {CleanWebpackPlugin} = require('clean-webpack-plugin')
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')

module.exports = Merge(baseConfig, {
  optimization: {
    minimizer: [
      new OptimizeCSSAssetsPlugin(),
      new UglifyJsPlugin()
    ]
  },
  mode: 'production',
  output: {
    filename: 'js/[name]_[hash].js',
    path: path.resolve(dir, 'dist')
  },
  module: {
    rules: [
      {
        test: /\.(png|svg|jpe?g)$/,
        loader: 'url-loader',
        options: {
          limit: 8192,
          name: 'img/[name].[hash:7].[ext]',
          publicPath: '/',
          esModule: false
        }
      },
      {
        test: /\.(woff|woff2|eot|ttf|otf)$/,
        loader: 'file-loader',
        options: {
          name: 'fonts/[name].[hash:7].[ext]',
          esModule: false
        }
      },
      {
        test: /\.(css|less)$/,
        loaders: [
          {
            loader: MiniCssExtractPlugin.loader,
            options: {
              insertAt: 'top'
            }
          },
          {
            loader: 'css-loader',
            options: { importLoaders: 2 }
          },
          'postcss-loader',
          'less-loader'
        ]
      }
    ]
  },
  devtool: 'cheap-source-map',
  plugins: [
    new webpack.DefinePlugin({
      NODE_ENV: JSON.stringify('production')
    }),
    new CleanWebpackPlugin({
      cleanOnceBeforeBuildPatterns: ['**/*', '!vendor.dll.js']
    }),
    new MiniCssExtractPlugin({
      filename: 'css/[name].[hash:7].css'
    })
  ]

babel的配置是通过单独增加.babelrc文件

{
  "presets": ["@babel/preset-env"],
  "plugins": [
    [
      "@babel/plugin-transform-runtime",
      {
        "corejs": 3,
        "helpers": true,
        "regenerator": true,
        "useESModules": false
      }
    ],
    "@babel/plugin-proposal-class-properties"
  ]
}

postcss配置是通过单独增加postcss.config.js文件,postcss-preset-env是给CSS样式加前缀的,cssnano是去除多余的CSS的。

module.exports = ({ env }) => ({
  parser: false,
  plugins: {
    'postcss-preset-env': env === 'development' ? false : {},
    'cssnano': env === 'development' ? false: {}
  }
})

eslint的配置通过单独增加.eslintrc.js文件,这个配置文件可以通过eslint --init进行生成,然后进行定制化配置自己的规则。


module.exports = {
    "env": {
        "node": true,
        "es6": true
    },
    "extends": [
        "eslint:recommended",
        "plugin:vue/essential"
    ],
    "globals": {
        "Atomics": "readonly",
        "SharedArrayBuffer": "readonly"
    },
    "parserOptions": {
        "ecmaVersion": 2020,
        "sourceType": "module"
    },
    "plugins": [
        "vue"
    ],
    "rules": {
        "indent": ["error", 2],
        "space-before-function-paren": ["error", "always"],
        "quotes": ["error", 'single']
    }
};

这些配置已经完成了常用的开发功能,大家可自行扩展,需要代码链接请点击查看源码查看更多!