代码分离
就是将打包的js分离成多个js,按需加载,加载速度快,提高代码的加载性能。
Webpack中常用的代码分离:
入口起点:使用entry配置手动分离代码
防止重复:使用Entry Dependencies或者SplitChunksPlugin去重和分离代码
动态导入:通过模块的内联函数调用来分离代码
入口起点 即多入口 实现代码分离
首先将不相关的代码分离到不同文件,如 main.js、index.js
在 webpack.config.js 中配置多入口:
entry: { main: './src/main.js', index: './src/index.js' }, output: { filename: '[name].bundle.js', // 这里的 name 对应 entry 配置的 key path: resolveApp('./build') },
缺点很明显:要配置非常多的入口
Entry Dependencies(入口依赖),用的不多
比如,index.js 和 main.js 都引入了一个相同的库,如 lodash,如果用上面的打包,打包后,两个js都会有这个库的代码,重复了
去重方法:
entry: { main: {import: './src/main.js', dependOn: 'lodash'}, index: {import: './src/index.js', dependOn: 'lodash'}, lodash: 'lodash' }, output: { filename: '[name].bundle.js', // 这里的 name 对应 entry 配置的 key path: resolveApp('./build') }, // 如果有多个,写法可以是: entry: { main: {import: './src/main.js', dependOn: ['lodash', 'dayjs']}, index: {import: './src/index.js', dependOn: ['lodash', 'dayjs']}, lodash: 'lodash', dayjs: 'dayjs' }, // 或者 entry: { main: {import: './src/main.js', dependOn: 'shared'}, index: {import: './src/index.js', dependOn: 'shared'}, shared: ['lodash', 'dayjs'] },
SplitChunks,最常用的分离方式
解释:
它主要用 SplitChunksPlugin 插件来实现的,该插件在安装webpack时,已默认安装和集成,不需要单独安装和单独使用
只需要提供 SplitChunksPlugin 相关配置信息即可
SplitChunksPlugin 用法:
// index.js // 同步加载 import dayjs from 'dayjs' // 异步加载 lodash import('lodash').then(res => { }) // webpack.config.js entry: { main: './src/main.js', index: './src/index.js', }, output: { filename: '[name].bundle.js', // 这里的 name 对应 entry 配置的 key path: resolveApp('./build') }, // 优化 optimization: { // 对代码进行压缩相关设置 minimizer: [ // 去除打包时产生的txt说明文件 new TerserPlugin({ extractComments: false }) ], // SplitChunksPlugin 代码分离 splitChunks: { // async:chunks 的默认值,异步,表示只有代码异步加载库时,才会进行分离 // initial: 同步 // all:异步同步加载的库或文件,都进行分离,用法常用 chunks: 'all' } },
optimization.splitChunks 其他几个常用的值:
minSize
默认20000,即20kb,拆分出来的包的最小限制,即拆分出来的包如果小于这个值,就不进行拆分
optimization: { splitChunks: { chunks: 'all', minSize: 200000 } },
maxSize
将大于maxSize的包继续拆分,拆分成不小于minSize的包
optimization: { splitChunks: { chunks: 'all', minSize: 200000, maxSize: 1000000 } },
minChunks
表示导入的包至少被导入了几次,才会被拆分
optimization: { splitChunks: { chunks: 'all', minSize: 200000, maxSize: 1000000, minChunks: 1 } },
cacheGroups
表示将匹配到的文件,如来自node_modules,都分离成指定的文件名
optimization: { splitChunks: { chunks: 'all', minSize: 200000, maxSize: 1000000, minChunks: 1, cacheGroups: { // vendors 随便取的名字 vendors: { test: /[\\/]node_modules[\\/]/, filename: '[id]_vendors.js', priority: -10 // 优先级最高 }, // 打包自己的有规则的文件,如 bar_01.js、bar_02.js,将它们都打包成 bar 开头的文件: bar: { test: /bar_/, filename: '[id]_bar.js', priority: -20 }, // 对引入多次的文件,也打包成特殊命名的文件 default: { minChunks: 2, filename: 'common_[id].js', priority: -30 // 优先级最低 } } } },
optimization.chunkIds 配置
optimization.chunkIds配置告知webpack,打包生成的模块的id采用什么算法
optimization: { // natural:自然数,一般不用 // named: 命名,会将引入的 文件路径+文件名+后缀+output.filename配置 拼接在一起 // deterministic:根据内部算法生成的ID,而且针对相同文件,id不变,默认值 chunkIds: 'deterministic' },
output.chunkFilename
用于引入文件打包命名,区分默认文件打包命名
output: { filename: '[name].bundle.js' chunkFilename: '[name].chunk.js' }
注:这里的 [name] 就是 optimization.chunkIds 设置的id,如果相对这个 name 进行自定义,可以在引入文件时,借助魔法注释(magic comments),如:
import(/* webpackChunkName: 'foo' */'./foo').then(res => { })
使用了魔法注释,加上 output.chunkFilename,最终打包的文件名:foo.chunk.js
在router.vuejs.org,搜索懒加载,就能看到路由的推荐写法,就是使用的魔法注释