从 Vite 2.9 起,manualChunks 默认情况下不再被更改怎么办?看这里↓

一、事情起因

  • 1.1 自己0-1搭建的项目是 Vue3 + Vite(4.4.11) + pinia(2.1.7) + echarts(5.4.3), 项目打包后控制台提示了一个小警告,强迫症患者这谁受得了啊?必须盘他!
  • 1.2 仔细一看,大概的意思是 打包之后的产物 index.js 体积超过了默认的500kb,使用build.rollupOptions.output.manualChunks 来改进分块,或者通过build.chunkSizeWarningLimit 调整此警告的区块大小限制。 也就是给 build.chunkSizeWarningLimit 设置一个大一点的值,官方默认是500kb提示警告;
  • 1.3 但我猜机智的你一定想问,有没有别的方式,不让他提示这个警告,从源头上解决这个问题,要知道,不管什么项目,打包之后的体积越大,意味着上传到服务器后,网络传输时间越久,从而一定程度上影响了我们的性能,于是就有了【拆包】的说法。

二、什么是拆包/分包?

  • 2.1 分包(code-splitting)是一种优化技术,用于将应用程序的代码拆分成多个较小的包(或块)。这种技术的目的是减少初始加载时需要下载的代码量,以提高应用程序的性能和加载速度。我们这里用的Vite,Vite底层本身用的rollupjs,这边重点阐述Vite的拆包方式。在使用 build.rollupOptions.output.manualChunks 时,Rollup官方拆包方式

  • 2.2 该选项允许你创建自定义的公共 chunk。当值为对象形式时,每个属性代表一个 chunk,其中包含列出的模块及其所有依赖,除非他们已经在其他 chunk 中,否则将会是模块图(module graph)的一部分。chunk 的名称由对象属性的键决定。

javascript 复制代码
manualChunks: {  
    lodash: ['lodash']  
}  
  • 2.3 上述例子中,即使你只是使用 import get from 'lodash/get' 形式引入,Rollup 也会将 lodash 的所有模块放到一个自定义 chunk 中。

  • 2.4 当该选项值为函数形式时,每个被解析的模块都会经过该函数处理。如果函数返回字符串,那么该模块及其所有依赖将被添加到以返回字符串命名的自定义 chunk 中。例如,以下例子会创建一个命名为 vendor 的 chunk,它包含所有在 node_modules 中的依赖:

javascript 复制代码
function manualChunks(id) {  
    if (id.includes('node_modules')) {  
        return 'vendor';  
    }  
}  
  • 安装包大小分析插件,来看下你项目中那些内容占了主要的空间;
    npm install --save-dev rollup-plugin-visualizer

    或者
    yarn add --dev rollup-plugin-visualizer

  • vite.config.js 中 引入

javascript 复制代码
import { visualizer } from "rollup-plugin-visualizer";  
module.exports = {  
    plugins: [  
        visualizer({  
            open: true, // 注意这里要设置为true,否则无效  
            gzipSize: true, // 分析图生成的文件名  
            brotliSize: true, // 收集 brotli 大小并将其显示  
            filename: "stats.html", // 分析图生成的文件名  
        }),  
    ],  
};  
  • 2.5 配置完执行一下 npm run build, 项目根目录会出现一个 stats.html 的文件, 用浏览器打开可以看到,目前暂用整个项目体积最大的是echarts和ant-design-vue,接下来就是想办法把他们单独拆成一个独立的文件,并且上传到CDN上面,通过配置baseUrl, 打包结果中的 index.html 只需引入这些独立的文件即可;

三、Vite如何拆包/分包?

  • 3.1 如果是Vite 2.9以下版本,那你恭喜你,用上面Rollup官方文档配置方式即可,但是请看官方文档

  • 3.2 到 Vite2.8 时,默认的策略是将 chunk 分割为 index 和 vendor。这对一些 SPA 来说是好的策略,但是要对每一种用例目标都提供一种通用解决方案是非常困难的。从 Vite2.9 起,manualChunks 默认情况下不再被更改。你可以通过在配置文件中添加 splitVendorChunkPlugin 来继续使用 "分割 Vendor Chunk" 策略:

  • 3.3 啊这?splitVendorChunkPlugin() 是个啥?我要怎么配置?会不会比rollup官方配置更香呢?管他三七二十一,不让我用我偏用!

