webpack高级概念code splitting 和 splitChunks (系列五)

当你把所有的代码都打包到一个文件的时候,每次改一个代码都需要重新打包。且用户都要重新加载下这个js文件。但是如果你把一些公共的代码或第三方库抽离并单独打包。通过缓存加载,会加快页面的加载速度。(分割成多个文件,不必打包成一个文件,提高性能)

  1. 异步加载的代码,webpack会单独打包到一个js文件中
  2. 同步加载的代码有两种方式

入口文件index.js

引入的第三方库
import _ from 'lodash'

业务逻辑代码
console.log(666)

 

打包后的文件main.js

main.js 551 KiB main [emitted] main
可以看到,webpack将业务代码跟lodash库打包到一个main.js文件了,每次更改业务代码,就要重新被打包一次,浪费性能

方法一:手动代码分割,不推荐

index.js

业务逻辑代码
console.log(666)

创建一个新文件lodsh.js入口, 将第三方的库单独抽离

import _ from 'lodash'
window._ = _

将文件挂载到 window 对象上,这样其他地方就可以直接使用了。

然后在webpack配置文件中的entry增加一个入口为该文件。

module.exports = {
    entry: {
        main: './src/index.js',
     //新增一个打包的文件,lodash为打包后的文件名称 ./src/lodash.js为入口文件, 映射关系 lodash:
'./src/lodash.js' },
    output: {
     //模糊匹配entry需要打包文件名称  filename:
'[name].js', path: path.resolve(__dirname, '../dist') }

 

打包后,打包成main,js和lodash.js两个文件,html会引入这两个文件。

当我们业务逻辑更改,webpack重新打包只需打包main.js,lodash.js会缓存在浏览器中代码分割打包,此时提高了性能

Asset      Size  Chunks             Chunk Names
lodash.js   551 KiB  lodash  [emitted]  lodash
  main.js  3.79 KiB    main  [emitted]  main


方法二: webpack自动代码分割

 

2.1,同步引入第三方库

入口文件index.js

// 同步加载lodash
import _ from 'lodash'
console.log(_.join(['a','b','c','***']))

在webpack.base.js配置optimization配置参数

    optimization: {
        // 代码分割配置
        splitChunks: {
            chunks: 'all'
        }
    },
    output: {
        filename: '[name].js',
        path: path.resolve(__dirname, '../dist')
    }
module.exports = {
    entry: {
        main: './src/index.js'
    },

 

打包后的文件,webapck的optimization会自动将诸如lodash等库抽离成单独的chunk,还会将多个模块公用的模块抽离成单独的chunk,提高性能

 

 

2.2,异步引入代码第三方库

index.js入口文件

function getComponent() {
    // 异步加载lodash
    return import('lodash').then(({ default: _ }) => {
        var element = document.createElement('div');
        element.innerHTML = _.join(['Dell', 'Lee'], '-');
        return element;
    })
}

getComponent().then(element => {
    document.body.appendChild(element);
});

不需要webpack做任何配置

打包后文件, lodash第三方库自动打包成单独的0.js,   vue中的路由懒加载就是这样,import函数

 

 

总结

// 代码分割,和webpack无关
// webpack中实现代码分割,两种方式
// 1. 同步代码: 只需要在webpack.common.js中做optimization的配置即可
// 2. 异步代码(import): 异步代码,无需做任何配置,会自动进行代码分割,放置到新的文件中

 

 

splitChunks里面还可以在添加个参数cacheGroups

optimization: {
    splitChunks: {
        chunks: 'all',
        cacheGroups: {
              // 下面的意思是:将从node_modules中引入的模块统一打包到一个vendors.js文件中
            vendors: {
                test: /[\\/]node_modules[\\/]/,
                priority: -10,
                filename: 'vendors.js'
            },
            default: false
        }
    }
}

 

 

 index.js入口文件

同步加载lodash
import _ from 'lodash'
console.log(_.join(['a','b','c','***']))

打包加载后,cacheGroupsvendors配置表示将node_modules中引入的模块(所有引入的第三方库)统一打包到一个vendors.js文件中

 如果venders的 filename: 'vendors.js',属性注释掉,那么默认会把第三方库lodash统一打包到vendors~main.js文件中(main.js为第三方库引入的文件)

 

splitChunksdefault参数:

根据上下文来解释,如上配置了vendors,打包node_modules文件夹中的模块,

那么default将会打包自己编写的公共方法

添加default的配置

optimization: {
    splitChunks: {
        chunks: 'all',
        cacheGroups: {
              // 下面的意思是:将从node_modules中引入的模块统一打包到一个vendors.js文件中
            vendors: {
                test: /[\\/]node_modules[\\/]/,
                priority: -10,
                filename: 'vendors.js'
            },
            // 打包除上面vendors以外的公共模块
            default: {
                priority: -20,
                reuseExistingChunks: true, // 如果该chunk已经被打包进其他模块了,这里就复用了,不打包进common.js了
                filename: 'common.js'
            }
        }
    }
}

 

新增test.js

export default {
    name: 'Dell Lee'
}

入口文件index.js,引入test模块

import test from './test.js';
console.log(test.name);

打包后,自己编写test.js的公共模块打包成common.js文件

 

 

splitChunks: {
  chunk: 'all', // all(全部), async(异步的模块),initial(同步的模块)
  minSize: 3000, // 表示文件大于3000k的时候才对他进行打包
  maxSize: 0,
  minChunks: 1, // 当某个模块满足minChunks引用次数时,才会被打包。例如,lodash只被一个文件import,那么lodash就不会被code splitting,lodash将会被打包进 被引入的那个文件中。如果满足minChunks引用次数,lodash会被单独抽离出来,打出一个chunk。
  maxAsyncRequests: 5, // 在打包某个模块的时候,最多分成5个chunk,多余的会合到最后一个chunk中。这里分析下这个属性过大过小带来的问题。当设置的过大时,模块被拆的太细,造成并发请求太多。影响性能。当设置过小时,比如1,公共模块无法被抽离成公共的chunk。每个打包出来的模块都会有公共chunk
  automaticNameDelimiter: '~', // 当vendors或者default中的filename不填时,打包出来的文件名就会带~
  name: true,
  cashGroups: {} // 如上
}

 

注意;chunk:'all' 默认等于下面一大窜的配置,我们一般默认all即可就行了

    optimization: {
        // 代码分割配置
        splitChunks: {
            chunks: 'all'
        }
    },

 

    optimization: {
     splitChunks: {
      chunks: 'all',
      minSize: 30000,
      minChunks: 1,
      maxAsyncRequests: 5,
      maxInitialRequests: 3,
      automaticNameDelimiter: '~',
      name: true,
      cacheGroups: {
        vendors: {
          test: /[\\/]node_modules[\\/]/,
          priority: -10,
          // filename: 'vendors.js',
        },
        default: {
          priority: -20,
          reuseExistingChunk: true,
          filename: 'common.js'
        }
      }
    }
    },

 

posted @ 2021-03-06 14:37  全情海洋  阅读(1400)  评论(0编辑  收藏  举报