使用?vite?external?減小產(chǎn)物體積的方法實(shí)現(xiàn)
寫在前面
前幾個(gè)月工作過程中遇到了 Javascript heap out of memory 問題,當(dāng)時(shí)想著減小前端的產(chǎn)物大小,通過 vite.external解決這問題,查了很多文章,不過都以失敗告終,經(jīng)過不懈努力和大佬的指點(diǎn),終于成功了,故此分享。
前置工作
首先創(chuàng)建一個(gè)vue的項(xiàng)目,本地運(yùn)行 pnpm dev 啟動(dòng)項(xiàng)目
$ pnpm dev > test-external@0.0.0 dev /Users/.../test-external > vite VITE v5.4.2 ready in 138 ms ? Local: http://localhost:5173/ ? Network: use --host to expose
項(xiàng)目可以正常運(yùn)行,執(zhí)行 pnpm build 開始構(gòu)建
$ pnpm build vite v5.4.2 building for production... ? 67 modules transformed. dist/index.html 0.51 kB │ gzip: 0.32 kB dist/assets/index-B5GNdBo.css 0.32 kB │ gzip: 0.24 kB dist/assets/index-Dwy3Kika.js 62.20 kB │ gzip: 25.16 kB
可以看到j(luò)s文件的大小為 62.20KB
設(shè)置你想要排除的依賴
比如你想你的代碼打包出來(lái)的code不包括 vue
// vite.config.ts
export default defineConfig({
build: {
rollupOptions: {
external: ['vue']
}
}
})我們?cè)賵?zhí)行下 build 命令,看看產(chǎn)物大小
$ pnpm build vite v5.4.2 building for production... ? 62 modules transformed. dist/index.html 0.51 kB │ gzip: 0.32 kB dist/assets/index-DY_q8tlo.js 8.33 kB │ gzip: 3.28 kB
可以看到j(luò)s文件大小為 8.33KB,相較于 62.20KB 小了不少,我們把代碼推送到github,部署到 github pages 看看效果
核心報(bào)錯(cuò): Failed to resolve module specifier "vue"
瀏覽器找不到名為 vue 的 ESM 模塊,因?yàn)榇虬a(chǎn)物里保留了 from "vue",但線上環(huán)境沒有提供這個(gè)模塊。
發(fā)現(xiàn)頁(yè)面上什么內(nèi)容都沒有,控制臺(tái)報(bào)錯(cuò),說(shuō)沒有找到vue這個(gè)module,我們來(lái)看下產(chǎn)物
import {
createElementBlock as e,
createElementVNode as n,
toDisplayString as f,
ref as s,
createApp as y
} from "vue";
這里引入了vue,但是我們打包的時(shí)候,vue是排除了的,所以找不到vue,就報(bào)錯(cuò)了,我之前也在這里卡住過,去網(wǎng)上查解決方法,有人說(shuō),你要通過 cdn 引入 vue,我們第二步通過cdn引入。
cdn 引入相關(guān)依賴
<!-- index.html --> <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
這一步我其實(shí)剛剛在做第一步的時(shí)候就做了,還是有問題。我們來(lái)看下 vue 的 cdn 內(nèi)容
// https://unpkg.com/vue@3/dist/vue.global.js
var Vue = (function (exports) {
'use strict';
// ...
return exports;
})({});通過var聲明了一個(gè)叫 Vue 的變量,后面是一個(gè)自執(zhí)行函數(shù),但是我們的語(yǔ)法正常都是像上面產(chǎn)物那樣
import { ref, reactive } from 'vue';
import vue from 'vue';
這樣一想,報(bào)錯(cuò)也就不奇怪了,我們要是能把 vue引入的內(nèi)容通過 Vue.xxx 替換掉,不就解決了這個(gè)問題,畢竟var聲明的變量是全局的
設(shè)置 globals
這里我之前嘗試的時(shí)候,看到網(wǎng)上很多教程讓我設(shè)置 output.globals,后來(lái)發(fā)現(xiàn)根本不生效,就去翻了rollup的文檔
output.globals
只對(duì) umd / iife 產(chǎn)物生效,用于告訴 Rollup:某個(gè) external 依賴在運(yùn)行時(shí)對(duì)應(yīng)哪個(gè)全局變量。
文檔寫的很清楚,你要是打包成 umd 或者 iife 格式,可以設(shè)置這個(gè)參數(shù),但是我是要打包成 esm 格式(這就很尷尬了)
output.format 默認(rèn)值是 es。
- es:保留為 ES module
- iife:自執(zhí)行函數(shù),適合直接通過 <script> 引入
- umd:兼容 AMD / CommonJS / IIFE 的通用格式
所以這里的關(guān)鍵問題是:我的目標(biāo)產(chǎn)物是 ESM,不是 umd 或 iife,因此單獨(dú)配置 output.globals 并不能解決問題。
然后我就找到了一個(gè)rollup插件 rollup-plugin-external-globals,解決了我的問題
// vite.config.ts
import { defineConfig } from 'vite';
import externalGlobals from 'rollup-plugin-external-globals';
export default defineConfig({
plugins: [
externalGlobals({
vue: 'Vue'
})
],
build: {
rollupOptions: {
external: ['vue']
}
}
});
$ pnpm build vite v5.4.2 building for production... ? 62 modules transformed. dist/assets/index-*.js 9.59 kB
我們看到包的大小相較于 8.33KB 大了一點(diǎn),為什么呢?我引入了一個(gè)插件就變大了,直接來(lái)看下產(chǎn)物
const {
createElementVNode,
openBlock,
createElementBlock,
ref,
createApp
} = Vue;沒有 import { xxx } from 'vue';,這個(gè)Vue在代碼運(yùn)行的時(shí)候會(huì)沿著作用域鏈一直找到 Window,剛好我們引入的 vue cdn通過var聲明了一個(gè)Vue,這樣就對(duì)上了。至于為什么打包產(chǎn)物大小變大了,是因?yàn)樽址麛?shù)變多了。我們推下代碼,驗(yàn)證下想法
控制臺(tái)不再出現(xiàn) Failed to resolve module specifier "vue" 的報(bào)錯(cuò)。
大功告成?。?!
QA
為什么要設(shè)置 external ?我直接設(shè)置cdn,代碼里面不用import,也能行啊 ??? ?
這么做確實(shí)沒啥問題,代碼也能正常運(yùn)行,部署到生產(chǎn)也不會(huì)有啥問題,不用import,就失去了類型提示,引入提示等依賴帶來(lái)的好處,內(nèi)容都是有上下文的,不會(huì)覺得奇怪
為什么這套配置開發(fā)環(huán)境下有問題
由于vite的開發(fā)環(huán)境用的是esbuild,打包用的是rollup,而rollup-plugin-external-globals插件是rollup插件,不建議在開發(fā)環(huán)境使用,以避免引起不必要的麻煩
/// vite.config.ts
import { defineConfig } from 'vite';
import externalGlobals from "rollup-plugin-external-globals";
const isProduction = process.env.NODE_ENV === 'production'
export default defineConfig(() => {
return {
plugins: [
...,
isProduction && externalGlobals({
vue: "Vue"
})
],
}
})
寫在最后
到此這篇關(guān)于使用 vite external 減小產(chǎn)物體積的文章就介紹到這了,更多相關(guān)vite external 減小體積內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Vue中splice()方法對(duì)數(shù)組進(jìn)行增刪改等操作的實(shí)現(xiàn)
vue中對(duì)數(shù)組的元素進(jìn)行刪除,以前一直以為這個(gè)方法是vue中特有的,后來(lái)百度之后才知道原來(lái)是js的一個(gè)寫法,下面這篇文章主要給大家介紹了關(guān)于Vue中splice()方法對(duì)數(shù)組進(jìn)行增刪改等操作的實(shí)現(xiàn)方法,需要的朋友可以參考下2023-05-05
Vue+Echarts實(shí)現(xiàn)繪制動(dòng)態(tài)折線圖
這篇文章主要為大家詳細(xì)介紹了如何利用Vue和Echarts實(shí)現(xiàn)繪制動(dòng)態(tài)折線圖,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-03-03
Vue?keepAlive實(shí)現(xiàn)不同的路由共用一個(gè)組件component的緩存問題(推薦)
這篇文章主要介紹了Vue?keepAlive實(shí)現(xiàn)不同的路由共用一個(gè)組件component的緩存問題,實(shí)現(xiàn)方式使用Vue?keepAlive實(shí)現(xiàn)頁(yè)面緩存,需要的朋友可以參考下2022-08-08

