項目背景
- 公司的活動項目太多,每一個項目都要單獨配置部署環境太麻煩,所以創建了一個倉庫,src/pages/下面的每一個文件夾都是是一個項目
- 優點是
* 這樣就可以使用一個git倉庫,一個jenkins配置,很方便
* 不需要多次配置域名和nginx服務 - 缺點是
* 該倉庫下的任何一個項目發布,其他的項目如果有變更也會一起發布了。這需要在發布項目前,review代碼,減少馬虎改寫了其他項目的代碼,引起不必要的線上bug
* 修改了配置文件,發布后可能會影響src/pages/下的其他的線上項目,所以修改公共文件,配置文件都要注意,可以全局搜索下該文件被哪些項目引用,如果其他地方也引用了該文件,修改該文件就要慎重且通知測試來測試這塊改動。如utils文件下的公共js,很多項目都引用了。如果修改的是這類文件,review代碼的人也需要注意這塊代碼的改動
* 針對上面的問題,其實有些公共文件可以抽取出來,放在git倉庫,使用tag引用,這樣就能減少上面的問題
項目准備
- 技術框架:vue-cli3
- 按照vue-cli3官方文檔搭建項目
- 添加vue.config.js修改打包配置,滿足多頁面打包要求
- 添加.env.development、.env.test、.env.beta、.env.production文件(環境變量)
- 修改后的框架代碼可以參考 vue-cli3-mpa-spa
- 詳細說明可以看REANDE.md里面的說明
第一版的vue.vonfig.js里面的代碼如下
let path = require('path')
let glob = require('glob')
function resolve (dir) {
return path.join(__dirname, dir)
}
let pageNum=0
//配置pages多頁面獲取當前文件夾下的html和js
function getEntry(globPath) {
let [entries,basename]=[{},'']
glob.sync(globPath).forEach(function(entry,i) {
basename = path.basename(entry, path.extname(entry));
pathname = basename; // 正確輸出js和html的路徑
let filename=entry.split('./src/pages/')[1]
let middlePath=filename.split('/index.html')[0]
let dirList=middlePath.split("/")
entries[i+'-'+dirList[dirList.length-1]] = {
entry: 'src/pages/' + middlePath + '/main.js',
template: 'src/pages/' + middlePath + '/index.html',
filename,
}
pageNum=i
})
return entries
}
let pages = getEntry('./src/pages/**/index.html');
module.exports = {
css: {
// 是否使用css分離插件 ExtractTextPlugin
extract: true,
// 開啟 CSS source maps?
sourceMap: false,
// css預設器配置項
loaderOptions: {},
// 啟用 CSS modules for all css / pre-processor files.
modules: false
},
devServer: {
disableHostCheck: true
},
chainWebpack: (config)=>{
config.resolve.alias
.set('@', resolve('src'))
.set('assets',resolve('src/assets'))
.set('components',resolve('src/components'))
.set('utils',resolve('src/utils'))
.set('api',resolve('src/api'))
},
pages
}
出現的問題
1、圖片過大,影響訪問速度,如src/pages/mpa-one/detail/App.vue里面引入的圖片,源文件是12MB,dist/img/map-one-details.png還是12MB
先看下vue-cli3默認對圖片做了哪些處理
執行npm run inspect或npm run inspectwebpack(package.json的srcipt字段里面配置的命令)
/* npm run inspect操作和npm run inspectwebpack的區別是前者將webpack文件打印在命令行里,后者將webpack文件打印在output.js(沒有該文件會自動創建並將內容寫入output.js)里面*/
/* 執行命令完成后,可以看到webapck打包文件,在module.rules里面看到關於image的配置,代碼如下,沒有做壓縮配置*/
/* config.module.rule('images') */
{
test: /\.(png|jpe?g|gif|webp)(\?.*)?$/,
use: [
/* config.module.rule('images').use('url-loader') */
{
loader: 'url-loader',
options: {
limit: 4096,
fallback: {
loader: 'file-loader',
options: {
name: 'img/[name].[hash:8].[ext]'
}
}
}
}
]
}
解決方案:
a、對於項目中的圖片(尤其是大圖片)可以使用壓縮網站先壓縮一下
b、添加圖片壓縮配置,執行npm install image-webpack-loader --save-dev,在vue.config.js里面的chainWebpack字段里添加如下配置
先在命令行安裝插件npm i image-webpack-loader --D
config.module
.rule('images')
.use('image-webpack-loader')
.loader('image-webpack-loader')
添加上述配置后再執行npm run build后看下dist里面的圖片發現從12MB降到2.88MB
將src/pages/mpa-one/detail/App.vue里面的圖片在網站上壓縮一下(從12MB到1.71MB),在src/pages/mpa-one/list/App.vue里面引入,再執行npm run build 發現從1.71MB降到1.54MB
注意圖片的引用問題
在 JavaScript 被導入或在 template/CSS 中通過相對路徑(./或../或@(別名,其他別名在vue.config.js里面添加)/)被引用。這類引用會被 webpack 處理。
放置在 public 目錄下或通過絕對路徑(/或http:xxxxx)被引用。這類資源將會直接被拷貝,而不會經過 webpack 的處理。
demo在src/mpa-one/detail/index.html
2、dist/js/chunk-vendor.js和chunk-common.js過大的問題
該問題是公司的項目中發現的,代碼就不貼出來了,vue.config.js里面的代碼是一樣的,src/pages/里面的內容不一樣,打包結果會以截圖的形式展示出來,項目里有單頁面應用也有多頁面應用,所以,下面的案例都會選這兩種案例展示說明
單頁面路由頁面(總的js大小為256.3KB)
多頁面(總的js大小為196.3KB)
可以看到這兩個項目都引入了chunk-vendor.js(177KB)和chunk-common.js(8.6KB)
chunk-vendor.js(177KB)和chunk-common.js(8.6KB)是什么?chunk-vendor.js為什么這個大?
原因:
上面的項目背景已經給大家說明了,因為這個倉庫的src/pages/下面的每一個文件夾都是一個活動項目,項目很多,vue.config.js里面除了將單頁面入口改為多頁面入口,添加了圖片壓縮,其他的打包機制都沒有修改
現有的打包機制適用單頁面應用,會將src/pages/下面所有的html頁面使用到的滿足條件的第三方的靜態資源(node_modules)打包到dist/js/chunk-vendor.js里面,和將滿足條件的除了打到chunk-vendor.js里面的其他靜態模塊(node_modules和其他的項目中的文件如utils文件資源)打到dist/js/chunk-common.js里面,最后將每個頁面剩下的js邏輯打到dist/js/xxx(頁面的名字).js每個頁面引入的是chunk-vendor.js、chunk-common.js和xxx(頁面的名字).js,如果是單頁面路由頁面,使用了路由懶加載,頁面還會有一些模塊js如(dist/js/chunk-xxx.js)。
倉庫里面放置的不是一個項目,所以隨着項目越來越大,chunk-vendor.js和chunk-common.js會越來越大,每個頁面引入的多余的代碼會越來越多,所以對於這個問題,做了多頁面打包的處理。修改內容為,將每個頁面都引入的第三方庫作為提取到dist/js/chunk-vendor.js,刪除chunk-common.js(去掉默認配置common),將每個頁面剩余的js打包到dist/js/xxx(頁面的名字).js。這樣頁面就不會引入多余的js文件了
針對這個問題,對vue.config.js的chainWebpack字段添加下面的代碼
做如下修改
// 公共資源提取,
// vendors提取的是第三方公共庫(滿足提取規則的node_modules里面的且頁面引入的),這些文件會打到dist/js/chunk-vendors.js里面
// 提取規則是每個頁面都引入的才會打到chunk-vendors.js里面(如vue.js)
// 控制條件是minChunks字段,所以該字段的值是當前activity/src/projects里面的html的個數
// common提取的應該是除了vendors提取后,剩余的滿足條件的公共靜態模塊
// 我們的項目不需要common,所以將common置為{},覆蓋默認common配置
config.optimization.splitChunks({
cacheGroups: {
vendors: {
name: 'chunk-vendors',
minChunks: pageNum,
test: /node_modules/,
priority: -10,
chunks: 'initial'
},
common: {}
}
});
再次執行打包命令
單頁面路由頁面(總的js大小為161.6KB)
多頁面(總的js大小為167.9KB)
可以看到優化后的頁面總資源大小比沒有優化之前的小了
spa頁面js(256.3KB => 161.6KB)
mpa頁面js(196.3KB => 167.9KB)
經過優化,頁面的js還是挺大的,查看項目,發現spa頁面有引入vconsole工具,用於調試的,所以配置下在生產環境不引入該工具
spa和mpa都引入了一個modal的組件(彈框),該組件里面有引入jquery,用的jquery很少,所以可以將jquery去掉,用原生的代碼實現
vconsole優化:由於每個頁面測試環境都需要引入該包用於調試,在每個頁面引入很麻煩,所以,可以在vue.config.js里面配置,代碼如下
先在命令行里面安裝npm install vconsole-webpack-plugin --save-dev
const vConsolePlugin = require('vconsole-webpack-plugin');
//開發環境
let pluginsDev = [
//移動端模擬開發者工具
new vConsolePlugin({
filter: [], // 需要過濾的入口文件
enable: true
}),
];
if(process.env.NODE_ENV !== 'production') {
config.plugins = [...config.plugins, ...pluginsDev];
}
再將頁面的jquery去掉,改用原生js寫法,再執行npm run build打包部署到服務器后
spa頁面
mpa頁面
可以看到優化后的頁面總資源大小比沒有優化之前的小了
經過上面的優化,頁面的js總資源數字如下
spa頁面js(161.6KB => 106.2KB)
mpa頁面js(167.9KB => 137.9KB)
上面兩次優化后
spa頁面js(256.3KB => 106.2KB)減少了150KB
mpa頁面js(196.3KB => 137.9KB)減少了60KB
另外訪問我們公司的集成環境和beta環境(非生產環境)發現js文件都是很大的,不是gzip包
生產環境的js不大,因為服務器配置的問題,生產環境配置了使用gzip的文件,如圖response header里面的content-encoding的值是gzip,非生產環境沒有這個字段,如果服務器配置了,是會有的
上面所述如有問題,評論里幫我指出,呃呃....第一次寫博客,寫博客也挺累的啊