由一个问题引出 CodeSpliting
1.首先安装第三方库 - lodash
npm i loadsh —save
2.在index.js 中引入这个库
import _ from 'lodash';
console.log(_.join(['a','b','c'],'***'))
3.打包,发现问题
我们看打包后的main.js ,发现目前所有的业务代码 和 lodash工具代码都打包在了一起。
实际情况下,业务代码是非常多的。如果现在按照这样打包会把两者打包到一起,从代码运行层面上是没有任何问题的;
但是也有一个潜在的问题:假设 lodash 体积很大,有1MB;业务代码也有1MB;在不压缩main.js 代码的情况下,main.js 代码有2MB,如果用户访问index.js页面就需要等待 2MB 加载完后才能看到。
问题:
- 导致打包文件太大,加载时间太长,影响体验;
- 其实lodash库的代码并不怎么会变化。但是当业务代码改动后,如果用户重新访问页面的话,又必须重新加载2MB的包。根本没有必要再次加载lodash的代码。(后面会缓存这些工具代码,这样二次加载页面的时候就不会再重新加载这些工具代码了,直接从缓存中拿)
webpack中的代码分离
对于⼤的 Web 应⽤来讲,将所有的代码都放在⼀个⽂件中显然是不够有效的,特别是当你的
某些代码块是在某些特殊的时候才会被使⽤到。webpack 有⼀个功能就是将你的代码库分割成
chunks(语块),当代码运⾏到需要它们的时候再进⾏加载。
适用的场景:
将公用代码拆分出来;(例如第三方库等工具类库)(同步过程?)
联想vue:业务代码(app) 和 第三方库代码(vendor)分离 第三方库代码由于很少像本地的源代码那样频繁修改,因此可以利用浏览器的缓存来消除请求。
将业务代码拆分成一小块,等到需要的时候再加载(异步模块引入和拆分)(即动态引入,懒加载)
联想vue:业务代码分离成一块一块的,使得初始下载的代码更小
暂时没有用到的模块
代码分离的三种方式
- 入口起点:使用 entry 配置手动地分离代码;
- 防止重复:使用 Entry Dependencies(entry 配置中的 dependOn 选项 )或 splitChunksPlugin 去重和分离 chunk;
- 动态导入:通过模块的内联函数(如import)调用来分离代码。
1)多入口起点
入口起点的含义非常简单,就是配置多入口。
比如有两个文件src/main.js、src/index.js,在webpack.common.js里配置:
entry: {
main: "./src/main.js",
index: "./src/index.js"
},
output: {
path: resolveApp("./build"),
filename: "[name].bundle.js"
}
2)Entry Dependencies(入口依赖)
假如我们的index.js和main.js都依赖两个库:lodash、dayjs。
如果我们单纯的进行入口分离,那么打包后的两个bunlde都有会有一份lodash和dayjs;事实上我们可以对他们进行共享。
entry: {
main: { import: "./src/main.js", dependOn: "shared" },
index: { import: "./src/index.js", dependOn: "shared" },
lodash: "lodash",
// dayjs: "dayjs"
shared: ["lodash", "dayjs"]
}
3)splitChunksPlugin
另外一种分包的模式是splitChunk,它是使用 SplitChunksPlugin 来实现的,用于import文件或者第三方包的时候:
- 因为该插件webpack已经默认安装和集成,所以我们并不需要单独安装和直接使用该插件;只需要提供SplitChunksPlugin相关的配置信息即可。
- Webpack提供了SplitChunksPlugin默认的配置,我们也可以手动来修改它的配置。
4)动态导入(dynamic import)
最后一种代码拆分的方式是动态导入,主要是EM6中的import() 语法。