vue-cli 打包優(yōu)化

01-performance項(xiàng)目

vue-cli 搭建項(xiàng)目

  1. 查看 vue-cli 版本:vue -V

報(bào)錯(cuò)或者說(shuō)不存在 vue 命令:安裝 vue-cli:npm install -g @vue/cli

  1. 創(chuàng)建項(xiàng)目:vue create 01-performance
Vue CLI v5.0.8
? Please pick a preset: Manually select features
? Check the features needed for your project: Babel, Router, Vuex, CSS Pre-processors, Linter
? Choose a version of Vue.js that you want to start the project with 3.x
? Use history mode for router? (Requires proper server setup for index fallback in production) Yes
? Pick a CSS pre-processor (PostCSS, Autoprefixer and CSS Modules are supported by default): Sass/SCSS (with dart-
? Pick a linter / formatter config: Standard
? Pick additional lint features: Lint on save
? Where do you prefer placing config for Babel, ESLint, etc.? In dedicated config files
? Save this as a preset for future projects? No
? Pick the package manager to use when installing dependencies: NPM
  1. 運(yùn)行項(xiàng)目:cd 01-performance烂翰,npm run serve

安裝 axios

  1. npm i --save axios

報(bào)錯(cuò):npm ERR! code ERESOLVE npm ERR! ERESOLVE could not resolve

原因:npm 不同版本庫(kù)之間命令不兼容

解決:npm i --save axios --legacy-peer-deps

數(shù)據(jù)懶加載(DataLazy.vue)

該功能一共被分為三個(gè)階段:

  1. 不獲取數(shù)據(jù)

  2. 用戶將要看到(使用 IntersectionObserver玉掸,或 useIntersectionObserver 進(jìn)行判斷)

  3. 獲取數(shù)據(jù)并渲染(在視圖元素可見時(shí),再獲取數(shù)據(jù))

IntersectionObserver

作用:監(jiān)聽某個(gè)視窗是否被用戶看見

// IntersectionObserver為 JS 的原生api璧榄,可直接使用
const box3Target = ref(null)
onMounted(() => {
    const intersectionObserver = new IntersectionObserver((entries) => {
        if (entries[0].intersectionRatio <= 0) {
            return console.log('當(dāng)前試圖不可見')
        }
        console.log('當(dāng)前視圖可見')

        // TODO 獲取數(shù)據(jù)
    })
    // box3Target.value:被監(jiān)聽的元素對(duì)象
    intersectionObserver.observe(box3Target.value)
})

useIntersectionObserver

vue 的工具庫(kù) vueuse 提供的一個(gè)基于 IntersectionObserver 的封裝方法业筏,需安裝npm i --save @vueuse/core

報(bào)錯(cuò):npm ERR! code ERESOLVE npm ERR! ERESOLVE could not resolve

原因:npm 不同版本庫(kù)之間命令不兼容

解決:npm i --save @vueuse/core --legacy-peer-deps

import { useIntersectionObserver } from '@vueuse/core'
const box3Target = ref(null)
onMounted(() => {
    const { stop } = useIntersectionObserver(
        box3Target,
        ([{ isIntersecting }]) => {
            if (isIntersecting) {
                console.log('當(dāng)前視圖可見')

                // TODO 獲取數(shù)據(jù)

                // 觸發(fā) stop黔攒,監(jiān)聽停止
                stop()
            } else {
                console.log('當(dāng)前試圖不可見')
            }
        }
    )
})

圖片懶加載(ImgLazy.vue)

使用 <b>自定義指令</b> 實(shí)現(xiàn)圖片懶加載

通過(guò) vue3 的 app.directive 完成 <b>自定義指令</b>

步驟:

  1. 構(gòu)建自定義指令

  2. 利用 IntersectionObserver旨巷,或 useIntersectionObserver 完成監(jiān)聽

// 01-performance\src\directive\index.js
import { useIntersectionObserver } from '@vueuse/core'

const imgLazy = {
    // mounted: 在綁定元素的父組件及他自己的所有子節(jié)點(diǎn)都掛載完成后調(diào)用
    // el: 調(diào)用該指令的元素
    mounted(el) {
        // 圖片懶加載:一開始不加載,等到將要看到時(shí)再加載
        // 1. 緩存當(dāng)前的圖片路徑
        const catchSrc = el.src
        console.log(catchSrc)
        // 2. 把 img.src 變?yōu)檎嘉粓D
        el.src = 'https://res.lgdsunday.club/img-load.png'
        // 3. 使用 useIntersectionObserver 監(jiān)聽 el 將要被看到
        const { stop } = useIntersectionObserver(el, ([{ isIntersecting }]) => {
            if (isIntersecting) {
                // 4. 渲染圖片
                el.src = catchSrc
                // 5. 停止監(jiān)聽
                stop()
            }
        })
    }
}
export default {
    // app.use 的方式使用
    install: (app) => {
        app.directive('imglazy', imgLazy)
    }
}

// 01-performance\src\main.js
import directive from './directive'
app.use(directive)
<!-- 01-performance\src\views\ImgLazy.vue -->
<!-- v-imglazy: 自定義指令imglazy -->
<img :src="item.path" alt="" class="item-img" v-imglazy />

解決打包體積過(guò)大

例子:安裝并使用了 xlsx 和 echarts 后尿赚,打包結(jié)果如下:

warning

asset size limit: The following asset(s) exceed the recommended size limit (244 KiB).
This can impact web performance.
Assets:
  js/chunk-vendors.bd8f41b3.js (1.55 MiB)

warning

entrypoint size limit: The following entrypoint(s) combined asset size exceeds the recommended limit (244 ct web performance.
Entrypoints:
  app (1.56 MiB)
      js/chunk-vendors.bd8f41b3.js
      js/app.f9f8599c.js

File                                 Size                                      Gzipped
dist\js\chunk-vendors.bd8f41b3.js    1591.84 KiB                               522.06 KiB
dist\js\67.24f04139.js               37.50 KiB                                 14.77 KiB
dist\js\app.f9f8599c.js              5.74 KiB                                  2.61 KiB
dist\js\546.4ca973ee.js              2.26 KiB                                  0.86 KiB
dist\js\816.5c4d75f2.js              1.02 KiB                                  0.59 KiB
dist\css\546.2e47b4de.css            0.76 KiB                                  0.30 KiB
dist\css\816.5617b692.css            0.75 KiB                                  0.32 KiB

步驟:

  1. 分析包體積過(guò)大的主要原因

1.1 命令 vue-cli-service build --report散庶,打包的同時(shí)生成 dist\report.html 以幫助分析包內(nèi)容

// 01-performance\package.json
{
    "scripts": {
        "report": "vue-cli-service build --report"
    }
}

1.2 查看 dist\report.html 可看到最大的占比為 echarts 和 xslx蕉堰,即包體積過(guò)大的主要原因

  1. 使用 webpack5 的 externals 配置選項(xiàng),排除體積過(guò)大的包
// 01-performance\vue.config.js
// @vue/cli-service 集成了webpack的配置
const { defineConfig } = require('@vue/cli-service')

let externals = {}
// 排除打包悲龟,只需要在 build 排除
const isProd = process.env.NODE_ENV === 'production'
if (isProd) {
    externals = {
        xlsx: 'xlsx',
        echarts: 'echarts'
    }
}

module.exports = defineConfig({
    transpileDependencies: true,
    // 調(diào)整webpack配置
    // 對(duì)象:會(huì)被 webpack-merge 合并入最終的 webpack 配置
    configureWebpack: {
        externals: externals
    },
})

重新打包后的結(jié)果如下:

 WARNING  Compiled with 1 warning                                                                          14:22:38

[eslint]
D:\Study\前端\05-性能優(yōu)化\01-performance\src\views\DataLazy.vue
  44:3  warning  Unexpected console statement  no-console
  51:3  warning  Unexpected console statement  no-console
  59:3  warning  Unexpected console statement  no-console
  79:9  warning  Unexpected console statement  no-console
  85:9  warning  Unexpected console statement  no-console

D:\Study\前端\05-性能優(yōu)化\01-performance\src\views\HomeView.vue
  14:3  warning  Unexpected console statement  no-console
  15:3  warning  Unexpected console statement  no-console

D:\Study\前端\05-性能優(yōu)化\01-performance\src\views\ImgLazy.vue
  7:3  warning  Unexpected console statement  no-console

? 8 problems (0 errors, 8 warnings)


You may use special comments to disable some warnings.
Use // eslint-disable-next-line to ignore the next line.
Use /* eslint-disable */ to ignore all warnings in a file.

File                                 Size                                 Gzipped
dist\js\chunk-vendors.8c4522c4.js    146.95 KiB                           51.96 KiB
dist\js\67.e0736f3f.js               37.71 KiB                            14.86 KiB
dist\js\app.8c52ff36.js              5.74 KiB                             2.61 KiB
dist\js\546.4ca973ee.js              2.26 KiB                             0.86 KiB
dist\js\816.5c4d75f2.js              1.02 KiB                             0.59 KiB
dist\css\546.2e47b4de.css            0.76 KiB                             0.30 KiB
dist\css\816.5617b692.css            0.75 KiB                             0.32 KiB
  1. 運(yùn)行此時(shí)的打包文件屋讶,會(huì)得到錯(cuò)誤:
Uncaught ReferenceError: XLSX is not defined

可以利用第三方 anywhere 運(yùn)行打包之后的項(xiàng)目

  1. 安裝: npm i -g anywhere
  2. 在 dist 目錄下,執(zhí)行終端命令: anywhere
  3. 會(huì)自動(dòng)啟動(dòng)服務(wù)
  1. 使用 CDN 引入被 webpack 排除的包须教,利用 vue-cli 默認(rèn)配置的 HtmlWebpackPlugin 攜帶屬性的特性皿渗,添加 CDN
// 01-performance\vue.config.js
const { defineConfig } = require('@vue/cli-service')

let cdnJS = []
// 排除打包,只需要在 build 排除
const isProd = process.env.NODE_ENV === 'production'
if (isProd) {
    cdnJS = [
            'https://unpkg.com/echarts@5.5.1/dist/echarts.js',
      'https://unpkg.com/xlsx@0.18.5/dist/xlsx.full.min.js'
        ]
}

module.exports = defineConfig({
    transpileDependencies: true,    
    // 允許對(duì)內(nèi)部的 webpack 配置進(jìn)行更細(xì)粒度的修改
    chainWebpack(config) {
        // 修改插件選項(xiàng)
        // config.plugin('html'):獲取到HtmlWebpackPlugin
        // tap():修改參數(shù)
        config.plugin('html').tap((args) => {
            // 攜帶指定的屬性到 HtmlWebpackPlugin
            args[0].cdnJS = cdnJS
            return args
        })
    }
})
<!-- 01-performance\public\index.html -->
<!DOCTYPE html>
<html lang="">
  <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" />
    <!-- 請(qǐng)求不添加請(qǐng)求來(lái)源轻腺,解決403錯(cuò)誤 -->
    <meta name="referrer" content="no-referrer" />
    <title>
      <!-- 從 htmlWebpackPlugin 配置項(xiàng)中獲取 title 屬性 --> <%=
      htmlWebpackPlugin.options.title %>
    </title>
    <style>
      * {
        margin: 0;
        padding: 0;
      }
    </style>
  </head>
  <body>    
    <div id="app"></div>    
    <!-- 從 htmlWebpackPlugin 配置項(xiàng)中獲取 cdnJS 屬性 -->
    <% for(var js of htmlWebpackPlugin.options.cdnJS){ %>
    <script src="<%=js%>"></script>
    <% } %>
  </body>
</html>

其它優(yōu)化

externals + CDN 只能減小打包的體積乐疆,加快訪問(wèn)速度

其它的優(yōu)化如:

  1. gzip 壓縮

  2. http 緩存

  3. service worker

gzip 壓縮

  • 通過(guò) LZ77 算法與 Huffman 編碼來(lái)壓縮文件,<b>重復(fù)度越高</b> 的文件可壓縮的空間越大约计,對(duì)JS诀拭、CSS迁筛、HTML等文本資源均有效

  • 當(dāng) Nginx 返回 js 文件的時(shí)候煤蚌,會(huì)判斷是否開啟 gzip,然后壓縮后再返回給瀏覽器

  • 該方法需要 Nginx 配置開啟 Gzip 壓縮细卧,單純前端通過(guò) webpack 插件開啟 Gzip 壓縮是不能達(dá)到優(yōu)化效果的

http 緩存

  • 網(wǎng)頁(yè) 304 狀態(tài)碼:所請(qǐng)求的資源<b>未修改</b>尉桩。服務(wù)器返回此狀態(tài)碼時(shí),<b>不會(huì)</b>返回任何資源贪庙≈├纾客戶端通常會(huì)緩存訪問(wèn)過(guò)的資源,通過(guò)提供一個(gè)頭信息指出客戶端希望只返回在指定日期之前修改的資源

  • 大多數(shù)情況下止邮,304 一般在服務(wù)框架中進(jìn)行了處理这橙,前端一般不需要過(guò)于關(guān)注

service worker

  • 是一個(gè) JS api:https://developer.mozilla.org/zh-CN/docs/Web/API/Service_Worker_API

  • 旨在創(chuàng)建有效的離線體驗(yàn),它會(huì)攔截網(wǎng)絡(luò)請(qǐng)求并根據(jù)網(wǎng)絡(luò)是否可用來(lái)采取適當(dāng)?shù)膭?dòng)作导披、更新來(lái)自服務(wù)器的資源

  • 還提供入口以推送通知和訪問(wèn)后臺(tái)同步 API

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末屈扎,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子撩匕,更是在濱河造成了極大的恐慌鹰晨,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,039評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件止毕,死亡現(xiàn)場(chǎng)離奇詭異模蜡,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)扁凛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門忍疾,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人谨朝,你說(shuō)我怎么就攤上這事卤妒⊥璞撸” “怎么了?”我有些...
    開封第一講書人閱讀 165,417評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵荚孵,是天一觀的道長(zhǎng)妹窖。 經(jīng)常有香客問(wèn)我,道長(zhǎng)收叶,這世上最難降的妖魔是什么骄呼? 我笑而不...
    開封第一講書人閱讀 58,868評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮判没,結(jié)果婚禮上蜓萄,老公的妹妹穿的比我還像新娘。我一直安慰自己澄峰,他們只是感情好嫉沽,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,892評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著俏竞,像睡著了一般绸硕。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上魂毁,一...
    開封第一講書人閱讀 51,692評(píng)論 1 305
  • 那天玻佩,我揣著相機(jī)與錄音,去河邊找鬼席楚。 笑死咬崔,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的烦秩。 我是一名探鬼主播垮斯,決...
    沈念sama閱讀 40,416評(píng)論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼只祠!你這毒婦竟也來(lái)了兜蠕?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,326評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤铆农,失蹤者是張志新(化名)和其女友劉穎牺氨,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體墩剖,經(jīng)...
    沈念sama閱讀 45,782評(píng)論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡猴凹,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,957評(píng)論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了岭皂。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片郊霎。...
    茶點(diǎn)故事閱讀 40,102評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖爷绘,靈堂內(nèi)的尸體忽然破棺而出书劝,到底是詐尸還是另有隱情进倍,我是刑警寧澤,帶...
    沈念sama閱讀 35,790評(píng)論 5 346
  • 正文 年R本政府宣布购对,位于F島的核電站猾昆,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏骡苞。R本人自食惡果不足惜垂蜗,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,442評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望解幽。 院中可真熱鬧贴见,春花似錦、人聲如沸躲株。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)霜定。三九已至档悠,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間然爆,已是汗流浹背站粟。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工黍图, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留曾雕,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,332評(píng)論 3 373
  • 正文 我出身青樓助被,卻偏偏與公主長(zhǎng)得像剖张,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子揩环,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,044評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容