前言
在前端开发中,代码拆分(Code Splitting)是一种常见的优化技术。简而言之,就是将代码分成多个小块,而不是将所有代码一次性打包在一起。这样可以确保用户访问页面时,只加载他们需要的部分代码,而不是整个应用,从而提高页面加载速度。
例如,我们的项目引入了 Vue.js
和 lodash
,如下所示:
import _ from "lodash";
import { createApp } from "vue";
import App from "./App.vue";
import "./style.css";
console.log(_);
createApp(App).mount("#app");
打包后,所有代码会被放进一个大的 JavaScript 文件中,包括我们写的 Vue 组件、lodash
和 Vue.js
。这会带来一些问题:
为什么会有问题
虽然我们的 Vue 组件代码可能会经常更新,但 Vue.js
和 lodash
这些库的代码不会频繁变化。每次我们修改 Vue 组件代码时,整个打包后的文件指纹都会重新生成,包括这些没有变化的库。这意味着每次修改都会导致浏览器重新请求整个 JavaScript 文件,即使其中大部分内容没有变化。
解决方案
所以,我们可以将不会频繁更新的公共库和框架提取出来,单独形成一个 JavaScript 文件。这么做可以减少打包的频率和大小,只在需要时更新特定的代码。
Vite.js 使用了 Rollup 作为打包工具,我们可以利用 Rollup 的 manualChunks
功能来进行手动分包。下面是一个示例:
export default defineConfig({
plugins: [vue()],
build: {
rollupOptions: {
output: {
manualChunks: {
common: ["lodash", "vue"],
},
},
},
},
});
通过这种配置,我们可以将 lodash
和 Vue.js
分成一个独立的 common.js
文件。
如果有很多第三方库怎么办?
当使用大量第三方库时,我们可以将 manualChunks
配置为一个函数,通过检查模块路径,自动决定哪些模块应该被分包。例如:
manualChunks(id) {
console.log(id)
}
这样配置后,每个被打包的文件路径都会被打印出来。通过检查路径中是否包含 node_modules
,我们可以将所有第三方库打包进一个文件:
可以看到,vite.js 打包过程中打印出了很多文件,函数每次读到一个文件都会打印出一个id,所以,我们可以通过判断 id 包不包含 node_modules,如果是第三方包那就给他单独打包成一个 JavaScript 文件。
export default defineConfig({
plugins: [vue()],
build: {
rollupOptions: {
output: {
manualChunks(id) {
if (id.includes("node_modules")) {
return "vendor";
} else {
// 不是第三方库。。。
}
},
},
},
},
});