什么是代码分片

代码分片是webpack作为打包工具所特有的一项技术,通过这项技术,我们可以把代码按照规定的形式进行拆分,使用户不必一次加载全部,而是按需加载js、css和资源文件等。

作用

代码分片可以有效降低首屏加载资源的大小,单同时也会带来新的问题,比如我们应该对那些模块进行分片,分片后的资源如何管理等。

CommonsChunkPlugin

CommonesChunkPluginWebpack 4之前内部自带的插件,Webpack 4之后替换为了SplitChucks。它可以将多个Chunk中的公共的部分提取出来,起到如下作用:

  • 开发中减少重复模块打包,可以提升开发编译速度;
  • 减少整体资源体积;
  • 合理分片之后的代码可以跟有效的利用客户端缓存。

多入口公共模块提取

例子:

  1. //webpack.config.js
  2. module.exports={
  3. entry:{
  4. foo:'./foo.js',
  5. bar:'./bar.js'
  6. },
  7. output:{
  8. filename:'[name].js'
  9. }
  10. }
  11. //foo.js
  12. import React from 'react';
  13. document.write('foo.js',React.version);
  14. //bar.js
  15. import React from 'react';
  16. document.write('bar.js',React.version);

打包结果如下图:

React被分别打包进入到连个js文件中,因此连个文件都是72.1KB,文件较大。

接下来更改webpack.config.js,添加CommonsChunkPlugin配置。

const webpack=require('webpack');
moduel.exports={
    entry:{
        foo:'foo.js',
        bar:'bar.js'
    },
    output:{
        filename:'[name].js'
    },
    plugins:[
        new webpack.optimize.CommonsChunkPlugin({
            name:'commons',
            filename:'commons.js'
        })
    ]
}

更改后的打包结果如下图:

产出的资源中多出了一个commons.js文件,而foo.jsbar.js都缩小到不到1KB,这是因为React及其依赖都被提取到了commons.js中了。

提取vendor

设置提取范围

设置提取规则

hash和长效缓存

不足

optimization.SplitChunks

它是Webpack 4为了改进CommonsChunkPlugin而重新设计和实现的代码分片特性。

可以对异步加载的模块和公共模块进行合理的分片处理。

module.exports={
    optimization:{
        //几乎不用添加其他配置
        splitChunks:{
            chunks:'all'
        }
    }
}

资源异步加载

在Webpack中有两种异步加载的方式——import函数及require.ensure。require.ensure是Webpack 1支持的异步加载方式,从Webpack 2开始引入了import函数,并且官方也更推荐使用它。

正常加载:

//foo.js
import {add} from './bar.js';
console.log(add(2,3));

//bar.js
export function add(a,b){
    return a+b;
}

异步加载:

//foo.js
import('./bar.js').then(({add})=>{
    console.log(add(2,3));
})

//bar.js
export function add(a,b){
    return a+b;
}

异步chunk的配置

修改Webpackfoo.js的配置:

//webpack.config.js
module.exports={
    ...
    output:{
        publicPath:'/dist/',
        filename:'[name].js',
        //配置chunk文件的名称
        chunkFilename:'[name].js'
    }
}
//foo.js
import(/* webpackChunkName:"bar" */'./bar.js').then(({add})=>{
    console.log(add(2,3));
})