阅读 3694

【译】如何使用webpack减少vuejs打包的大小

banner

我在Stanley Black & Decker的工业4.0团队工作。我们的团队最近为Stanley制造工厂创建了相当于App Store的产品。工厂可以访问市场并根据他们在该位置生产的产品选择他们需要的应用程序。这将构建一个自定义构建,将所有这些应用程序捆绑在一起,以便工厂运行。由于捆绑了如此众多的应用程序,我们的vue生产构建时,导致多个大小过度的警告。

我们最初的构建规模

当我们进行构建时,我们收到以下2条错误消息:

two_error

Vue建议捆版bundles不超过244KiB。我们只有14个资源,每个资源都超过这个规模。此外,我们有四个入口点也高于建议的大小。以下是我将构建的大小减半的方法。

导致大型构建包的原因是什么?

首先,我需要了解导致大型构建包大小的原因。为此,我安装了webpack-bundle-analyzer。这将提供每个包中项目大小的可视指南。

npm install --save-dev webpack-bundle-analyzer
复制代码

接下来,我在vue.config.js文件中配置webpack来使用它。下面是我的配置文件vue.config.js的内容:

const BundleAnalyzerPlugin = require('webpack-bundle-analyzer')
    .BundleAnalyzerPlugin;
    module.exports = {
        configureWebpack: {
            plugins: [new BundleAnalyzerPlugin()]
        }
   };
复制代码

安装完插件后,我再次运行构建,我可以看到我的构建大小是2.48MB。从图像中我可以看到最大的罪魁祸首是:

  • vue-echarts
  • vuetify
  • moment
  • lodash

biggest_culprits

减少Lodash的大小

Lodash占用了70.7kb的空间。Lodash仅在我们的框架中的所有应用程序中的两个位置使用。这只是两种方法的大量空间。

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。这是显示构建的当前大小的图像。

optimize_lodash_graph

在这里我们可以看到lodash本身作为构建包一部分的大小。

optimize_lodash_itself

减少moment.js的大小

Moment.js在构建包中占了234.36KB。当你查看图片的时,该大小的绝大部分是它们支持的所有语言的国际化语言环境。我们根本没有使用moment.js的这一部分,所以我们打包中包含了不必要部分。

幸运的是,我们可以删除它。而不是使下面的调用导入所有moment.js

import moment form 'moment';
复制代码

我们只能通过此调用导入日期操作代码:

import moment from 'moment/src/moment'
复制代码

至少在我们的代码库中进行替换是一个问题。有18个地方在代码中导入了moment.js。我本可以在代码中进行全局搜索和替换。但是如果我们向框架添加一个新的应用程序,开发人员很可能会使用默认调用来导入moment.js。如果他们这样做,那么我们将再次导入所有国际语言环境。

因此,权衡之后,在webpack中创建一个快捷方式的别名。该快捷方式将用moment/src/moment替换所有导入moment的调用。我们可以使用resolve和设置别名在我们的vue.config.js文件添加该别名。这是我vue.config.js现在的样子。

webpack_alia

当我们现在运行构建时,我们的捆绑包现在已经下降到2.22MB的大小了。

optimize_moment

当你查看图像的moment.js时,你将看到国际化区域设置根本不再被加载。

optimize_moment_after

通过删除moment.js中的语言环境,每当我启动服务器运行我的代码时都会发生错误,该错误代码说它无法找到./locale。在做了一些研究之后,我发现这已经成为了moment.js的一个已知好几年的问题,moment.js总是加载并假定locales是现在。你无法分辨加载日期操作功能的时刻。

要解决这个问题,我使用内置的webpack IgnorePlugin忽略此消息。这是我添加到我的vue.config.js文件中的插件代码:

new webpack.IgnorePlugin(/^\\.\\/locale$/, /moment$/)
复制代码

减少Vuetify.js的大小

我的下一个目标是Vuetify.js的大小。Vuetify占用空间500.78KB。对于一个供应商产品来说,这是一个巨大的空间。

vuetify

Vuetify提供了一种他们称之为点菜的功能。这允许你仅导入你使用的Vuetify组件。这会减少Vuetify的大小。挑战在于我们有如此多的应用程序正在进行并试图确定我们正在使用的组件不会改变。

在当前版本的Vuetify(当我写这篇文章的时候版本为1.56)中,他们提供了一个名为vuetify-loader的产品。 它将遍历你的代码并确定你正在使用的所有组件,然后将它们只导入你的构建包。 ⚠️注意:最终vuetify v2将内置此功能。 在该版本可用之前,你必须使用vuetify-loader仅导入你正在使用的组件。 Vuetify文档说明要获得所有必需的样式,我们需要在stylus中导入它们。

我意识到我们正在运行旧版本的vuetify.js。 所以我决定将我的vuetify版本升级到最新版本。我还同时安装了stylevuetify-loader

npm install vuetify vuetify-loader stylus stylus-loader style-loader css-loader --save
复制代码

我导入Vuetify的插件代码有一些主题的自定义,以使用我们公司的调色板。 以下是我目前的Vuetify插件:

current_vuetify_plugin

我需要将Vuetify的导入更改为从vuetify/lib导入。 我还将导入stylus以获得所有样式。 这是我的插件代码现在的样子:

current_vuetify_plugin02

最后一步是告诉webpack使用vuetify-loader插件,以便它只导入我们正在使用的组件。 我将需要的插件添加到插件数组。 这是我的vue.config.js文件:

current_vuetify_plugin03

现在,当我运行生产构建时,我的捆绑包大小为2MB

optimize_vuetify_after

减少vue-echarts的大小

Vue-echarts不是我捆绑中最大的项目。 Vue-echarts运行在echarts之上。 和Vuetify一样,我正在运行两种产品的旧版本。 将它们升级到最新版本我运行此命令:

npm install echarts vue-echarts --save
复制代码

我对vue-echarts GitHub repo进行了一些研究,查看所有已关闭的问题,发现最新版本的vue-echarts允许你通过更改导入的内容来加载较小的包。 以前我使用此命令导入它:

import ECharts from 'vue-echarts';
复制代码

我改成这种:

import ECharts from 'vue-echarts/components/ECharts.vue';
复制代码

现在,当我运行生产构建时,我的捆绑包大小降至1.28MB。

optimize_vue_echart

总结

我的目标是减少为我们的应用程序生产而创建的包的大小。 我的构建的初始大小是2.48MB。 通过进行一些更改,我能够将构建大小减少到1.2MB。 这几乎减少了50%

如果要创建生产环境Vue应用程序,则应该花时间来评估构建大小。 使用webpack-bundle-analyzer确定哪些项目占用的空间最多。 然后开始采取必要步骤来减少这些项目的大小。 我能够通过这种方式减少捆绑中四个最大项目的大小。

希望对你有帮助,能按照这些步骤来减少生产构建包的大小。

参考和后话

更多的内容,请戳我的博客进行了解,能留个star就更好了💨

文章分类
前端
文章标签