Skip to content

Vite.js 手动分包

Published:

前言

在前端开发中,代码拆分(Code Splitting)是一种常见的优化技术。简而言之,就是将代码分成多个小块,而不是将所有代码一次性打包在一起。这样可以确保用户访问页面时,只加载他们需要的部分代码,而不是整个应用,从而提高页面加载速度。

例如,我们的项目引入了 Vue.jslodash,如下所示:

import _ from "lodash";
import { createApp } from "vue";
import App from "./App.vue";
import "./style.css";

console.log(_);
createApp(App).mount("#app");

打包后,所有代码会被放进一个大的 JavaScript 文件中,包括我们写的 Vue 组件、lodashVue.js。这会带来一些问题:

为什么会有问题

虽然我们的 Vue 组件代码可能会经常更新,但 Vue.jslodash 这些库的代码不会频繁变化。每次我们修改 Vue 组件代码时,整个打包后的文件指纹都会重新生成,包括这些没有变化的库。这意味着每次修改都会导致浏览器重新请求整个 JavaScript 文件,即使其中大部分内容没有变化。

解决方案

所以,我们可以将不会频繁更新的公共库和框架提取出来,单独形成一个 JavaScript 文件。这么做可以减少打包的频率和大小,只在需要时更新特定的代码。

Vite.js 使用了 Rollup 作为打包工具,我们可以利用 Rollup 的 manualChunks 功能来进行手动分包。下面是一个示例:

export default defineConfig({
  plugins: [vue()],
  build: {
    rollupOptions: {
      output: {
        manualChunks: {
          common: ["lodash", "vue"],
        },
      },
    },
  },
});

通过这种配置,我们可以将 lodashVue.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 {
            // 不是第三方库。。。
          }
        },
      },
    },
  },
});

参考资料