在本文中,谷歌开发者专家 Jennifer Bland 介绍了如何应用 Webpack 减少 Vue.js 包大小的技巧,希望能给大家带来一些启发。
我在史丹利百德公司(Stanley Black&Decker,主营工业工具及安全方案)的工业 4.0 团队任职。我们的团队最近为史丹利公司分布在全球的制造工厂开发了一款相当于 App Store 的产品。我们的工厂可以访问这个软件商城并根据他们在各地生产的产品需求选择所需的应用程序。这个过程会创建一个自定义的构建,将他们选择的这些应用程序打包在一起供厂方使用。由于打包的应用程序太多了,我们生产环境上的版本 Vue 构建触发了很多体积超限警告。
我们构建的初始大小
我们处理一个构建时收到了以下两条错误消息:
Vue 建议包大小不超过 244 KiB。我们一共有 14 项 assets 的大小超限了。此外还有四个入口点的大小也超过了建议值。以下是我将构建的大小减半的具体方法。
是什么让构建包变得这么大?
首先我需要了解构建包为什么会变得这么大。为此我安装了 webpack-bundle-analyzer。它能提供包中所有项目大小的可视指南。
npminstall--save-dev webpack-bundle-analyzer
接下来我对 webpack 做了些配置,然后就能在 vue.config.js 文件中使用它了。我的 vue.config.js 文件现在是这个样子:
constBundleAnalyzerPlugin =require('webpack-bundle-analyzer').BundleAnalyzerPlugin;module.exports = {configureWebpack: {plugins: [newBundleAnalyzerPlugin()]}};
插件装好后我再次运行构建,可以看到构建包的大小是 2.48MB。从图中可以找出影响体积的罪魁祸首有:
vue-echarts
vuetify
moment
lodash
减少 Lodash 的大小
Lodash 占用了 70.74KB 的空间。我们框架中的所有应用只有两处用到了 Lodash,才两个方法就占这么多空间不太划算。
我们加载的还不止是 lodash,而且还加载了 vue-lodash。所以第一步就是从 package.json 中删除 vue-lodash,本来就用不着它。
下一步是只从 lodash 中导入我们需要的两个项目,不再加载整个库。我们使用的是 cloneDeep 和 sortBy。我换掉了之前会导入整个 lodash 库的调用:
import_from'lodash';
新的调用应该只导入我们需要的两个项目。为此我把导入目标从 lodash 改成了 lodash/core:
import{ cloneDeep, sortBy }from'lodash/core';
改动完成后,构建包大小从 2.48MB 减少到了 2.42MB。下图显示了构建的当前大小。
在这里,我们可以看到构建包中 lodash 的部分有多大。
减少 moment.js 的大小
Moment.js 在我们的包中占用了 234.36KB 的空间。查看分析视图可知,这部分数据中绝大部分是国际化语言环境,用来支持一大堆语言版本。我们根本不会使用 moment.js 的这部分功能,所以它就算是包里的无用数据了。
还好我们可以直接删除它。原来的调用会导入所有 moment.js 内容:
importmoment form'moment';
我们可以改成只导入日期操作代码,如下所示:
importmomentfrom'moment/src/moment'
做这种替换可能会出现一个问题,至少在我们的代码库中遇到了这个问题。有 18 处代码会导入 moment.js,我本可以在代码中执行全局搜索和替换的。但是如果我们向框架添加一个新的应用程序,开发人员很可能会使用默认调用来导入 moment.js,那样的话我们又会导入所有国际化语言环境了。
所以妥协方案是在 webpack 中创建一个快捷方式别名。该快捷方式将用’moment/src/moment’替换所有导入’moment’的调用。我们可以使用 resolve 在我们的 vue.config.js 文件中添加该别名并进行设置。我的 vue.config.js 文件现在变成这样。
现在运行我们的构建,可以看到包大小已经缩减到 2.22MB。
观察视图中的 moment.js,可以看到国际化区域设置完全没有加载。
删除 moment.js 中的语言环境后,每当我启动服务器运行我的代码时都会发生错误,说它无法找到./locale。经过一些研究我发现这是 moment.js 的一个存在多年的已知问题:moment.js 总是会加载 locales,还假定 locales 存在。你不能让 moment 只加载日期操作函数。
为了解决这个问题,我使用内置的 webpack IgnorePlugin 忽略了这个消息。下面是我添加到 vue.config.js 文件中的插件代码:
newwebpack.IgnorePlugin(/^\.\/locale$/,/moment$/)
减少 Vuetify.js 的大小
下一个目标是 Vuetify.js。Vuetify 占用 500.78KB 空间。一个产品就占这么多空间实在不是个小数字。
Vuetify 提供了一种他们称之为“点菜”的功能,允许你仅导入你要使用的 Vuetify 组件,从而减小 Vuetify 的体积。这里的挑战在于我们有如此多的应用程序,找出来哪些组件是完全不会被用到的也不是容易的事情。
在当前版本的 Vuetify(当我写这篇文章的时候版本为 1.56)中,他们提供了一个名为 vuetify-loader 的产品。它将遍历你的代码并找出你正在使用的所有组件,然后只将这些组件导入你的构建包。注意:vuetify v2 将内置此功能。在 v2 版本发布之前,你必须使用 vuetify-loader 来按需导入组件。Vuetify 文档提到,我们要获得所有所需的样式就要在 stylus 中导入它们。
这时我发现我们还在用旧版 vuetify.js。所以我决定先把 vuetify 升级到最新版本。我还同时安装了样式和 vuetify-loader:
npminstallvuetify vuetify-loader stylus stylus-loaderstyle-loader css-loader--save
我用来导入 Vuetify 的插件代码有一些自定义主题,可以使用我们公司的调色板。以下是我目前使用的 Vuetify 插件:
我需要将“从 Vuetify 导入”更改为“从 vuetify/lib 导入”。我还会导入 stylus 以获得所有样式。然后插件代码会变成:
最后一步是告诉 webpack 使用 vuetify-loader 插件,让它只导入我们需要的组件。我得把插件添加到插件数组里。现在 vue.config.js 文件变成这样:
之后运行构建,包大小减少为 2MB。
减少 vue-echarts 的大小
Vue-echarts 不是我包中最大的项目。Vue-echarts 运行在 echarts 之上。和 Vuetify 一样,我用的这两种产品都还是旧版本。运行下面的命令将它们升级到最新版本:
npminstallecharts vue-echarts--save
我对 vue-echarts 的 GitHub repo 做了一些研究,查看了所有已解决的问题,发现最新版本的 vue-echarts 允许你通过更改导入的内容来加载较小的包。以前我使用下面的命令导入它:
importEChartsfrom'vue-echarts';
现在我改成了这样:
importEChartsfrom'vue-echarts/components/ECharts.vue';
然后运行构建,应用包大小降至 1.28MB。
结 论
我的目标是精简生产环境上的应用包体积。一开始构建包需要 2.48MB 空间。通过一系列改动优化,构建包大小最后减少到了 1.28MB,几乎压缩了一半。
如果你要创建生产环境上的 Vue 应用程序,则应该花些时间来评估构建的体积。使用 webpack-bundle-analyzer 来确定哪些项目占用的空间最多,然后采取必要步骤来减少这些项目的大小。我通过这种方式精简了包中的四个项目。
希望你能够按照这些步骤减少构建的空间占用。非常感谢你的阅读。
原文链接:
https://www.jenniferbland.com/how-to-reduce-your-vue-js-bundle-size-with-webpack/
源网络,版权归原创者所有。如有侵权烦请告知,我们会立即删除并表示歉意。谢谢。
更多技术,欢迎关注下方公众号