正确使用externals,vue工程构建性能提升67%
一、 externals的使用场景
官方解释:防止将某些 import
的包(package)打包到bundle
中,而是在运行时(runtime)再去从外部获取这些扩展依赖
换句话说:externals
配置项用来告诉Webpack
要构建的代码中使用了哪些不用被打包的模块,也就是说这些模版是外部环境提供的,Webpack
在打包时可以忽略它们
使用场景:所以说只要是用webpack构建的工程,当工程规模达到一定程度时,都有必要将体积较大的
、基本无变动
的第三方包处理为externals
,以减小入口js文件的大小
,缩短首屏加载时长
;减小依赖包体积
具体使用:很简单,两步(webpack配置声明externals,html cdn引入),如下图,更多可见官方文档
二、 为什么要使用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
体积也不小
(2)webpack-bundle-analyzer分析
// 安装
npm install --save-dev webpack-bundle-analyzer
// 引用
// 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
一致,echarts
、element-ui
、gojs
体积较大;且app.js
体积大,增长首屏时长
三、 如何使用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"
},
},
}
如何得知第三方包对应的key
,value
是啥,key
是package.json
中安装的包名,value
时包真实注册或者说暴露的全局变量的值,比如element-ui
的value
是ELEMENT
,打开elememt-ui
的源码,格式化可以看到如下,注册的值是ELEMENT
,且依赖了vue
;其他包同样思路
第三方包不直接直接使用cdn
,在node_modules
下或者cdn
上找到相关版本的包,拷贝放在public/js
目录下,入下图
入口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>
首先将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+%
,仔细看下方的依赖项可以看到其中echarts
、element-ui
体积超过1M,gojs
体积也不小
webpack-bundle-analyzer分析结果,可以看到相关包大小同vue ui
效果一致,开发环境下,app.js
体积也减小了
部署到生产环境后,可以看到下图,chunk-vendors.js的体积有
246kb
降低到41kb
,网络请求时长由3.73s
减少到185ms
- 使用
externals
之前 - 使用
externals
之后
转载自:https://juejin.cn/post/7001138300178137118