一、背景
- 背景:為了提高頁面的加載速度、減小庫的體積,來提高用戶體驗(yàn)。
- 整體思路:減小modules的體積、壓縮圖片大小、路由懶加載等優(yōu)化
二、操作步驟
2.1 開發(fā)前的準(zhǔn)備工作
準(zhǔn)備工作
首先安裝webpack的可視化資源分析工具,命令行執(zhí)行
npm i webpack-bundle-analyzer -D
然后在vue.config.js配置中,引入插件,代碼如下:
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer')
configureWebpack: {
plugins: [
new Webpack.IgnorePlugin(/\.\/locale/, /moment/), //moment這個(gè)庫中,如果引用了./locale/目錄的內(nèi)容,就忽略掉,不會打包進(jìn)去
new BundleAnalyzerPlugin(),
]
},
最后命令行執(zhí)行
npm run build --report, 瀏覽器會自動打開分析結(jié)果,如下所示:

針對項(xiàng)目中對webpack的構(gòu)建速度和網(wǎng)站加載速度有有影響的,例出了幾個(gè)優(yōu)化方案可供參考。
三、代碼層面的優(yōu)化
3.1、關(guān)閉打包時(shí)生成的map文件
在vue.config.js文件中將productionSourceMap設(shè)置為false,再次打包便沒有了map文件
productionSourceMap: false
3.2、 圖片資源的壓縮
嚴(yán)格說來這一步不算在編碼技術(shù)范圍內(nèi),但是卻對頁面的加載速度影響很大。對于所有的圖片文件,都可以在一個(gè)叫tinypng的網(wǎng)站上去壓縮一下。網(wǎng)址:圖片壓縮地址
3.3、圖片資源懶加載
對于圖片過多的頁面,為了加速頁面加載速度,所以很多時(shí)候我們需要將頁面內(nèi)未出現(xiàn)在可視區(qū)域內(nèi)的圖片先不做加載, 等到滾動到可視區(qū)域后再去加載。這樣對于頁面加載性能上會有很大的提升,也提高了用戶體驗(yàn)。我們在項(xiàng)目中使用 Vue 的 vue-lazyload 插件:
- 安裝插件
npm install vue-lazyload --save-dev - 在入口文件 man.js 中引入并使用
import VueLazyload from 'vue-lazyload' - vue 中直接使用
Vue.use(VueLazyload) - 在 vue 文件中將 img 標(biāo)簽的 src 屬性直接改為 v-lazy ,從而將圖片顯示方式更改為懶加載顯示(vue-lazyload 的 github 地址。)
<img v-lazy="/static/img/1.png">
3.4、路由懶加載
如果我們能把不同路由對應(yīng)的組件分割成不同的代碼塊,然后當(dāng)路由被訪問的時(shí)候才加載對應(yīng)的組件,這樣就更加高效了。這樣會大大提高首屏顯示的速度,但是可能其他的頁面的速度就會降下來。
const Foo = () => import('./Foo.vue')
const router = new VueRouter({
routes: [
{ path: '/foo', component: Foo }
]
})
3.5、長列表性能優(yōu)化
Vue 會通過 Object.defineProperty 對數(shù)據(jù)進(jìn)行劫持,來實(shí)現(xiàn)視圖響應(yīng)數(shù)據(jù)的變化,然而有些時(shí)候我們的組件就是純粹的數(shù)據(jù)展示,不會有任何改變,我們就不需要 Vue 來劫持我們的數(shù)據(jù),在大量數(shù)據(jù)展示的情況下,這能夠很明顯的減少組件初始化的時(shí)間,那如何禁止 Vue 劫持我們的數(shù)據(jù)呢?可以通過 Object.freeze 方法來凍結(jié)一個(gè)對象,一旦被凍結(jié)的對象就再也不能被修改了
export default { data: () => ({ users: {} }),
async created() {
const users = await axios.get("/api/users");
this.users = Object.freeze(users);
}
};
3.6、v-for 遍歷必須為 item 添加 key,且避免同時(shí)使用 v-if
- v-for 遍歷必須為 item 添加 key
在列表數(shù)據(jù)進(jìn)行遍歷渲染時(shí),需要為每一項(xiàng) item 設(shè)置唯一 key 值,方便 Vue.js 內(nèi)部機(jī)制精準(zhǔn)找到該條列表數(shù)據(jù)。當(dāng) state 更新時(shí),新的狀態(tài)值和舊的狀態(tài)值對比,較快地定位到 diff 。
- v-for 遍歷避免同時(shí)使用 v-if
v-for 比 v-if 優(yōu)先級高,如果每一次都需要遍歷整個(gè)數(shù)組,將會影響速度,尤其是當(dāng)之需要渲染很小一部分的時(shí)候,必要情況下應(yīng)該替換成 computed 屬性。例如:
<ul>
<li v-for="user in activeUsers" :key="user.id"> {{ user.name }} </li>
</ul>
computed: {
activeUsers: function () {
return this.users.filter(function (user) { return user.isActive }) }
}
四、Webpack 層面的優(yōu)化
4.1、Webpack 對圖片進(jìn)行壓縮
在 vue 項(xiàng)目中除了可以在 webpack.base.conf.js 中 url-loader 中設(shè)置 limit 大小來對圖片處理,對小于 limit 的圖片轉(zhuǎn)化為 base64 格式,其余的不做操作。所以對有些較大的圖片資源,在請求資源的時(shí)候,加載會很慢,我們可以用 image-webpack-loader來壓縮圖片:
- 首先,安裝 image-webpack-loader
npm install image-webpack-loader --save-dev
- 然后,在
vue.config.js中進(jìn)行配置
{ test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
use:[
{
loader: 'url-loader',
options: { limit: 10000, name: utils.assetsPath('img/[name].[hash:7].[ext]') }
},
{
loader: 'image-webpack-loader',
options: { bypassOnDebug: true, }
}
]
}
4.2、減少 ES6 轉(zhuǎn)為 ES5 的冗余代碼
- 首先,安裝
babel-plugin-transform-runtime
npm install babel-plugin-transform-runtime --save-dev
- 修改
vue.config.js配置文件為
plugins: [
transform-runtime
]
4.3、針對類似UserServer多頁面工程本地?zé)岣聝?yōu)化
webpack搭建的多頁面應(yīng)用,當(dāng)項(xiàng)目大了以后,修改一個(gè)簡單的css,webpack熱更新都很慢。通過觀察可以發(fā)現(xiàn)大部分的時(shí)間都耗在94% Asset Optimization 這一步上
- 問題是出在html-webpack-plugin插件上,所以引入另一個(gè)插件html-webpack-plugin-for-multihtml
npm i html-webpack-plugin-for-multihtml--save-dev
- 在webpack.dev.conf.js文件中將html-webpack-plugin替換成html-webpack-plugin-for-multihtml
const HtmlWebpackPlugin = require('html-webpack-plugin-for-multihtml')