
壓縮項(xiàng)目打包后的體積大小、提升打包速度,是前端性能優(yōu)化中非常重要的環(huán)節(jié),筆者結(jié)合工作中的實(shí)踐總結(jié),梳理出一些 ?常規(guī)且有效?
? 的性能優(yōu)化建議
(資料圖片)
技術(shù)棧: vue-cli3 + vue2 + webpack4主要插件:elementUI + echarts + axios + momentjs
目標(biāo):通過一系列的優(yōu)化方案,對比打包體積和速度的前后變化,來驗(yàn)證方案的有效性
?2.25M?
?vue 項(xiàng)目可以通過添加--report命令: ??"build": "vue-cli-service build --report"?
?,打包后 dist 目錄會生成 report.html 文件,用來分析各文件的大小
或者通過安裝 ??webpack-bundle-analyzer?
? 插件來分析,步驟如下:
1)安裝
npm install webpack-bundle-analyzer -D復(fù)制代碼
2)vue.config.js中 引入
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer").BundleAnalyzerPlugin;module.exports = { configureWebpack: { plugins: [ new BundleAnalyzerPlugin() ] }}復(fù)制代碼
3)npm run serve運(yùn)行后,在瀏覽器打開??http://127.0.0.1:8888/?
? 可以看到分析頁面
?25386ms?
?從上面的打包分析頁面中可以看到,??chunk-vendors.js?
? 體積為 ??2.21M?
?,其中最大的幾個(gè)文件都是一些公共依賴包,那么只要把這些依賴提取出來,就可以解決 chunk-vendors.js 過大的問題
可以使用 ??externals?
? 來提取這些依賴包,告訴 webpack 這些依賴是外部環(huán)境提供的,在打包時(shí)可以忽略它們,就不會再打到 chunk-vendors.js 中
1)vue.config.js 中配置:
module.exports = { configureWebpack: { externals: { vue: "Vue", "vue-router": "VueRouter", axios: "axios", echarts: "echarts" }}復(fù)制代碼
2)在 index.html 中使用 CDN 引入依賴
<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> 復(fù)制代碼
驗(yàn)證 externals 的有效性:
重新打包,最新數(shù)據(jù)如下:
打包體積:??1.12M?
?
打包速度:??18879ms?
?
使用 externals 后,包體積壓縮50%、打包速度提升26%
為什么沒有使用 externals 的方式處理組件庫呢?
externals缺點(diǎn):直接在html內(nèi)引入的,失去了按需引入的功能,只能引入組件庫完整的js和css
組件庫按需引入的原理:最終只引入指定組件和對應(yīng)的樣式
elementUI 需要借助 ??babel-plugin-component?? 插件實(shí)現(xiàn),插件的作用如下:
如按需引入 Button 組件:
import { Button } from "element-ui"Vue.component(Button.name, Button)復(fù)制代碼
編譯后的文件(自動引入 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);復(fù)制代碼
通過該插件,最終只引入指定組件和樣式,來實(shí)現(xiàn)減少組件庫體積大小
1)安裝 babel-plugin-component
npm install babel-plugin-component -D復(fù)制代碼
2)babel.config.js中引入
module.exports = { presets: ["@vue/app"], plugins: [ [ "component", { libraryName: "element-ui", styleLibraryName: "theme-chalk" } ] ]};復(fù)制代碼
驗(yàn)證組件庫按需引入的有效性:
重新打包,最新數(shù)據(jù)如下:
打包體積:??648KB?
?
打包速度:??15135ms?
?
組件庫按需引入后,包體積壓縮72%、打包速度提升40%
同時(shí) ??chunk-vendors.css?
? 的體積也有了明顯的減少,從??206KB?
?降到了??82KB?
?
原始體積:
按需引入后:
繼續(xù)分析打包文件,項(xiàng)目中使用了 momentjs,發(fā)現(xiàn)打包后有很多沒有用到的語言包
使用 ??moment-locales-webpack-plugin?
? 插件,剔除掉無用的語言包
1)安裝
npm install moment-locales-webpack-plugin -D復(fù)制代碼
2)vue.config.js 中引入
const MomentLocalesPlugin = require("moment-locales-webpack-plugin");module.exports = { configureWebpack: { plugins: [ new MomentLocalesPlugin({localesToKeep: ["zh-cn"]}) ] }}復(fù)制代碼
驗(yàn)證插件的有效性:
重新打包,最新數(shù)據(jù)如下:
打包體積:??407KB?
?
打包速度:??10505ms?
?
減小三方依賴體積后,包體積壓縮82%、打包速度提升59%
由于運(yùn)行在 Node.js 之上的 webpack 是單線程模型的,我們需要 webpack 能同一時(shí)間處理多個(gè)任務(wù),發(fā)揮多核 CPU 電腦的威力
??HappyPack?
? 就能實(shí)現(xiàn)多線程打包,它把任務(wù)分解給多個(gè)子進(jìn)程去并發(fā)的執(zhí)行,子進(jìn)程處理完后再把結(jié)果發(fā)送給主進(jìn)程,來提升打包速度
1)安裝
npm install HappyPack -D復(fù)制代碼
2)vue.config.js 中引入
const HappyPack = require("happypack");const os = require("os");// 開辟一個(gè)線程池,拿到系統(tǒng)CPU的核數(shù),happypack 將編譯工作利用所有線程const happyThreadPool = HappyPack.ThreadPool({ size: os.cpus().length });module.exports = { configureWebpack: { plugins: [ new HappyPack({ id: "happybabel", loaders: ["babel-loader"], threadPool: happyThreadPool }) ] }}復(fù)制代碼
驗(yàn)證 HappyPack 的有效性:
重新打包,最新數(shù)據(jù)如下:
打包速度:??8949ms?
?
使用HappyPack后,打包速度進(jìn)一步提升了65%
由于測試項(xiàng)目較小,打包時(shí)間縮短的不算太多。實(shí)測發(fā)現(xiàn)越是復(fù)雜的項(xiàng)目,HappyPack 對打包速度的提升越明顯
線上的項(xiàng)目,一般都會結(jié)合構(gòu)建工具 webpack 插件或服務(wù)端配置 nginx,來實(shí)現(xiàn) http 傳輸?shù)?gzip 壓縮,目的就是把服務(wù)端響應(yīng)文件的體積盡量減小,優(yōu)化返回速度
html、js、css資源,使用 gzip 后通常可以將體積壓縮70%以上
這里介紹下使用 webpack 進(jìn)行 gzip 壓縮的方式,使用 ??compression-webpack-plugin?
? 插件
1)安裝
npm install compression-webpack-plugin -D復(fù)制代碼
2)vue.config.js 中引入
const CompressionPlugin = require("compression-webpack-plugin");module.exports = { configureWebpack: { plugins: [ new CompressionPlugin({ test: /\.(js|css)(\?.*)?$/i, //需要壓縮的文件正則 threshold: 1024, //文件大小大于這個(gè)值時(shí)啟用壓縮 deleteOriginalAssets: false //壓縮后保留原文件 }) ] }}復(fù)制代碼
驗(yàn)證插件的有效性:
重新打包,原來 ??407KB?
? 的體積壓縮為 ??108KB?
?
??DllPlugin?
? 與 externals 的作用相似,都是將依賴抽離出去,節(jié)約打包時(shí)間。區(qū)別是 DllPlugin 是將依賴單獨(dú)打包,這樣以后每次只構(gòu)建業(yè)務(wù)代碼,而 externals 是將依賴轉(zhuǎn)化為 CDN 的方式引入
當(dāng)公司沒有很好的 CDN 資源或不支持 CDN 時(shí),就可以考慮使用 DllPlugin ,替換掉 externals
DllPlugin 配置流程大致分為三步:
1)創(chuàng)建 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結(jié)合使用 path: AbsPath("dist/static/[name]-manifest.json") // 輸出目錄路徑 }) ]};復(fù)制代碼
2)package.json 配置腳本
"build:dll": "webpack --config ./dll.config.js",復(fù)制代碼
3)使用 ??DllReferencePlugin?
? 將打包生成的dll文件,引用到需要的預(yù)編譯的依賴上來,并通過 ??html-webpack-tags-plugin?
? 在打包時(shí)自動插入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"] // 資源路徑 }) ] }};復(fù)制代碼
先運(yùn)行 ??npm run build:dll?
? 打包生成依賴文件,以后只用運(yùn)行 ??npm run build?
? 構(gòu)建業(yè)務(wù)代碼即可
經(jīng)過上面的一系列優(yōu)化,可以看到:
包體積由原來的2.25M
減少到 407KB
,壓縮了82%打包速度由原來的 25386ms
減少到 8949ms
,提升了65%這些方式雖然很常規(guī),但確實(shí)可以有效地提升項(xiàng)目的性能
完整項(xiàng)目:??點(diǎn)此下載??
標(biāo)簽: 最新數(shù)據(jù) 速度提升 全局變量