🧑💻 寫在開頭
點贊 + 收藏 === 學會🤣🤣🤣
有一天,甲方打開一個後台管理的項目,説有點卡,不太滿意,項目經理叫我優化,重新打包一下。
從輸入地址 到 展示 首屏,最佳時間在 3秒內,否則,甲方掛臉,咱就有可能有被裁的風險,understand?
廢話不多説,先來看一下怎麼個優化法吧。
優化
✅ cdn
分析
用Webpack Bundle Analyzer分析依賴,安裝webpack-bundle-analyzer打包分析插件:
# NPM
npm install --save-dev webpack-bundle-analyzer
# Yarn
yarn add -D webpack-bundle-analyzer
反正都是裝,看着來。
配一下:
// vue.config.js 文件裏。(沒有就要新建一下)
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
plugins: [
new BundleAnalyzerPlugin()
]
}
打包
執行打包命令並查看分析
npm run build --report
打包結束後,會在項目根目錄下生成dist文件。自動跳到127.0.0.1:8888(沒有跳的話,手動打開dist文件夾下的report.html),這個網址就是打包分析報告。
佔得比較大的塊,就是Element UI組件庫和echarts庫佔的空間比相對較大。
這就要考慮,第一,要按需,要啥再用啥,不要一股腦啥都裝。按需安裝,按需加載。
第二,考慮單獨引入這些組件庫的cdn,這樣速度也會咔咔提升。
詳細講一下怎麼搞cdn。
按需大家都知道,要啥再引入啥,再裝啥。
比如element-ui,我要uninstall掉,然後呢,去引入cdn,不要裝庫了,用cdn。
去package.json裏面看element-ui裝了啥版本,然後看完之後,就npm uninstall element-ui卸載掉。
去cdn庫裏面去找https://www.staticfile.org/,(首先先説一下,要找免費的開放的那種,因為一般有的公司沒有自家的cdn,沒有自家的桶,有的話,直接把js文件地址拖上去,然後得到一個地址,這樣也安全,也方便,但沒有的話另説)。
然後去
樣式庫: https://cdn.staticfile.org/element-ui/2.15.12/theme-chalk/index.min.css
組件庫:https://cdn.staticfile.org/element-ui/2.15.12/index.min.js
public/index.html入口文件中,去加入這個東西,像咱以前寫原生一樣引入就好,body裏面引入js,head裏面引入css。:
<head> <link rel="stylesheet" href="https://cdn.staticfile.org/element-ui/2.15.12/theme-chalk/index.min.css"> </head> <body> <script src="https://cdn.staticfile.org/element-ui/2.15.12/index.min.js"></script> </body>
所以這樣子,就引入好了。接着在main.js裏面,把之前import的所有element的樣式刪掉。
接着,vue.config.js的configureWebpack加個externals字段:
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
plugins: [
new BundleAnalyzerPlugin()
],
externals: {
'element-ui': 'ELEMENT' // key 是之前install下下來的包名,element-ui。value是全局變量名(ELEMENT)
}
}
externals: Webpack 的 externals 配置用於聲明某些依賴應該從外部獲取,而不是打包到最終的 bundle 中。這樣可以減小打包體積,前提是這些依賴已經在運行環境中存在。
'element-ui': 'ELEMENT' 的含義
- 當你的代碼中
import 'element-ui'時,Webpack 不會打包element-ui,而是會從全局變量ELEMENT中獲取它。 ELEMENT是element-ui庫通過<script>標籤引入時,在全局(window)中暴露的變量名。
例如,如果你在 HTML 中這樣引入:
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
- 那麼
element-ui會掛載到window.ELEMENT上。
為什麼這樣配置?
- 通常是為了通過 CDN 引入
element-ui(而不是打包它),從而優化構建速度和體積。 - 你需要確保在 HTML 中通過
<script>提前加載了element-ui,否則運行時ELEMENT會是undefined。
<!-- HTML 中通過 CDN 引入 element-ui --> <script src="https://unpkg.com/element-ui/lib/index.js"></script>
// webpack.config.js
module.exports = {
externals: {
'element-ui': 'ELEMENT' // 告訴 Webpack:import 'element-ui' 時,返回全局的 ELEMENT
}
};
// 你的代碼中依然可以正常 import(但實際用的是全局變量) import ElementUI from 'element-ui'; // 相當於:const ElementUI = window.ELEMENT;
注意事項:
- 確保全局變量名(
ELEMENT)和element-ui的 CDN 版本一致。不同版本的庫可能有不同的全局變量名。 - 如果使用模塊化打包(如 npm + Webpack 全量打包),則不需要配置
externals。
這裏有的夥伴就説,我咋知道是ELEMENT,而不是element呢。
這裏是這麼找的:
直接在瀏覽器控制枱檢查 在 HTML 中通過 CDN 引入該庫:
<script src="https://cdn.staticfile.org/element-ui/2.15.12/index.min.js"></script>
console.log(window);
然後查找可能的全局變量名(如 ELEMENT、ElementUI 等)。
cdn配置之後,重新分析
npm run build --report
重新用cdn的去分析,
那麼就很舒服了,也因此,這個就是cdn優化的方法。
✅ nginx gzip壓縮
server {
listen 8103;
server_name ************;
# 開啓gzip
gzip on;
# 進行壓縮的文件類型。
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
# 是否在http header中添加Vary: Accept-Encoding,建議開啓
gzip_vary on;
}
✅vue gzip壓
安包:npm i compression-webpack-plugin@1.1.12 --save-dev
注意版本匹配問題。
vue配置,這段配置是 Webpack 構建中關於 Gzip 壓縮 的設置,位於 config/index.js 文件中。:
//文件路徑 config --> index.js
build: {
productionGzip: true, // 啓用生產環境的 Gzip 壓縮
productionGzipExtensions: ['js', 'css'], // 需要壓縮的文件類型
}
productionGzip: true
- 作用:開啓 Gzip 壓縮,減少靜態資源(JS、CSS)的體積,提升頁面加載速度。
- 要求:需要安裝
compression-webpack-plugin(如註釋所述)。
npm install --save-dev compression-webpack-plugin
-
productionGzipExtensions: ['js', 'css']- 指定需要壓縮的文件擴展名(默認壓縮 JS 和 CSS 文件)。
為什麼需要 Gzip?
- 優化性能:Gzip 壓縮後的資源體積可減少 60%~70%,顯著降低網絡傳輸時間。
- 服務器支持:大多數現代服務器(如 Nginx、Netlify)會自動對靜態資源進行 Gzip 壓縮,但本地構建時提前生成
.gz文件可以避免服務器實時壓縮的開銷。
✅ 按需加載路由
路由級代碼分割(動態導入)
// 原寫法 import About from './views/About.vue' // 優化後寫法 const About = () => import(/* webpackChunkName: "about" */ './views/About.vue')
- 首頁只加載核心代碼(home路由)
- about模塊會在用户點擊about路由時才加載
- 顯著減少首屏加載資源體積
✅ 合理配置 prefetch策略
// vue.config.js
module.exports = {
chainWebpack: config => {
// 移除prefetch插件
config.plugins.delete('prefetch')
// 或者更精細控制
config.plugin('prefetch').tap(options => {
options[0].fileBlacklist = options[0].fileBlacklist || []
options[0].fileBlacklist.push(/myasyncRoute(.)+?\.js$/)
return options
})
}
}
- 禁用prefetch:減少不必要的帶寬消耗,但可能增加後續路由切換等待時間
- 啓用prefetch:利用瀏覽器空閒時間預加載,提升用户體驗但可能浪費帶寬
- 折中方案:只對關鍵路由或高概率訪問的路由啓用prefetch
✅ splitChunks 將node_modules中的依賴單獨打包
拆分vendor:將node_modules中的依賴單獨打包
config.optimization.splitChunks({
chunks: 'all',
cacheGroups: {
vendors: {
name: 'chunk-vendors',
test: /[\\/]node_modules[\\/]/,
priority: -10,
chunks: 'initial'
}
}
})
✅ 按需引入 lodash
import debounce from 'lodash/debounce'