Optimization of webpack configuration based on vue-cli

  github, javascript, vue-cli, vue.js, webpack

Based onvue-cliOptimizedwebpackConfiguration

It can be roughly divided into the following points

  • viaexternalsConfigure to extract common libraries and reference external chains
  • ConfigurationCommonsChunkPluginExtract common codes (vue-cli(already done)
  • Make good use ofalias(vue-cliPart of it is configured)
  • EnableDllPluginAndDllReferencePluginPrecompiled library files
  • happypackStart a multi-core build project
  • willwebpack-parallel-uglify-pluginTo replacewebpackin-houseUglifyJSFor code compression confusion
  • UpgradewebpackTo version 3.x onScope Hoisting

externals

Document addresshttps://doc.webpack-china.org …

To prevent some import package from being packed into bundle, but to obtain these external dependencies from the outside at runtime.

CommonsChunkPlugin

Document addresshttps://doc.webpack-china.org …

The CommonschunkPlugin plug-in is an optional function for creating an independent file (also called Chunk), which includes a common module of multiple entry Chunks. By detaching the common module, the final synthesized file can be loaded once at the beginning and then stored in the cache for subsequent use. This brings about an increase in spee d, because browsers will quickly remove common code from the cache instead of loading a larger file each time they visit a new page.

resolve.alias

Document addresshttps://doc.webpack-china.org …

Create aliases for import or require to ensure easier module introduction. For example, some common modules located under src/ folder:

DllPlugin and DllReferencePlugin

Document addresshttps://doc.webpack-china.org …

The Dll will exist independently after packaging. As long as the libraries it contains are not increased or decreased or upgraded, the hash will not change. Therefore, the online dll code does not need to be updated frequently with the release of the version. Dll packages are basically independent library files, which have one feature that changes little. As long as the included libraries are not upgraded, increased or decreased, there is no need to repackage. This also improves the construction speed.

It is generally used in the packaging phase.

  1. InbuildNew under folderwebpack.dll.conf.jsFile
var path = require('path');
var webpack = require('webpack');
var AssetsPlugin = require('assets-webpack-plugin');
var CleanWebpackPlugin = require('clean-webpack-plugin');
var config = require('../config');
var env = config.build.env;

module.exports = {
  entry: {
    libs: [
      'babel-polyfill',
      'vue/dist/vue.esm.js',
      'vue-router',
      'vuex',
      'element-ui',
      'echarts',
      'mockjs',
    ],
  },
  output: {
    path: path.resolve(__dirname, '../libs'),
    filename: '[name].[chunkhash:7].js',
    library: '[name]_library',
  },
  plugins: [
    new webpack.DefinePlugin({
      'process.env': env,
    }),
    new webpack.DllPlugin({
      path: path.resolve(__dirname, '../libs/[name]-mainfest.json'),
      name: '[name]_library',
      context: __dirname, // 执行的上下文环境,对之后DllReferencePlugin有用
    }),
    new ExtractTextPlugin('[name].[contenthash:7].css'),
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        warnings: false,
      },
    }),
    new AssetsPlugin({
      filename: 'bundle-config.json',
      path: './libs',
    }),
    new CleanWebpackPlugin(['libs'], {
      root: path.join(__dirname, '../'), // 绝对路径
      verbose: true,
      dry: false,
    }),
  ],
  module: {
    rules: [
      {
        test: /\.js$/,
        loader: 'babel-loader',
      },
    ],
  },
};
  1. InbuildNew under folderbuild-dll.jsFile
var path = require("path");
var webpack = require("webpack");
var dllConfig = require("./webpack.dll.conf");
var chalk = require("chalk");
var rm = require("rimraf");
var ora = require("ora");

var spinner = ora({
  color: "green",
  text: "building for Dll..."
});
spinner.start();
rm(path.resolve(__dirname, "../libs"), err => {
  if (err) throw err;
  webpack(dllConfig, function(err, stats) {
    spinner.stop();
    if (err) throw err;
    process.stdout.write(
      stats.toString({
        colors: true,
        modules: false,
        children: false,
        chunks: false,
        chunkModules: false
      }) + "\n\n"
    );
    console.log(chalk.cyan(" build dll succeed !.\n"));
  });
});
  1. Modifywebpack.prod.conf.jsFile