javascript 复制代码
build: {  
    assetsDir: "",  
    chunkSizeWarningLimit: 1500,  
    emptyOutDir: true,  
    rollupOptions: {  
        output: {  
        dir: "dist/",  
        format: "es", // es iife  
        inlineDynamicImports: false,  
        // 配置方式一:  
        // manualChunks: {  
            // echarts: ['echarts', 'echarts-wordcloud'],  
            // // echartsWordcloud: ['echarts-wordcloud'],  
            // antDesignVue: ['ant-design-vue'],  
            // vue: ['vue', 'vue-router'],  
            // axios: ['axios'],  
            // dayjs: ['dayjs'],  
            // pinia: ['pinia'],  
            // xlsx: ['xlsx', 'xlsx-js-style']  
        // },  
        // 配置方式二:  
        manualChunks(id) {  
            // 判断是否为第三方依赖,将其拆分到 vendor 中  
            if (id.includes('node_modules')) {  
                // 这里代码可以优化一下,但是我懒,我相信你一定可以的!
                if (id.includes('ant-design-vue')){  
                    return 'ant-design-vue';  
                } else if (id.includes('echarts') || id.includes('echarts-wordcloud')){  
                    return 'echarts';  
                } else if (id.includes('dayjs')){  
                    return 'dayjs';  
                } else if (id.includes('lodash-es')){  
                    return 'lodash-es';  
                } else if (id.includes('zrender')){  
                    return 'zrender';  
                } else if (id.includes('xlsx') || id.includes('xlsx-js-style')){  
                    return 'xlsx';  
                } else {  
                    return 'vendor';  
                }  
            } else {  
                return 'index';  
            } 
        },  
    },  
    plugins: [  
        cleaner({  
            targets: [  
                'dist/'  
            ]  
        }),  
    ]  
    },  
    cssCodeSplit: false,  
}  
  • 3.4 来看下打包结果,整体来看效果还不错,之前包含在 index中的 echarts、ant-design-vue、xlsx 等都已经打包到独立的文件夹;
  • 3.5 打包结果中的index中也是以link的方式引入,如果在base中配置了前缀,打包后自动上传到CDN,每次只需要上传一个index.html 和样式文件即可;
  • 3.6 分析打包结果,最大的两个第三方包 ant-desin-vue、echarts 已经变成了一个独立的文件夹,大多数情况这类第三方包是不会变的,如果放到我们的CDN或者文件服务器上,每次打包后只需要引入即可,第二次打包过滤掉这类包,这大大提升了打包速度,同时也加快了我们的网站性能!散会!
相关推荐
想退休的搬砖人1 小时前
vue选项式写法项目案例(购物车)
前端·javascript·vue.js
啥子花道2 小时前
Vue3.4 中 v-model 双向数据绑定新玩法详解
前端·javascript·vue.js
清灵xmf2 小时前
揭开 Vue 3 中大量使用 ref 的隐藏危机
前端·javascript·vue.js·ref
学习路上的小刘2 小时前
vue h5 蓝牙连接 webBluetooth API
前端·javascript·vue.js
&白帝&2 小时前
vue3常用的组件间通信
前端·javascript·vue.js
冯宝宝^3 小时前
基于mongodb+flask(Python)+vue的实验室器材管理系统
vue.js·python·flask
cc蒲公英4 小时前
Vue2+vue-office/excel 实现在线加载Excel文件预览
前端·vue.js·excel
森叶4 小时前
Electron-vue asar 局部打包优化处理方案——绕开每次npm run build 超级慢的打包问题
vue.js·electron·npm
小小竹子5 小时前
前端vue-实现富文本组件
前端·vue.js·富文本
青稞儿5 小时前
面试题高频之token无感刷新(vue3+node.js)
vue.js·node.js