webpack-optimization介绍

5,995 阅读3分钟

从webpack3升级到webpack4的过程中,官方移除了commonchunk插件,改用了optimization.splitChunks替代:

splitChunks优点

  • 它不会打包不需要的模块
  • 对异步模块有效(默认情况下是打开的)
  • 更加容易使用和更加自动化

今天介绍一下optimization的用法: webpack.js.org/configurati…

optimization.minimize

module.exports = {
  //...
  optimization: {
    minimize: false
  }
};

如果mode是production类型,minimize的默认值是true,执行默认压缩,

optimization.minimizer

当然如果想使用第三方的压缩插件也可以在optimization.minimizer的数组列表中进行配置

optimization.splitChunks webpack.js.org/plugins/spl…
module.exports = {
  //...
  optimization: {
    splitChunks: {
     //chunks: 表示显示块的范围,有三个可选值:initial(初始块)、async(按需加载块)、all(全部块),默认为all;
      chunks: 'async',
      minSize: 30000, // 表示在压缩前的最小模块大小,默认是30kb;
      minRemainingSize: 0, // 
      maxSize: 0,
      minChunks: 1, // 表示被引用次数,默认为1;
      maxAsyncRequests: 6, //所有异步请求不得超过6个
      maxInitialRequests: 4, //初始话并行请求不得超过4个
      automaticNameDelimiter: '~', //名称分隔符,默认是~
      automaticNameMaxLength: 30,
      // cacheGroups: 缓存组
      cacheGroups: { 
         common: {
             name: 'common',  //抽取的chunk的名字
             chunks(chunk) { //同外层的参数配置,覆盖外层的chunks,以chunk为维度进行抽取
             },
             test(module, chunks) {  //可以为字符串,正则表达式,函数,以module为维度进行抽取,只要是满足条件的module都会被抽取到该common的chunk中,为函数时第一个参数是遍历到的每一个模块,第二个参数是每一个引用到该模块的chunks数组。自己尝试过程中发现不能提取出css,待进一步验证。
             },
            priority: 10,  //优先级,一个chunk很可能满足多个缓存组,会被抽取到优先级高的缓存组中
           minChunks: 2,  //最少被几个chunk引用
           reuseExistingChunk: true//  如果该chunk中引用了已经被抽取的chunk,直接引用该chunk,不会重复打包代码
           enforce: true  // 如果cacheGroup中没有设置minSize,则据此判断是否使用上层的minSize,true:则使用0,false:使用上层minSize
       }
        vendors: {
          test: /[\\/]node_modules[\\/]/,
          priority: -10
        },
        default: {
          minChunks: 2,
          priority: -20,
          reuseExistingChunk: true
        }
      }
    }
  }
};
optimization.runtimeChunk webpack.js.org/configurati…

object string boolean

module.exports = {
  //...
  optimization: {
    runtimeChunk: {
      name: entrypoint => `runtime~${entrypoint.name}`
    }
  }
};

runtimeChunk ,作用是将包含chunks映射关系的list单独从app.js里提取出来,因为每一个chunk的id基本都是基于内容hash出来的,所以你每次改动都会影响它,如果不把它提取出来的话,等于app.js每次都会改变,缓存就失效了。 在使用 CommonsChunkPlugin的时候,我们也通常把webpack runtime 的基础函数提取出来,单独作为一个chunk,毕竟code splitting想把不变的代码单独抽离出来,方便浏览器缓存,提升加载速度。 其实就是单独分离出webpack的一些运行文件。

假设一个使用动态导入的情况(使用import()),在app.js动态导入component.js

const app = () =>import('./component').then();

build之后,产生3个包。

  • 0.01e47fe5.js
  • main.xxx.js
  • runtime.xxx.js

其中runtime,用于管理被分出来的包。

function jsonpScriptSrc(chunkId) {
     return __webpack_require__.p + "" + ({}[chunkId]||chunkId) + "." + {"0":"01e47fe5"}[chunkId] + ".bundle.js"
 }

如果采用这种分包策略

  • 当更改app的时候runtime与(被分出的动态加载的代码)0.01e47fe5.js的名称(hash)不会改变,main的名称(hash)会改变。
  • 当更改component.js,main的名称(hash)不会改变,runtime与 (动态加载的代码) 0.01e47fe5.js的名称(hash)会改变。

optimization.noEmitOnErrors

webpack.docschina.org/configurati…

在编译出错时,使用 optimization.noEmitOnErrors 来跳过生成阶段(emitting phase)。这可以确保没有生成出错误资源。而 stats 中所有 assets 中的 emitted 标记都是 false。

module.exports = {
  //...
  optimization: {
    noEmitOnErrors: true
  }
};

参考:www.jianshu.com/p/a12928c18…