/
CATEGORY
Vue
/
在 Vite 專案中按需引入檔案,並自訂 chunk 分割代碼

在 Vite 專案中按需引入檔案,並自訂 chunk 分割代碼

MUKI AI Summary

在 Vite 專案中,按需引入檔案可減少不必要的資源載入。使用 Vue Router 的路由懶加載,將每個路由拆分成獨立的 chunk,僅在需要時載入相關檔案。設定 import 動態載入路由,能有效提升效能。

完成路由懶加載後,若發現過大的檔案,可使用 Vite 的 build.rollupOptions.output.manualChunks 手動拆分 node_modules 的 package。對於 element-plus 等框架,使用其內建的按需引入功能。另可透過 vite-plugin-compression 插件進行 gZip 壓縮,減少檔案大小,提升載入速度。...

關於按須引入檔案這個功能,我前前後後卡了很久,都是在專案開發的閒暇之餘研究,因為公司大多是以後台開發為主,比較不需要跑 PageSpeed。

不過還是希望可以按需引入,不然每次載入頁面看到拖了一堆不必要的資料,真的覺得很阿雜 XD。以下記錄我自己按需引入的設定步驟,希望對大家有幫助!

1. 路由懶加載

如果你也是用 Vue Router,那就可以將每個路由拆分成單獨的 chunk,例如 /login 的路由,就有一個 Login.js 的檔案,只有當進入 /login 頁面時,才會載入 Login.js 這隻檔案。

使用方法也很簡單,用 import 動態載入路由即可

▼ 把要按需引用的路由改用 import 動態載入

import { createRouter, createWebHistory } from 'vue-router'

const Login = () => import('@/pages/Login.vue')	// 改用 import 動態載入

const router = createRouter({
  history: createWebHistory(),
  routes: [{
  	path: '/login',
    component: Login
  }]
})

▼ 我其實在這一步卡很久 😂,因為我原本是這樣寫,把 import 寫在裡面,但不知為何 build 的時候就是不會把路由單獨 build 出一個檔案,最後我把它獨立拉出來才成功,但我到現在還是不知道原因 QQ,跪求各路大神指點迷津!

const router = createRouter({
  history: createWebHistory(),
  routes: [{
  	path: '/login',
    component: () => import('@/pages/Login.vue') // 原本寫在這,但沒有做用
  }]
})

其實只要做好這一步,就能實現基本的按需引用了,你會發現 build 專案時,他會幫你把檔案都照著路由拆分:

dist/assets/index.c2e3d9e4.js
dist/assets/Home.a4c8a61e.js
dist/assets/Area.3c14fb4d.js
dist/assets/Dashboard.7131aacd.js
dist/assets/Edit.54616d8c.js
...

如此一來,打開 /home 路由,就會載入 Home.a4c8a61e.js

打開 /dashboard,就會載入 Dashboard.7131aacd.js,... 依此類推。

參考資料:https://router.vuejs.org/guide/advanced/lazy-loading.html

2. 自己動手拆較大的檔案 (Chunk)

完成路由的懶加載後,可能會在 build 清單看到幾個過大的檔案,像這邊的 shine.3aae3c83.js 有 600多 kb;index.5cd3180a.js 也有 700 多 kb。

這部分的檔案,通常是由 node_modules 產生的,而我們並未對 node_modules 進行拆分,因此他預設會將所有 package 的 JS 合在一起,導致檔案過大。

因為我是用 Vite 框架,所以這邊以 Vite 為例,Vite 不需要再安裝 webpack,他使用的是 build.rollupOptions.output.manualChunks 幫我們手動拆檔,可以參考 rollupjs.org 的介紹

▼ 開啟 vite.config.ts,使用 build.rollupOptions.output.manualChunks

build: {
  rollupOptions: {
    output: {
      manualChunks: (id) => {
        // 可以把 id 印出來看,會更清楚知道他的內容
        // console.log('id', id)
        if (id.includes('node_modules')) {
          const arr = id.toString().split('node_modules/')[1].split('/')
          switch (arr[0]) {
            case 'element-plus':
              return
            default:
              return arr[0]
          }
        }
      }
    }
  }
}

我這邊的做法,是把 node_modules 裡面的所有 package 檔案都拆成一個一個獨立的檔案,命名方式為:package 叫什麼名字,檔案就是什麼名字,例如:dist/static/chunk/axios-95165d17.js,這個就是 axios 的 package

element plus 使用框架本身支援的按需引入

▼ 參考上述程式碼,可以發現當我的 node_modules'element-plus' 時,我的設定為照原本的拆法不要動,因為我有使用 element-plus 的按需引入,所以他會幫我把元件拆成一個個的 css 以及 js,用到才會載入

▼ 用到的 CSS 或 JS 檔案才會載入,這邊提供 CSS 的截圖以供參考, JS 亦同

3. 使用 gZip 壓縮

▼ 當我們在 build 檔案時,可以看到右側有兩個大小,第一個是實際大小,第二個是如果用了 gzip 壓縮後的大小

▼ vite 有 plugin 可以支援 gzip 壓縮,直接安裝:

$ npm install -D vite-plugin-compression 

▼ 在 vite.config.ts 設定你要壓縮的大小,我這邊設定為「原檔超過 50kb 就用 gzip 壓縮」

import viteCompression from 'vite-plugin-compression'

export default defineConfig({
  plugins: [
  	viteCompression({
      threshold: 50000 // 50kb
    })
  ]
})

▼ 再重新 build 一次,就會顯示有壓縮的檔案

確認 gZip 是否有成功執行

最後我們來檢查瀏覽器是否抓得到你的 gZip 檔案吧。

首先,先確認 server 有開啟 gzip,並且有把 CSS、JavaScript 加入 gzip 的設定中。

▼ 以 nginx 為例,我這邊加入的檔案類型有 text、css、js,以及 json:

http {
  gzip on;
  gzip_types text/plain text/css application/json application/javascript;
}

設定好之後記得重啟伺服器。

然後把網站的快取清除,重新開啟網頁,打開開發者工具面板,將 Content-Encoding 打開,如果有顯示 就表示有抓到 gzip 囉!

歡迎給我點鼓勵,讓我知道你來過 :)

7
2
8
MUKI says:

如果文章有幫助到你,歡迎分享給更多人知道。文章內容皆為 MUKI 本人的原創文章,我會經常更新文章以及修正錯誤內容,因此轉載時建議保留原出處,避免出現版本不一致或已過時的資訊。

本文地址:https://muki.tw/vite-lazyload-router-manual-chunk-gzip/ 已複製

Subscribe
Notify of
guest

0 則留言
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Copyright © since 2008 MUKI space* / omegaSS theme All Rights Reserved.