vue工程构建性能提升之externals正确使用
# 一、 externals的使用场景
官方解释:防止将某些import的包(package)打包到bundle中,而是在运行时(runtime)再去从外部获取这些扩展依赖
换句话说:externals配置项用来告诉Webpack要构建的代码中使用了哪些不用被打包的模块,也就是说这些模版是外部环境提供的,Webpack在打包时可以忽略它们
使用场景:所以说只要是用webpack构建的工程,当工程规模达到一定程度时,都有必要将体积较大的、基本无变动的第三方包处理为externals,以减小入口js文件的大小,缩短首屏加载时长;减小依赖包体积
具体使用:很简单,两步(webpack配置声明externals,html cdn引入),如下图,更多可见官方文档 https://fire-repository.oss-cn-beijing.aliyuncs.com/2024/0913/0913/1.png
# 二、 为什么要使用externals
# 1、 前提
使用到的webpack分析工具
- webpack-bundle-analyzer:使用交互式可缩放树形图可视化网页包输出文件的大小,可视化分析工具
- vue ui:vuecli3 自带的webpack分析工具(使用vuecli3搭建的项目可使用)
可使用的cdn服务商
两个工具用一个就行,都是webpack分析工具,这里介绍两种工具的用法
# 2、真实业务工程举例分析
本文的相关数据是我工作中的一个实际业务工程,用vuecli3搭建的
(1)vue ui分析 在业务工程的命令行执行vue ui,在浏览器会打开一个http://localhost:8000/,点击任务>build>执行,执行结束后
可以看到npm run build执行时间36s,资源体积10.5M,其中依赖项体积8.3M,资源占比72+%,仔细看下方的依赖项可以看到其中echarts、element-ui体积超过1M,gojs体积也不小 https://fire-repository.oss-cn-beijing.aliyuncs.com/2024/0913/0913/2.png (2)webpack-bundle-analyzer分析 js 代码解读
// 安装
npm install --save-dev webpack-bundle-analyzer
2
js 代码解读复制代码
// 引用
// vue.config.js
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
configureWebpack: {
// BundleAnalyzerPlugin只在开发环境使用
plugins: [
...[
new ...// 其他插件
],
...(process.env.NODE_ENV !== "production"
? [new BundleAnalyzerPlugin()]
: [])
],
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
启动项目,在浏览器打开http://127.0.0.1:8888/,如下,可以看到依赖包情况跟vue ui一致,echarts、element-ui、gojs体积较大;且app.js体积大,增长首屏时长 https://fire-repository.oss-cn-beijing.aliyuncs.com/2024/0913/0913/3.png
# 三、 如何使用externals
将体积较大的第三方包抽离为externals,我们这里选择处理axios,element-ui,echarts,vue,gojs
// vue.config.js
module.exports = {
publicPath,
configureWebpack: {
externals: {
axios: "axios",
"element-ui": "ELEMENT",
echarts: "echarts",
vue: "Vue",
gojs: "go"
},
},
}
2
3
4
5
6
7
8
9
10
11
12
13
14
如何得知第三方包对应的key,value是啥,key是package.json中安装的包名,value时包真实注册或者说暴露的全局变量的值,比如element-ui的value是ELEMENT,打开elememt-ui的源码,格式化可以看到如下,注册的值是ELEMENT,且依赖了vue;其他包同样思路
https://fire-repository.oss-cn-beijing.aliyuncs.com/2024/0913/0913/4.png
第三方包不直接直接使用cdn,在node_modules下或者cdn上找到相关版本的包,拷贝放在public/js目录下,入下图
https://fire-repository.oss-cn-beijing.aliyuncs.com/2024/0913/0913/5.png
入口html中CDN通过html-webpack-plugin注入的方式引入,而非以下手动直接在html中手动注入
<html>
<body id="<%= VUE_APP_NAME %>">
<div id="app"></div>
<script
type="text/javascript"
src="<%=BASE_URL%>js/vue.@2.5.21.min.js"
></script>
<script
type="text/javascript"
src="<%=BASE_URL%>js/element-ui@2.4.0.js"
></script>
...
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
首先将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;
});
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
然后在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>
2
3
4
5
6
7
8
9
10
11
12
13
# 四、externals使用效果验证
再次执行vue ui,可以看到npm run build执行时间降低为12s,缩短了24s,资源体积9M,其中依赖项体积3.8M,减少了8.3-3.8=4.5M,占比54+%,
仔细看下方的依赖项可以看到其中echarts、element-ui体积超过1M,gojs体积也不小
webpack-bundle-analyzer分析结果,可以看到相关包大小同vue ui效果一致,开发环境下,app.js体积也减小了
https://fire-repository.oss-cn-beijing.aliyuncs.com/2024/0913/0913/6.png
部署到生产环境后,可以看到下图,chunk-vendors.js的体积有246kb降低到41kb,网络请求时长由3.73s减少到185ms
https://fire-repository.oss-cn-beijing.aliyuncs.com/2024/0913/0913/7.png
使用externals之前
https://fire-repository.oss-cn-beijing.aliyuncs.com/2024/0913/0913/8.png
使用externals之后
https://fire-repository.oss-cn-beijing.aliyuncs.com/2024/0913/0913/9.png
作者:jjjona0215
链接:https://juejin.cn/post/7001138300178137118