前言
项目完成,我们会将项目进行上线,同时为了提升性能,我们往往会进行一些优化处理。由于项目打包之后,会将之前所使用到的部署依赖包和项目中使用到的外部资源都打包,如果之前引入的包很多,或者引入的不必需的包,那么会增大项目的体积,从而造成用户访问的时候需要请求更多的数据才能正常的访问,不利于用户体验,所以需要对打包过程进行优化。
webpack-bundle-analyzer:查看资源树
优化cdn之前,我们需要知道自己优化的目标是啥,哪些值得我们去优化的,因此我们需要借助webpack-bundle-analyzer这样的工具帮我们分析代码
先安装插件webpack-bundle-analyzer:
npm i webpack-bundle-analyzer -D
在vue.config.js中配置使用:
// 使用webpack-bundle-analyzer分析打包
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
plugins: [new BundleAnalyzerPlugin()],
};
https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/7eb190a96d224f45bbebcd3123d12589~tplv-k3u1fbpfcp-zoom-1.image
配置完毕后打开package.json,在scripts中配置如下命令:
"analyz": "NODE_ENV=production npm_config_report=true npm run build"
这样在你npm run build的时候就会自动打开http://127.0.0.1:8888/看到生产包的文件情况了,这里我一个vue-cli创建的基础项目组成是这样的
开始优化
从刚才的打包结果可以看出,vue全家桶占据了我们生产包的大头,此时我们如果使用cdn移除这些依赖,是否就可以只保留src中的业务代码了呢?
下面我们开始尝试,思路是以下两点
添加包的排除:
这步操作的关键点是configureWebpack.externals
其形式是这样的:
module.exports = {
configureWebpack: {
externals: {
vue: 'Vue',
'vue-router': 'VueRouter',
vuex: 'Vuex'
},
},
}
这就是在告诉Webpack:请不要将这个模块注入编译后的JS文件里,对于我源代码里出现的任何import/require这个模块的语句,请将它保留。
怎么使用,根据webpack给出的标准动作(点击查看webpack/externals)。根据文档这里直接上结论:
请查看上面的例子。属性名称是vue,表示应该排除import Vue from 'vue' 中的vue模块。为了替换这个模块,Vue 的值将被用来检索一个全局的 Vue变量。换句话说,当设置为一个字符串时,它将被视为全局的(定义在上面和下面)。
这时我们重新打包操作,再看看打包分析,发现刚才的三兄弟已经没了。
但现在程序是不可运行的,因为我们已经排除了部分依赖,因此接下来我们开始下一步
添加cdn地址到index.html:
查找依赖的cdn
最常用的地址有:
通过查询我们查到了对应的cdn地址,并配置如下:
const cdn = {
css: [],
js: [
'https://cdn.jsdelivr.net/npm/vue@2.6.11/dist/vue.min.js',
'https://cdn.jsdelivr.net/npm/vue-router@3.2.0/dist/vue-router.min.js',
'https://cdn.jsdelivr.net/npm/vuex@3.4.0/dist/vuex.min.js'
]
};
这里暂时没用UI组件,所以css没有配置
将cdn参数添加到页面
chainWebpack (config) {
config.plugin('html').tap(args => {
args[0].cdn = cdn
return args
})
}
改造index.html
<% for (var i in htmlWebpackPlugin.options.cdn && htmlWebpackPlugin.options.cdn.js) { %>
<script src="<%= htmlWebpackPlugin.options.cdn.js[i] %>" preload></script>
<% } %>
<% for (var i in htmlWebpackPlugin.options.cdn && htmlWebpackPlugin.options.cdn.css) { %>
<link href="<%= htmlWebpackPlugin.options.cdn.js[i] %>" rel="stylesheet" preload></link>
<link href="<%= htmlWebpackPlugin.options.cdn.js[i] %>" rel="stylesheet"></link>
<% } %>
这样打包后就可以正常使用啦
附:
vue.config.js完整版:
const path = require('path');
const externals = {
vue: 'Vue',
'vue-router': 'VueRouter',
vuex: 'Vuex'
};
const cdn = {
css: [],
js: [
'https://cdn.jsdelivr.net/npm/vue@2.6.11/dist/vue.min.js',
'https://cdn.jsdelivr.net/npm/vue-router@3.2.0/dist/vue-router.min.js',
'https://cdn.jsdelivr.net/npm/vuex@3.4.0/dist/vuex.min.js'
]
};
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
configureWebpack: {
resolve: {
alias: {
'@': path.resolve(__dirname, './src')
}
},
externals,
plugins: [
// 开启 BundleAnalyzerPlugin
new BundleAnalyzerPlugin()
]
},
chainWebpack(config) {
config.plugin('html').tap((args) => {
args[0].cdn = cdn;
return args;
});
}
};
index.html完整版
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<link rel="icon" href="<%= BASE_URL %>favicon.ico" />
<% for (var i in htmlWebpackPlugin.options.cdn && htmlWebpackPlugin.options.cdn.css) { %>
<link href="<%= htmlWebpackPlugin.options.cdn.js[i] %>" rel="stylesheet" preload></link>
<link href="<%= htmlWebpackPlugin.options.cdn.js[i] %>" rel="stylesheet"></link>
<% } %>
<title><%= htmlWebpackPlugin.options.title %></title>
<!-- built files will be auto injected -->
<% for (var i in htmlWebpackPlugin.options.cdn && htmlWebpackPlugin.options.cdn.js) { %>
<script src="<%= htmlWebpackPlugin.options.cdn.js[i] %>" preload></script>
<% } %>
</head>
<body>
<noscript>
<strong
>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please
enable it to continue.</strong
>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>