Webpack 代码分割及缓存

1,070 阅读3分钟

Code Splitting (代码拆分)

Code Splitting 与 webpack 无关 , 实现代码拆分有很多种形式

  1. 手动加载 第三方依赖的入口文件,进行打包
entry:{
  lodash : '../src/lodash.js' ,  // 这里引入了lodash 并赋值给 window对象,  那么webpack 会先打包								// 出这个入口文件 , 然后再去打包index.js , 至此就完成了第一种区							  // 分打包
  main : '../src/index.js' // 业务逻辑的入口文件 
}
  1. 同步加载

     import _ from 'lodash' ; // 1. 同步加载第三方模块 
     // _.xx()   
    
    

    然后在webpack配置

    module.exports = {
      optimization : {
        splitChunks : {
          chunks : 'all' ,   // 让同步模块和异步模块都进行代码分离 
        }
      } 
    }
    

optimization.splitChunks 配置

module.exports = {
  optimization : {
    splitChunks : {
      chunks : 'async' ,   // 异步模块进行代码分离
      // 默认值async,all:异步|同步模块都进行代码分离,initial 同步模块
      minSize : 30000 ,  // 模块必须大于30000字节才会进行代码分离
      maxSize : 0  ,	// 生成代码块的最大大小,如果此模块大于这个maxSize 那么他可能会进行二次拆分 
      minChunks : 1 , // 打包之后的Chunk引用此模块时 Chunk引用此模块数 >=minChunks 才会对此模块进行代码分割 
      maxAsyncRequests : 5 , // 按需加载时并行请求的最大数量。
      maxInitialRequests:3 , // 入口文件的模块最大拆分数  
      automaticNameDelimiter : '~' , //拆分文件名的默认连接符
      name : true , // 分割块的名称。提供true将根据块和缓存组键自动生成名称。
      cacheGroups: { // 缓存组
       	 vendors : {	// vendor组
           	 test: /[\\/]node_modules[\\/]/, // 匹配处于node_modules中的模块
          	 priority: -10	// 优先级   数值越大越高
          	 filename : 'vendor.js'
       	 },
       	 default : {	// 默认组 
       	 	priority : -20 , // 优先级 
       	 	reuseExistingChunk : true ,   //  如果当前块包含已经从主包中分离出来的模块,那么它将被重用,而不是生成一个新的模块。这可能会影响块的结果文件名。
       	 	filename : 'default.js'
       	 }	
      }
    }
  } 
}

懒加载

当webpack 遇到异步加载模块时,webpack会进行懒加载来提升性能,什么时候加载关机键点在于什么时候引入此模块
vue 中的router  就是通过异步加载模块来让webpack进行懒加载功能



// chunk : 当webapck 打包出来之后 ,每有一个文件就算一个chunk 

分析工具

webpack 官方提供了非常多的分析工具,来分析打包的过程和结果

首先得得到一个分析结果文件 。 一般叫做 state.json

webpack --profile --json > stats.json

官方推荐分析工具、网站

webpack.js.org/guides/code…

Prefetching/Preloading modules (空闲加载/预加载) 模块

webpack配置文件中

optimization:{
  splitChunks : {
    chunks : 'async'  // async 为默认值 
  }
}

webpack 比较推荐的方式是 异步加载 , 因为只需要加载可使用的模块

(空闲加载/预加载) 模块 这个的用处在于 , 当一个异步模块更换他的加载方式时,可以使用空闲加载此异步模块,还是预加载异步模块

在webpack中可以使用魔法注释来完成空闲加载/预加载 异步模块

例:

// 此异步模块会进行空闲加载 
const { handleClick: fun } = await import(/* webpackPrefetch: true */'./click.js')

// 此异步模块会进行预先加载 
const { handleClick: fun } = await import(/* webpackPreload: true */'./click.js')

具体文档 : webpack.js.org/guides/code…

可以查看chrome开发者工具中的 coverage 来查看代码的利用率 , 通常来说, 代码利用率越高,网页性能越好

缓存

对于webpack来说,可以使用 [contenthash] 来进行缓存管理 , 如果代码没有进行改变的话,hash不会变化

output:{
  filename : 'main[contenthash].js',
  chunkFilename : '[name][contenthash].js'
}

在老版本的webpack中 入口chunk 可能每次对应的contenthash 可能不一样,因为webpack默认将运行时的代码放入入口chunk中,这些运行时的代码可能每次运行都不一样 , 所以才导致入口chunk 每次对应的contenthash不一样解决这个问题:

optimization : {
  runtimeChunk : {
    name : 'runtime' ;
  }
}

Shimming

用来处理兼容问题 . .

// 当你使用 _ 对象时 , webpack 会去使用 loadsh 中的模块对象  
new webpack.ProvidePlugin({
       _: 'lodash'
 })