最近對公司商務(wù)運(yùn)營管理平臺做了部分優(yōu)化,優(yōu)化后包體積減小為原來的43%,性能有很大提升。
優(yōu)化前
原配置文件中已包含部分優(yōu)化,包括
- 使用
compression-webpack-plugin開啟gzip壓縮 - 使用
svg-sprite-loader將svg文件打包成雪碧圖 - 使用
optimization.splitChunks做代碼分割
......
在此基礎(chǔ)上仍有很大優(yōu)化空間,首先借助 webpack-bundle-analyzer 將打包后的內(nèi)容展示為方便交互的樹狀圖,我們可以很直觀的看到有哪些比較大的模塊,然后做針對性優(yōu)化。

可以看到總體為7.71M,其中node_modules占用較多,所以可進(jìn)行較明顯的構(gòu)建優(yōu)化.
CDN+external
> CDN 的工作原理是將源站的資源緩存到位于全球各地的 CDN 節(jié)點(diǎn)上,用戶請求資源時(shí),就近返回節(jié)點(diǎn)上緩存的資源,而不需要每個(gè)用戶的請求都回您的源站獲取,避免網(wǎng)絡(luò)擁塞、緩解源站壓力,保證用戶訪問資源的速度和體驗(yàn)。
可以看到打包模塊中將一些引入庫也打包進(jìn)來,這里我們可以采用引入外鏈cdn取消對較大依賴模塊的打包。
在vue.config.js中添加如圖配置

同時(shí)在public中的index.html中引入cdn鏈接

需要注意點(diǎn),在 html 中配置的 CDN 引入腳本最好要在 body 內(nèi)的最底部,因?yàn)椋?/p>
- 如果放在 body 上面或 header 內(nèi),則加載會(huì)阻塞整個(gè)頁面渲染。
- 如果放在 body 外,則會(huì)在業(yè)務(wù)代碼被加載之后加載,模塊中使用了該模塊將會(huì)報(bào)錯(cuò)
- CDN最好采用公司內(nèi)部CDN,這里使用了vue及element官網(wǎng)鏈接和服務(wù)較好的bootcdn
按需引入
很多element組件只用到了較少一部分,所以可采用按需引入
安裝插件babel-plugin-component后修改.babelrc文件
{
"presets": [],
"plugins": [
[
"component",
{
"libraryName": "element-ui",
"styleLibraryName": "theme-chalk"
}
]
]
}
在需要的地方引入,例
import { Loading } from "element-ui";
語言包優(yōu)化
某些場景下,語言包會(huì)占用整個(gè)包體積的非常大一部分。實(shí)際上庫本身的邏輯不會(huì)很大,moment 就是一個(gè)很好例子。如果是新項(xiàng)目,推薦使用dayjs替代moment,它只有2k,此處用了不影響原邏輯我們?nèi)匝佑胢oment,把不使用的語言包過濾掉,推薦使用 ContextReplacementPlugin,他可以過濾掉不使用的語言,也可以用webpack的IgnorePlugin插件

const ContextReplacementPlugin = require("webpack/lib/ContextReplacementPlugin");
config.plugin("ignore").use(new ContextReplacementPlugin(/moment[/\\]locale$/, /zh-cn$/));

過濾后僅為原來25%
去除console
日常開發(fā)為了方便調(diào)試,代碼中會(huì)有一些console,但是在生產(chǎn)環(huán)境中為了信息安全這些console是不能出現(xiàn)的,這里我們使用terser-webpack-plugin插件來去掉console。該插件通常用語代碼壓縮,有類似功能的插件還有uglifyjs-webpack-plugin,但uglifyjs-webpack-plugin缺點(diǎn)是不支持es6
安裝
npm install terser-webpack-plugin --save-dev
使用
const TerserPlugin = require("terser-webpack-plugin");
vue.config.js的configureWebpack中添加
optimization: {
minimizer: [
new TerserPlugin({
terserOptions: {
compress: {
pure_funcs: ["console.log"]
}
}
})
]
},
打包時(shí)發(fā)現(xiàn)報(bào)錯(cuò)

排查后發(fā)現(xiàn)原因是webpack和terser插件的版本差異,terser目前最新版為5.0.2,但我們項(xiàng)目中使用的事webpack4.x,所以要安裝terser插件的4.x版本,安裝后重新build正常。
在打包后的dist文件夾app.js中搜索console.log未發(fā)現(xiàn)說明生效。

壓縮圖片
項(xiàng)目中有較多小于2k的icon和小圖片可使用file-loader和url-loader處理

原理是url-loader可將小于limit的圖片轉(zhuǎn)成base64格式,大于limit的圖片由file-loader編譯
配置如下
const imagesRule = config.module.rule("images");
imagesRule.uses.clear();
imagesRule
.use("file-loader")
.loader("url-loader")
.options({
limit: 16384, // 小于2k轉(zhuǎn)長base64
fallback: {
loader: "file-loader",
options: {
outputPath: "static/img"
}
}
});
打包后包大小減少了0.2M,效果不大,但是對圖片處理更明顯的優(yōu)點(diǎn)是減少http請求以及在圖片渲染過程中的性能提升。
最終效果

以上方式可使項(xiàng)目在花費(fèi)較小時(shí)間成本的情況下讓性能有較大提升,如對性能還有更高要求,仍有很多方式可進(jìn)一步優(yōu)化。