18_webpack代码分离
作者:互联网
什么是代码分离
代码分离(Code Splitting)是webpack一个非常重要的特性
他主要的目的是将代码分离到不同的bundle中,之后我们可以按需加载,或者并行加载这些文件
比如默认情况下,所有的JS代码(业务代码,第三方依赖,展示没有用到的模块)在首页全部都加载
就会影响首页的加载速度
代码分离可以分出更小的bundle,以及控制资源加载优先级,提供代码的加载性能
webpack中常用的代码分离有三种
入口起点:使用entry配置手动代码分离
防止重复:使用Entry Dependencies或者SplitChunksPlugin去重和分离代码
动态导入:通过模块的内联函数调用来分离代码
Entry Dependencies(入口依赖)
入口手动分离代码
entry: { main: "./src/main.js", index: "./src/index.js", }, output: { path: resolveApp("./build"), filename: "[name].bundle.js", },
但是这样子会有缺点
如:我在main.js引入了lodash库,在index.js也引入了lodash这个库,那么webpack在打包后的index.js中有一份lodash,main.js中也有一份lodash,相当于生成了两份lodash
我们不想在打包后的每个引用第三方依赖的js文件中都把第三方的依赖都打包进去,这个时候我们就需要对第三方代码进行一个分离
entry: {
//也可以写成一个数组 main: { import: "./src/main.js", dependOn: "lodash" }, index: { import: "./src/index.js", dependOn: "lodash" }, lodash: "lodash", },
那么这个时候,lodash就会生成一个单独的js文件,webpack会通过模块化加载lodash
假如我在main和index文件又引入了dayjs第三方库的时候,我们还需要对dayjs进行分离,那么改如何设置呢?
我们可以这样设置:
entry: { main: { import: "./src/main.js", dependOn: ["lodash", "dayjs"] }, index: { import: "./src/index.js", dependOn: ["lodash", "dayjs"] }, lodash: "lodash", dayjs: "dayjs", },
也可以这样设置:
entry: { //他们两个依赖的库是一样的话可以添加一个shared属性 main: { import: "./src/main.js", dependOn: "shared" }, index: { import: "./src/index.js", dependOn: "shared" }, shared: ["lodash", "dayjs"], },
当我们build的时候会给我们生成一个LICENSE.txt文件,那么我们如何去掉呢?
const TerserPlugin = require("terser-webpack-plugin"); // 和entry同级 optimization: { minimizer: [ new TerserPlugin({ extractComments: false, }), ], },
Split Chunks
它是使用 SplitChunksPlugin来实现的
因为该插件webpack已经默认安装和集成,所以我们并不需要单独安装,直接使用该插件
只需要提供SplitChunksPlugin相关的配置信息即可
webpack提供了SplitChunksPlugin默认的配置,我们也可以手动来修改它的配置:
比如默认配置中,chunks仅仅针对于异步(async)请求,我们可以设置为initial或者all
如:我们使用import语句导入的dayjs和lodash,他们相当于是同步的,所以该插件并不会对他进行任何的分离,所以我们需要修改其中的chunks值
require()和import()就是异步加载js文件所以该插件会对导入的其js代码进行分离
optimization: { minimizer: [ new TerserPlugin({ extractComments: false, }), ], splitChunks: { // async:require,import函数 // initial:同步导入如:import语句 // all:异步/同步都支持 chunks: "all", }, },
你会发现在我们的build文件夹已经生成了一个叫xxx(数字).bundle.js文件,就已经对代码进行了一个分离
因为我们所有的分离都是使用SplitChunksPlugin来实现的,所以我们需要对它的配置有所了解
splitChunks: { // async:require,import函数 // initial:同步导入如:import语句 // all:异步/同步都支持 chunks: "all", // 最小值:默认值为:20000kb,如果我们拆分出来一个包,那么拆分出来的这个包的大小最小为minSize,如果达不到就不拆分了 // minSize的优先级大于maxSize的优先级 minSize: 2000, // 将大于maxSize的包拆分成不小于minSize的包, maxSize: 2000, // minChunks表示引入的包,至少被引入了一次 minChunks: 1, // 缓存组:b把匹配的文件打包到vendors中 // 把来自node_modules文件夹的代码(第三方库)打包到vendors中 // 当匹配到了lodash不会立即做一个输出,先缓存,等到把所有的匹配都加载完成之后,一起用filename命名的名字一起做一个输出 cacheGroups: { vendors: { test: /[\\/]node_modules[\\/]/, filename: "[id]_vendors.js", //优先级,如果vendors和default都满足的情况下,它会优先使用default priority: -20, }, /* bar: { test: /bar_/, filename: "[id]_bar.js", }, */ default: { //如果有一个文件被引用了两次,会被打包成一个单独的文件 minChunks: 2, filename: "common_[id].js", //优先级 一般是负数 priority: -10, }, }, },
这些配置我们一般都不需要进行配置的,使用默认的就好了。
动态导入(dynamic import)
另外一个代码拆分是动态导入时,webpack提供了两种实现动态导入的方式
使用ECMAScript中的import()语法来完成,也是目前推荐的方式
使用webpack遗留的require.ensure,目前已经不推荐使用
在vue中同步打包出来的文件最多的就4个
1.main.bundle.js
2.vendors_chunks.js
3.common_chunks.js
4.runtime.js
无论你的splitChunksPlugin设置的是什么,webpack都会对异步导入的代码进行分离 当我们使用import()函数动态导入,在打包的文件夹中会生成一个[id].bundle.js
打包过后的文件名字来自于哪里呢?
默认情况下如果你没有告诉他,打包过后的文件叫什么名字,它会根据output.filename来进行命名,但是我这里的filename设置的是 [name].bundle.js ,为什么我的name是一个数字,这个数字来自哪里,它来自optimization的属性中有一个叫chunkIds,他就来自这里
optimization.chunkIds配置
optimization.chunkIds配置用于告知webpack模块的id采用什么算法生成
boolean = false
string: 'natural' | 'named' | 'size' | 'total-size' | 'deterministic'
natural:使用自然数,不推荐,不利于浏览器缓存,假如我对应a.js是1_vendors.js b.js是2_vendors.js,那么我把a.js删除掉了,下次再进行打包的时候,1_vendors.js对应的就是b.js了
named:使用包所在的目录作为name(开发环境推荐)
deterministic:生成id,针对相同的文件,生成的id是不变的(默认)
一般我们的异步代码不叫xxx.bundle.js,应该是xxx.cunk.js,那么该怎么设置呢?output: { path: resolveApp("./build"), filename: "[name].bundle.js", chunkFilename: "[name].chunk.js", },但是我们就算设置了[name].chunk.js,那么它生成的文件还是id.chunk.js那么该怎么办呢?
我们可以使用我们的魔法注释(magic comments)
标签:lodash,18,代码,js,webpack,import,main 来源: https://www.cnblogs.com/Mr-Hou88888/p/16217467.html