在前端开发的世界里,性能优化是一个永恒的话题。今天,咱们就来深入聊聊externals这个神奇的配置项,它能让你的vue工程构建性能大幅提升哦。

一、externals的使用场景

(一)官方解释与理解

externals的官方解释是防止将某些import的包(package)打包到bundle中,而是在运行时(runtime)再去从外部获取这些扩展依赖。简单来说呢,externals配置项就是告诉Webpack,在构建的代码里用到了哪些模块是不用打包的,因为这些模块由外部环境提供,Webpack打包的时候就可以忽略它们啦。

(二)实际使用场景

只要是用webpack构建的工程,当工程规模发展到一定程度时,就很有必要对那些体积较大且基本无变动的第三方包进行externals处理。这样做有很多好处,比如可以减小入口js文件的大小缩短首屏加载时长,还能减小依赖包体积呢。具体操作也不难,就两步:在webpack配置里声明externals,然后在html里通过cdn引入,详细的可以查看官方文档哦。

二、为什么要使用externals

(一)前提

在分析webpack的时候,我们有两个很实用的工具可以用。

  1. webpack - bundle - analyzer:这个工具可以使用交互式可缩放树形图来可视化网页包输出文件的大小,是个很棒的可视化分析工具哦。
  2. vue ui:这是vuecli3自带的webpack分析工具,如果你的项目是用vuecli3搭建的,那就可以直接用这个工具啦。

另外,我们还有一些不错的cdn服务商可以选择,像BootCDNunpkg,只要选择其中一个就好啦。

(二)真实业务工程举例分析

这里的数据是来自于我工作中的一个实际业务工程,是用vuecli搭建的哦。

  1. vue ui分析在业务工程的命令行执行vue ui后,浏览器会打开http://localhost:8000/。点击任务>build>执行,执行结束后可以看到npm run build执行时间是36s,资源体积有10.5M,其中依赖项体积达到了8.3M,资源占比72+%。仔细看下方的依赖项,会发现像echartselement - ui体积超过了1M,gojs的体积也不小呢。
  2. webpack - bundle - analyzer分析首先要安装这个工具:
npm install --save - dev webpack - bundle - analyzer

然后在vue.config.js里引用:

// 引用
// vue.config.js
const BundleAnalyzerPlugin = require('webpack - bundle - analyzer').BundleAnalyzerPlugin;

module.exports = {
    configureWebpack: {
        // BundleAnalyzerPlugin只在开发环境使用
        plugins: [
           ...[
                new...// 其他插件
            ],
           ...(process.env.NODE_ENV!== "production"
               ? [new BundleAnalyzerPlugin()]
                : [])
        ],
    }
}

启动项目后,在浏览器打开http://127.0.0.1:8888/,就可以看到依赖包的情况啦,和vue ui分析的结果是一致的,像echartselement - uigojs体积都比较大,而且app.js体积大,这会增长首屏时长哦。

三、如何使用externals

我们以处理axioselement - uiechartsvuegojs这些包为例。

  1. vue.config.js里进行配置:
// vue.config.js
module.exports = {
    publicPath,
    configureWebpack: {
        externals: {
            axios: "axios",
            "element - ui": "ELEMENT",
            echarts: "echarts",
            vue: "Vue",
            gojs: "go"
        },
    },
}

这里的keypackage.json中安装的包名,value是包真实注册或者说暴露的全局变量的值。比如element - uivalueELEMENT,打开elememt - ui的源码,格式化就能看到注册的值是ELEMENT,而且它还依赖了vue。其他包也是同样的思路哦。

  1. 第三方包不直接使用cdn,要在node_modules下或者cdn上找到相关版本的包,拷贝放在public/js目录下。
  2. 入口html中通过html - webpack - plugin注入cdn的方式引入,而不是手动直接在html中注入。 首先要把cdn相关地址信息挂在htmlWebpackPlugin.options.cdn上(这里是vuecli3的写法,直接用webpack写法可以看htmlWebpackPlugin插件):
// vue.config.js
const appName = process.env.VUE_APP_NAME;
const publicPath = `/${appName}/`;

const cdn = {
    js: [
        `${publicPath}js/vue.@2.5.21.min.js`,
        `${publicPath}js/element - ui@2.4.0.js`,
        `${publicPath}js/axios@0.18.0.min.js`,
        `${publicPath}js/echarts@4.1.0.min.js`,
        `${publicPath}js/gojs@2.0.15.js`
    ]
};

module.exports = {
    publicPath,
    chainWebpack: config => {
        config.plugin("html").tap(args => {
            args[0].cdn = cdn;
            return args;
        });
    }
}

然后在html中这样引入(要注意vue需要在element - ui之前引入,不然会报错哦):

<html>
  <body id="<%= VUE_APP_NAME %>">
    <div id="app"></div>
    <% for (var i in htmlWebpackPlugin.options.cdn &&
    htmlWebpackPlugin.options.cdn.js) { %>
    <script
        type="text/javascript"
        src="<%= htmlWebpackPlugin.options.cdn.js[i] %>"
    ></script>
    <% } %>
  </body>
</html>

四、externals使用效果验证

再次执行vue ui,就会发现npm run build执行时间降低为12s,缩短了24s呢。资源体积变为9M,其中依赖项体积是3.8M,减少了8.3 - 3.8 = 4.5M,占比54+%。仔细看下方的依赖项,echartselement - ui体积还是超过1M,gojs体积也不小。

webpack - bundle - analyzer分析结果,可以看到相关包大小和vue ui效果一致,在开发环境下,app.js体积也减小了。

部署到生产环境后,效果更明显啦,chunk - vendors.js的体积从246kb降低到41kb,网络请求时长由3.73s减少到185ms

总之,externals这个配置项在vue工程构建性能优化方面真的是非常有用的,大家可以在自己的项目里尝试一下哦。