本教程是針對vue-cli3以上的版本,其實原理都大同小異,這個demo為vue-cli直接創建的項目,並在main.js中引入了
echart
、element-ui
、lodash
首先看demo打包后生成的文件大小,這個demo里面什么業務都沒寫、僅僅引入了幾個包,chunk-vendors.js就達到了1.6M之多,如果是寫入了龐大的業務后沒做任何優化處理,那么這個文件可能會達到10M之多,這發生在我真實的項目經歷中
借助webpack-bundle-analyzer幫助分析
首先安裝webpack-bundle-analyzer
yarn add webpack-bundle-analyzer -D
然后在項目根目錄創建vue.config.js,然后在文件中寫入以下代碼
const WebpackBundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
module.exports = {
configureWebpack: {
plugins: [new WebpackBundleAnalyzerPlugin()]
}
}
然后執行yarn build
在瀏覽器會自動打開我們的使用包分析文件,大致如下圖的樣子
我們可以看到生成的最大文件為chunk-vendors.js
,這個文件主要又由echarts
、element-ui
、lodash
、zrender
組成,其中echarts
、element-ui
、lodash
為我們項目開發時必要引入的文件,所以我們如果把這寫文件分離出來那么文件自然就會小了很多
如何分離這些文件
我們可以借助wepack配置項里面的externals
來達到目的,在vue.config.js
里面加入如下代碼
module.exports = {
// ... other code
configureWebpack: {
// ... other code
externals: {
"lodash": '_',
"vue": 'Vue',
"echarts": 'echarts',
"element-ui": 'ELEMENT',
},
// ... other code
}
// ... other code
}
externals 配置選項提供了「從輸出的 bundle 中排除依賴」的方法。我們可以通過script標簽引入這些資源,具體關於externals的介紹請點擊這里
然后我們再對應的public -> index.html
文件加入以下代碼,其中BASE_URL指的是public目錄,你需要從官網下載對應的資源放在對應的目錄下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title>optimize_vue</title>
</head>
<body>
<noscript>
<strong>We're sorry but optimize_vue doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
<script src="<%= BASE_URL %>js/pace.min.js"></script>
<script src="<%= BASE_URL + (process.env.NODE_ENV === 'development' ? 'js/vue-2.6.0.js' : 'js/vue-2.6.0.min.js') %>"></script>
<script src="<%= BASE_URL %>js/element-ui-2.11.1.js"></script>
<script src="<%= BASE_URL %>js/lodash.min.js"></script>
<script src="<%= BASE_URL %>js/echarts.min-4.4.0.js"></script>
</body>
</html>
然后我們再看一下效果, lodash、echarts、elementui
已經成功從webpack bundle分離出去了,打包后的chunk-vendors.js
也只有24kb的大小
使用路由懶加載
路由懶加載會只加載當前頁面需要的資源,代碼如下
const Foo = () => Promise.resolve({ /* 組件定義對象 */ })
// or
const Foo = () => import(/* webpackChunkName: "group-foo" */ './Foo.vue')
const Bar = () => import(/* webpackChunkName: "group-foo" */ './Bar.vue')
const Baz = () => import(/* webpackChunkName: "group-foo" */ './Baz.vue')
注意如果使用import方式的引入需要安裝@babel/plugin-syntax-dynamic-import
,然后在babel.config.js中加入下面代碼即可
module.exports = {
// ... other code
"plugins": ["@babel/plugin-syntax-dynamic-import"]
// ... other code
}
關於process.env.NODE_ENV
相信大家在開發的時候一定會有跟多個開發環境,比如development/feature/sandbox/production,因為這玩意我真是吃了大虧,剛開始沒看文檔, 直接在執行package.json的script命令的時候通過cross-env NODE_ENV=xxx 來修改環境變量,導致無法使用vue-cli工具為我們提供的代碼優化功能
注意: process.env_NODE_ENV的值只能為development
、production
,不要修改為其他值,不然可能會出現其他問題,如果你真的想在不同的環境使用不同的接口地址或者、其他的內容我們可以用vue-cli為我們提供的--mode
達到目的,比如
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"build:sanbox": "vue-cli-service build --mode sanbox",
"build:feature": "vue-cli-service build --mode feature",
"lint": "vue-cli-service lint",
"precommit": "yarn lint"
}
這里vue-cli會讀取項目根目錄下的.env/.env./.env..local相關文件***
指的是--mode的值,--mode會修改process.env.NODE_ENV的值,我們需要再對應的env里面把NODE_ENV改寫回來,比如一個.env.sanbox
環境代碼如下
NODE_ENV=production
VUE_APP_ENV=sanbox
當我們執行yarn build:sanbox
的時候就會加載這個文件,我們可以通過process.env.VUE_APP_ENV
來訪問對應設置的值,注意只有VIE_APP_
前綴的環境變量才會被webpack.DefinePlugin
靜態嵌入到客戶端側的包中。
比如我們需要不同的構建命令構建不同的的publicPath的時候我們可以這樣做
const map = {
production: '/',
feature: '/feature',
sanbox: '/sanbox',
development: '/development',
}
const env = process.env.VUE_APP_ENV
const publicPath = map[env]
const PATH = require('path')
const WebpackBundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
module.exports = {
publicPath,
configureWebpack: {
externals: {
"lodash": '_',
"qiniu": 'qiniu',
"vue": 'Vue',
"echarts": 'echarts',
"element-ui": 'ELEMENT',
},
resolve: {
extensions: ['.js', '.vue', '.json', '.ts', '.tsx'],
alias: {
'$root': PATH.resolve(__dirname)
}
},
plugins: [new WebpackBundleAnalyzerPlugin()]
}
}
到這里就所有功能大功告成了,可以美滋滋的去喝一杯咖啡了。