var bundleConfig = require("../libs/bundle-config.json");
...
...
plugins: [
  // 增加DllReferencePlugin配置
  new webpack.DllReferencePlugin({
    context: __dirname,
    manifest: require("../libs/libs-mainfest.json") // 指向生成的manifest.json
  }),
  ...
  ...
  new HtmlWebpackPlugin({
    ...
    // 增加两个变量
    libJsName: bundleConfig.libs.js,
    libCssName: bundleConfig.libs.css,
  }),
  ...
  ...
  // 增加一个静态文件目录
   new CopyWebpackPlugin([
     ...
     ...
    {
      from: path.resolve(__dirname, "../libs"),
      to: config.build.assetsSubDirectory,
      ignore: ["*.json"]
    }
  ])
]
  1. Modify template fileindex.html
<body>
  <div id="app"></div>
  <!-- built files will be auto injected -->
  <% if (htmlWebpackPlugin.options.libCssName){ %>
    <link rel="stylesheet" href="./static/<%= htmlWebpackPlugin.options.libCssName %>">
  <% } %>

  <% if (htmlWebpackPlugin.options.libJsName){ %>
      <script src="./static/<%= htmlWebpackPlugin.options.libJsName %>"></script>
  <% } %>
</body>
  1. Modifypackage.json, increasescripts
"scripts": {
  // 增加
  "dll": "node build/build-dll.js"
},
  1. npm run dllPerform precompilation first, and then package the project file. If the introduced class library file has not changed, precompilation will not need to be performed again.

happypack

Document addresshttps://github.com/amireh/hap …

In general, node.js is compiled by a single thread, while happypack starts node’s multi-thread construction, which greatly improves the construction speed.

New a new happypack process in the plug-in, and then use the place where loader is used to replace it with the corresponding id.

  1. Modifywebpack.base.conf.jsFile
var HappyPack = require('happypack');
var os = require('os');
var happyThreadPool = HappyPack.ThreadPool({ size: os.cpus().length });
...
...
// 增加plugins
 plugins: [
  new HappyPack({
    id: 'happy-babel-js',
    loaders: ['babel-loader?cacheDirectory=true'],
    threadPool: happyThreadPool,
  })
]
...
...
// 修改对应loader
{
  test: /\.js$/,
  loader: 'happypack/loader?id=happy-babel-js',
  include: [resolve('src'), resolve('test')],
}

webpack-parallel-uglify-plugin

Document addresshttps://github.com/gdborton/w …

webpackProvidedUglifyJSPlug-ins are slow due to single thread compression.
webpack-parallel-uglify-pluginPlug-ins can run in parallelUglifyJSPlug-ins, which can effectively reduce the construction time.

  1. Modifywebpack.prod.conf.jsFile
var ParallelUglifyPlugin = require('webpack-parallel-uglify-plugin');
...
...
// 删掉webpack提供的UglifyJS插件
// new webpack.optimize.UglifyJsPlugin({
//   compress: {
//     warnings: false,
//     drop_console: true
//   },
//   sourceMap: true
// }),
// 增加 webpack-parallel-uglify-plugin来替换
new ParallelUglifyPlugin({
  cacheDir: '.cache/',
  uglifyJS:{
    output: {
      comments: false
    },
    compress: {
      warnings: false
    }
  }
}),

webpack 3

List of new features in webpack3https://juejin.im/entry/59714 …

Webpack 3.x provides a new function: Scope Hoisting, which is also translated as “scope promotion”. Just add a new plug-in to the configuration file, you can make the code file packaged by the Webpack smaller and run faster.

  1. Modifywebpack.prod.conf.js
...
...
plugins: [
  // 往plugins添加一个配置
  // ps 只针对es6的模块化有效
  new webpack.optimize.ModuleConcatenationPlugin(),
]

Ps: For details of configuration file, please clickhttps://github.com/liaoyinglo …