前端Vue项目打包性能优化方案
Posted liyunxi
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了前端Vue项目打包性能优化方案相关的知识,希望对你有一定的参考价值。
一.前言
Vue 框架通过数据双向绑定和虚拟 DOM 技术,帮我们处理了前端开发中最脏最累的 DOM 操作部分, 我们不再需要去考虑如何操作 DOM 以及如何最高效地操作 DOM;但 Vue 项目中仍然存在项目首屏优化、Webpack 编译配置优化等问题,所以我们仍然需要去关注 Vue 项目性能方面的优化,使项目具有更高效的性能、更好的用户体验。
二.优化方案
以下将从5个方面来说明vue项目的优化解决方案
1丶路由懒加载(代码分割)
Vue 是单页面应用,可能会有很多的路由引入 ,这样使用 webpcak 打包后的文件很大,当进入首页时,加载的资源过多,页面会出现白屏的情况,不利于用户体验。如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应的组件,这样就更加高效了。这样会大大提高首屏显示的速度,但是可能其他的页面的速度就会降下来。
在官方文档中对路由懒加载的书写分成了两步:
1丶首先将异步组件定义为返回一个Promise的工厂函数(该函数返回的Promise应该是resolve组件本身)
const Foo = () =>
Promise.resolve(
/* 组件定义对象 */
)
2丶在Webpack 2 中,我们可以使用动态语法来定义代码分块点(split point):
import(\'./Foo.vue\') //返回Promise
那么将这两者结合起来,就是如何定义一个能被Webpack自动代码分割的异步组件。在路由配置中什么都不需要改变,只需要像往常一样使用Foo
:
const Foo = () => import(\'./Foo.vue\')
const router = new VueRouter(
router: [ path: \'/foo\', component: Foo ]
)
对于路由懒加载我就不进行过多的赘述了,相信各位开发者在项目中都会使用到,这一点也应该在项目开始的时候制定成一个规则,以规范项目代码。
2丶第三方插件按需加载
我们在项目中经常会需要引入第三方插件,如果我们直接引入整个插件,会导致项目的体积太大,我们可以借助 babel-plugin-component ,然后可以只引入需要的组件,以达到减小项目体积的目的。由于我在项目中使用的是element-UI,以下为项目中引入 element-ui 组件库为例。
并且在此项目中,由于最初引入element-UI时是使用的全局引入,那么在项目打包之后发现组件过大,所以就把由全局引入改为按需引入。
那么以下是讲解如何将elemen-UI组件的全局引入更改为按需引入
步骤如下:
npm安装compression-webpack-plugin插件
npm install compression-webpack-plugin -D
在 babel.config.js 配置文件中书写以下配置
module.exports =
presets: ["@vue/cli-plugin-babel/preset"],
//elementUI按需引入
plugins: [
[
"component",
libraryName: "element-ui",
styleLibraryName: "theme-chalk",
,
],
],
在目录中新建一个文件用来统一管理element-UI组件并抛出
import Vue from "vue"
//引入自己需要的组件
import
Button,
Table
from "element-ui"
//用use方法注册组件
const element =
install: Vue =>
Vue.use(Button)
Vue.use(Table)
,
//将element实例抛出
export default element
在main.js文件中将抛出的组件引入,并用use方法注册
import element from "./element"
//CSS也要一起引入
import \'element-ui/lib/theme-chalk/index.css\'
Vue.use(element)
至此就把element-UI第三方组件由全局引入改为局部引入了,下面我们来看一下修改前后的文件打包大小对比:
由此我们可以看到明显的对比,那么在项目中是推荐使用第三方插件按需引入的方式去使用,这样在我们项目进行打包的时候文件目录就会小很多,有利于我们进行项目的优化和部署。
3丶常用插件库使用CDN加速
在我们的项目中会使用到很多的第三方库,这些插件往往都是不会作更改的,所以我们可以选择将这些插件库使用CDN引入的方式,而不将这些库打包到我们的项目目录中,这里推荐一个网址可以找到你所需要的所有的插件的CDN链接
BootCDN——稳定、快速、免费的前端开源项目 CDN 加速服务
下面是如何将我们的插件包使用CDN加速的代码示例
在index.html引入我们需要CDN加速的链接
(注意:如果你的项目中使用的vue-devtools插件,请将你的vue引用文件为vue.js而并非是vue.min.js,这会造成你的devtools工具无法正常使用)
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.11/vue.min.js"></script> <script src="https://cdn.bootcdn.net/ajax/libs/vue-router/3.2.0/vue-router.min.js"></script> <script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.min.js"></script>
接下来在vue.config.js
文件修改配置,在webpack
中有个externals
,它可以忽略掉不需要打包的库,那么在新版的Vue CLI中,webpack配置被集成进了vue.config.js
中,所以我们只需要在这个文件中加上配置就好了
module.exports =
configureWebpack: config =>
config.externals =
vue: "Vue",
"vue-router": "VueRouter",
axios: "axios",
(注意:在书写键值对时,值是第三方库作者定义的名字是不可修改的,如果把值名书写错误那么控制台会直接抛出错误。
例如:
"vue-router":"vue-router" //这是错误的书写方式
"vue-router": "VueRouter" //这是正确的书写方式
当你在使用外部CDN加速时若项目抛出错误,你可以检查你的键值对的书写是否正确以此来排除你的BUG
)
4、gzip压缩
gzip 是 GNUzip 的缩写,最早用于 UNIX 系统的文件压缩。HTTP 协议上的 gzip 编码是一种用来改进 web 应用程序性能的技术,web 服务器和客户端(浏览器)必须共同支持 gzip。目前主流的浏览器,Chrome,firefox,IE等都支持该协议。常见的服务器如 Apache,Nginx,IIS 同样支持,gzip 压缩效率非常高,通常可以达到 70% 的压缩率,也就是说,如果你的网页有 30K,压缩之后就变成了 9K 左右
在项目中使用gzip压缩的方法如下
首先安装compression-webpack-plugin插件
$ npm install compression-webpack-plugin -D
然后在vue.config.js
配置文件中书写你的代码
const webpack = require("webpack")
const CompressionWebpackPlugin = require("compression-webpack-plugin")
const productionGzipExtensions = ["js", "css"]
module.exports =
configureWebpack: (config) =>
const plugins = []
//start 生成gzip压缩文件
plugins.push(
// Ignore all locale files of moment.js
new webpack.IgnorePlugin(/^\\.\\/locale$/,/moment$/),
// 配置compression-webpack-plugin压缩
new CompressionWebpackPlugin(
algorithm: "gzip",
test: new RegExp("\\\\.(" +productionGzipExtensions.join("|") + ")$"),
threshold: 10240, //对10K以上的数据进行压缩
minRatio: 0.8,
),
new webpack.optimize.LimitChunkCountPlugin(
maxChunks: 5,
minChunkSize: 100,
)
)
//end 结束生成gzip压缩文件
config.plugins = [...config.plugins, ...plugins]
以上就是开启gzip压缩的配置代码了,在使用build打包之后在dist
目录中就会出现gzip压缩文件了
5、打包不生成map文件
map文件的作用在于:项目打包后,代码都是经过压缩加密的,如果运行时报错,输出的错误信息无法准确得知是哪里的代码报错。有了map就可以像未加密的代码一样,准确的输出是哪一行哪一列有错。
那么在项目打包时我们是可以设置不生成map文件的,因为map文件会使得我们的打包文件大很多
不生成map文件配置如下:
vue.config.js:
module.exports =
productionSourceMap: false,
只需要将productionSourceMap
这个配置设置为false就可以了
三、工具推荐
可视化分析包大小
推荐一个插件工具,让你能够直观的看到自己的项目大小,这样你就能够知道自己在进行项目优化的时候可以有针对性的对某一部分进行优化啦
这个插件工具可以直接在项目中使用npm进行安装
$ npm install webpack-bundle-analyzer -D
安装此插件后在你启动项目,或者在你进行build打包命令时它会自动打开,此时你就可以直观的看到你的项目大小了
总结
好了,以上就是关于Vue项目一些打包优化解决方案了,希望能对读者们有帮助,当然对于项目优化肯定是不会只有这几个方面的,还有更多其它的优化方法各位也可以一起沟通交流。
希望各位能够给此篇文章一个收藏点赞给我更多的鼓励,谢谢各位!
前端性能优化,压缩包体积提升打包速度
项目背景
压缩项目打包后的体积大小、提升打包速度,是前端性能优化中非常重要的环节,笔者结合工作中的实践总结,梳理出一些 常规且有效
的性能优化建议
技术栈: vue-cli3 + vue2 + webpack4
主要插件:elementUI + echarts + axios + momentjs
目标: 通过一系列的优化方案,对比打包体积和速度的前后变化,来验证方案的有效性
项目初始体积与速度
- 初始体积
2.25M
vue 项目可以通过添加--report命令: "build": "vue-cli-service build --report"
,打包后 dist 目录会生成 report.html 文件,用来分析各文件的大小
或者通过安装 webpack-bundle-analyzer
插件来分析,步骤如下:
1)安装
npm install webpack-bundle-analyzer -D
复制代码
2)vue.config.js中 引入
const BundleAnalyzerPlugin = require(webpack-bundle-analyzer).BundleAnalyzerPlugin;
module.exports =
configureWebpack:
plugins: [
new BundleAnalyzerPlugin()
]
复制代码
3)npm run serve运行后,在浏览器打开http://127.0.0.1:8888/
可以看到分析页面
- 初始打包速度
25386ms
开始优化 ✈︎
1、externals 提取项目依赖
从上面的打包分析页面中可以看到,chunk-vendors.js
体积为 2.21M
,其中最大的几个文件都是一些公共依赖包,那么只要把这些依赖提取出来,就可以解决 chunk-vendors.js 过大的问题
可以使用 externals
来提取这些依赖包,告诉 webpack 这些依赖是外部环境提供的,在打包时可以忽略它们,就不会再打到 chunk-vendors.js 中
1)vue.config.js 中配置:
module.exports =
configureWebpack:
externals:
vue: Vue,
vue-router: VueRouter,
axios: axios,
echarts: echarts
复制代码
2)在 index.html 中使用 CDN 引入依赖
<body>
<script src="http://lib.baomitu.com/vue/2.6.14/vue.min.js"></script>
<script src="http://lib.baomitu.com/vue-router/3.5.1/vue-router.min.js"></script>
<script src="http://lib.baomitu.com/axios/1.2.1/axios.min.js"></script>
<script src="http://lib.baomitu.com/echarts/5.3.2/echarts.min.js"></script>
</body>
复制代码
验证 externals 的有效性:
重新打包,最新数据如下:
打包体积:1.12M
打包速度:18879ms
使用 externals 后,包体积压缩50%、打包速度提升26%
2、组件库的按需引入
为什么没有使用 externals 的方式处理组件库呢?
externals缺点:直接在html内引入的,失去了按需引入的功能,只能引入组件库完整的js和css
组件库按需引入的原理:最终只引入指定组件和对应的样式
elementUI 需要借助 babel-plugin-component 插件实现,插件的作用如下:
如按需引入 Button 组件:
import Button from element-ui
Vue.component(Button.name, Button)
复制代码
编译后的文件(自动引入 button.css):
import _Button from "element-ui/lib/button";
import _Button2 from "element-ui/lib/theme-chalk/button.css";
// base.css是公共的样式
import "element-ui/lib/theme-chalk/base.css";
Vue.component(_Button.name, _Button);
复制代码
通过该插件,最终只引入指定组件和样式,来实现减少组件库体积大小
1)安装 babel-plugin-component
npm install babel-plugin-component -D
复制代码
2)babel.config.js中引入
module.exports =
presets: [@vue/app],
plugins: [
[
component,
libraryName: element-ui,
styleLibraryName: theme-chalk
]
]
;
复制代码
验证组件库按需引入的有效性:
重新打包,最新数据如下:
打包体积:648KB
打包速度:15135ms
组件库按需引入后,包体积压缩72%、打包速度提升40%
同时 chunk-vendors.css
的体积也有了明显的减少,从206KB
降到了82KB
原始体积:
按需引入后:
3、减小三方依赖的体积
继续分析打包文件,项目中使用了 momentjs,发现打包后有很多没有用到的语言包
使用 moment-locales-webpack-plugin
插件,剔除掉无用的语言包
1)安装
npm install moment-locales-webpack-plugin -D
复制代码
2)vue.config.js 中引入
const MomentLocalesPlugin = require(moment-locales-webpack-plugin);
module.exports =
configureWebpack:
plugins: [
new MomentLocalesPlugin(localesToKeep: [zh-cn])
]
复制代码
验证插件的有效性:
重新打包,最新数据如下:
打包体积:407KB
打包速度:10505ms
减小三方依赖体积后,包体积压缩82%、打包速度提升59%
4、HappyPack 多线程打包
由于运行在 Node.js 之上的 webpack 是单线程模型的,我们需要 webpack 能同一时间处理多个任务,发挥多核 CPU 电脑的威力
HappyPack
就能实现多线程打包,它把任务分解给多个子进程去并发的执行,子进程处理完后再把结果发送给主进程,来提升打包速度
1)安装
npm install HappyPack -D
复制代码
2)vue.config.js 中引入
const HappyPack = require(happypack);
const os = require(os);
// 开辟一个线程池,拿到系统CPU的核数,happypack 将编译工作利用所有线程
const happyThreadPool = HappyPack.ThreadPool( size: os.cpus().length );
module.exports =
configureWebpack:
plugins: [
new HappyPack(
id: happybabel,
loaders: [babel-loader],
threadPool: happyThreadPool
)
]
复制代码
验证 HappyPack 的有效性:
重新打包,最新数据如下:
打包速度:8949ms
使用HappyPack后,打包速度进一步提升了65%
由于测试项目较小,打包时间缩短的不算太多。实测发现越是复杂的项目,HappyPack 对打包速度的提升越明显
5、Gzip压缩
线上的项目,一般都会结合构建工具 webpack 插件或服务端配置 nginx,来实现 http 传输的 gzip 压缩,目的就是把服务端响应文件的体积尽量减小,优化返回速度
html、js、css资源,使用 gzip 后通常可以将体积压缩70%以上
这里介绍下使用 webpack 进行 gzip 压缩的方式,使用 compression-webpack-plugin
插件
1)安装
npm install compression-webpack-plugin -D
复制代码
2)vue.config.js 中引入
const CompressionPlugin = require(compression-webpack-plugin);
module.exports =
configureWebpack:
plugins: [
new CompressionPlugin(
test: /\\.(js|css)(\\?.*)?$/i, //需要压缩的文件正则
threshold: 1024, //文件大小大于这个值时启用压缩
deleteOriginalAssets: false //压缩后保留原文件
)
]
复制代码
验证插件的有效性:
重新打包,原来 407KB
的体积压缩为 108KB
6、DllPlugin 动态链接库
DllPlugin
与 externals 的作用相似,都是将依赖抽离出去,节约打包时间。区别是 DllPlugin 是将依赖单独打包,这样以后每次只构建业务代码,而 externals 是将依赖转化为 CDN 的方式引入
当公司没有很好的 CDN 资源或不支持 CDN 时,就可以考虑使用 DllPlugin ,替换掉 externals
DllPlugin 配置流程大致分为三步:
1)创建 dll.config.js 配置文件
import DllPlugin from "webpack";
export default
// 需要抽离的依赖
entry:
vendor: ["vue", "vue-router", "axios", "echarts"]
,
mode: "production",
optimization:
splitChunks:
cacheGroups:
vendor:
chunks: "all",
name: "vendor",
test: /node_modules/
,
output:
filename: "[name].dll.js", // 输出路径和文件名称
library: "[name]", // 全局变量名称:其他模块会从此变量上获取里面模块
path: AbsPath("dist/static") // 输出目录路径
,
plugins: [
new DllPlugin(
name: "[name]", // 全局变量名称:减小搜索范围,与output.library结合使用
path: AbsPath("dist/static/[name]-manifest.json") // 输出目录路径
)
]
;
复制代码
2)package.json 配置脚本
"build:dll": "webpack --config ./dll.config.js",
复制代码
3)使用 DllReferencePlugin
将打包生成的dll文件,引用到需要的预编译的依赖上来,并通过 html-webpack-tags-plugin
在打包时自动插入dll文件
vue.config.js 配置如下
import DllReferencePlugin from "webpack";
import HtmlTagsPlugin from "html-webpack-tags-plugin";
export default
configureWebpack:
plugins: [
new DllReferencePlugin(
manifest: AbsPath("dist/static/vendor-manifest.json") // manifest文件路径
),
new HtmlTagsPlugin(
append: false, // 在生成资源后插入
publicPath: "/", // 使用公共路径
tags: ["static/vendor.dll.js"] // 资源路径
)
]
;
复制代码
先运行 npm run build:dll
打包生成依赖文件,以后只用运行 npm run build
构建业务代码即可
优化总结
经过上面的一系列优化,可以看到:
- 包体积由原来的
2.25M
减少到407KB
,压缩了82% - 打包速度由原来的
25386ms
减少到8949ms
,提升了65%
这些方式虽然很常规,但确实可以有效地提升项目的性能
完整项目:点此下载
以上是关于前端Vue项目打包性能优化方案的主要内容,如果未能解决你的问题,请参考以下文章