當(dāng)webpack有了vite的速度
點(diǎn)擊上方關(guān)注 前端技術(shù)江湖,一起學(xué)習(xí),天天進(jìn)步

前言
本文主旨意義是在于和大家分享自己的腳手架,以及在開發(fā)過(guò)程中受到的一些心得。
首先閱讀此文可以當(dāng)作為僅僅了解一個(gè)新的工具,同時(shí)由于進(jìn)行了webpack和vite雙向的說(shuō)明,中間會(huì)參雜了一定的vite和webpack的內(nèi)容解析。(主要進(jìn)行思路分析不涉及具體源碼,感興趣的可以自己去閱讀源碼)
對(duì)于分析不感興趣的大佬可以直接進(jìn)入v5-run小結(jié)
#老規(guī)矩打一波推廣
vue組件平臺(tái)服務(wù)器最近搞了新的服務(wù)器了,歡迎大家去進(jìn)行嘗試!
同時(shí)如果有大佬希望能利用搭建公司的組件分析平臺(tái)也可以找我。
項(xiàng)目采用docker部署,可以很方便搭建公司內(nèi)部的一個(gè)平臺(tái)。
線上訪問(wèn)地址:http://assemble.everbeon.top/assemble/#/Show/index
注:嫌背景粒子動(dòng)畫卡的可以點(diǎn)擊右上角的小圖標(biāo)就可以關(guān)閉背景動(dòng)畫
復(fù)制代碼
如何讓webpack有vite的速度
webpack vs vite
首先這一個(gè)問(wèn)題我們要先將進(jìn)行兩段分析,webpack慢和vite快的原因是什么?
webpack bundle everything
是的,這就是webpack慢的原因,由于webpack對(duì)于所有運(yùn)行資源進(jìn)行了提前編譯處理,對(duì)依賴模塊進(jìn)行了語(yǔ)法分析轉(zhuǎn)義,最終的結(jié)果就是模塊被打包到內(nèi)存中。
vite Bundleless esbuild esmodule
在vite中就出現(xiàn)相反的情況了,遵循著打包少、預(yù)處理的方式,讓vite只有在運(yùn)行第一次的時(shí)候進(jìn)行依賴的打包處理(package.json不變)。并且在運(yùn)行中由于依賴著esmodule可以將文件采用import方式直接引入,這樣就不用把文件打包到一起,而且采用esbuild對(duì)于語(yǔ)法的解析轉(zhuǎn)換(如:ts、jsx等)這樣就不用進(jìn)行js解析ast語(yǔ)法樹后再重新構(gòu)建,這樣第一可以節(jié)省大量的cpu以及內(nèi)存空間、第二可以減少語(yǔ)法解析的大量時(shí)間,基本上可以達(dá)到時(shí)效性不用提前進(jìn)行語(yǔ)法解析。
why webpack
在webpack的開發(fā)中,大家或多或少的都在利用著webpack的“方言”帶來(lái)的便利。比如以下代碼:
// require.context Api
require.context(directory, useSubdirectories, regExp)
...
// css導(dǎo)出變量給js
:export {
theme: $--color-primary;
}
...
// 各種魔幻的路徑
import App from 'App'
...
// 以及svg引入
<use :xlink:href="iconName" />
復(fù)制代碼
可以說(shuō),webpack在給我們帶來(lái)方便的時(shí)候也同時(shí)把我們給慣壞了!越來(lái)越脫離標(biāo)準(zhǔn)的es規(guī)范了,給我們開了越來(lái)越多的后門可走,甚至我們可以在我們的頁(yè)面中寫一些node api一樣給我們搞定。(期待再多點(diǎn)這種方便的后門)在這種情況下我們進(jìn)行webpack遷移到vite就會(huì)出現(xiàn)一系列的報(bào)錯(cuò),并且由于配置文件不熟悉rollup也同時(shí)給我們的項(xiàng)目帶來(lái)了不確定性,那么我不想動(dòng)我原本的項(xiàng)目就像體驗(yàn)一下vite飛一般的感覺就是我的初始目標(biāo)了。
how to do
把大象放進(jìn)冰箱分幾步?
把冰箱門打開 把大象放進(jìn)去 關(guān)閉冰箱門
是的我們的原理也如果放大象一樣非常的簡(jiǎn)單,任何復(fù)雜的問(wèn)題都可以簡(jiǎn)單化處理,且不要把問(wèn)題想的過(guò)于復(fù)雜才是解決問(wèn)題的最快途徑
我們主要內(nèi)容也分為三步
構(gòu)建url以及語(yǔ)法解析服務(wù)
這一步主要是為了讓我們的腳手架支持webpack特有的路徑預(yù)處理判斷,并且可以正常的解析我們的vue文件。
三方依賴處理
這步作為依賴的收集處理,并且讓其支持import方式導(dǎo)入,相當(dāng)于webpack中的vender處理
webpack方言api實(shí)現(xiàn)
實(shí)現(xiàn)webpack的特殊api,如::export {}、require.context
這樣就實(shí)現(xiàn)了我們整個(gè)目標(biāo)路徑。當(dāng)然如果簡(jiǎn)單列一下架構(gòu)的話,估計(jì)就需要這樣的一張圖來(lái)實(shí)現(xiàn)。

當(dāng)然處理webpack方言實(shí)現(xiàn)之外(沒(méi)法進(jìn)行整合到這上面,那個(gè)算具體需求),會(huì)發(fā)現(xiàn)三方依賴并沒(méi)有在設(shè)計(jì)中,接下來(lái)我們就重點(diǎn)講一下這個(gè)三方依賴(涉及到vite的一定原理解析,可以了解到面試吹牛皮)。
why first node_modules
為什么在vite中需要提前構(gòu)建第三方依賴?官網(wǎng)給的解釋有以下兩點(diǎn):
CommonJS 和 UMD 兼容性 性能
但是!利用esbuild去構(gòu)建達(dá)到兼容性和性能似乎也不是問(wèn)題,并且不進(jìn)行預(yù)構(gòu)建其實(shí)有一個(gè)隱性的好處就是可以減少運(yùn)行時(shí)的node_modules依賴性,比如我們可以手動(dòng)實(shí)現(xiàn)一個(gè)類似yarn的包集中管理,這樣我們就可以完美的實(shí)現(xiàn)項(xiàng)目中無(wú)node_modules了,想想都激動(dòng)呢。那么問(wèn)題點(diǎn)在哪呢?
esbuild中有一個(gè)選項(xiàng)為bundle: true
這個(gè)選項(xiàng)會(huì)將需要打包的入口文件的依賴進(jìn)行全部打包,比如:我導(dǎo)入elementui,那么他就會(huì)將所有element需要的依賴統(tǒng)統(tǒng)打入到內(nèi)部。(重要!請(qǐng)記住)
這個(gè)時(shí)候當(dāng)我們引入了elementui后,elementui內(nèi)部使用的vue和項(xiàng)目中本身的vue是不是同一個(gè)呢?
答案:不是,因?yàn)閑lementui引入的是自己內(nèi)部的vue,而項(xiàng)目中是通過(guò)單獨(dú)引入的vue
webpack引入到底是怎樣引入?
在我們的node_modules中大家可以去找一下這個(gè)現(xiàn)象,會(huì)發(fā)現(xiàn)element-ui中明明就需要很多依賴,但是他卻沒(méi)有或者只有很少的依賴,這些依賴往往都是在node_modules中的第一層。這樣的結(jié)果是怎么樣的呢?
在同一項(xiàng)目中,不同工程依賴同一個(gè)npm,他們引入是相同的,并且是屬于引用值相當(dāng)于他們共享了這個(gè)npm的導(dǎo)出。比如a.js引入了 xxx.js將原本的導(dǎo)出的ceshi這個(gè)值修改成了2,那么當(dāng)b.js引入的時(shí)候獲取到ceshi這個(gè)值也是2而不是最開始的值了。
到這我們就發(fā)現(xiàn)了最大的問(wèn)題,在運(yùn)行時(shí)去加載依賴沒(méi)辦法分析他們之間的引用關(guān)系,這樣會(huì)導(dǎo)致最大的隱患問(wèn)題!!!
所以vite進(jìn)行了預(yù)處理的問(wèn)題最大點(diǎn)是在于三方包之間的依賴關(guān)系問(wèn)題。
vite為什么可以預(yù)處理分析
這個(gè)答案其實(shí)很簡(jiǎn)單了,因?yàn)関ite需要在入口的html中添加type="module"的script導(dǎo)入,然后將匹配script引入的導(dǎo)入作為esbuild的入口文件,這樣esbuild就通過(guò)入口文件尋找各種依賴關(guān)系然后再加入插件分析依賴引入狀態(tài),就實(shí)現(xiàn)了感覺高大上智能的預(yù)處理分析了。
v5-run
這就是讓webpack有vite速度的神奇指令了,實(shí)現(xiàn)就是依照著上面所屬完成的。
因此這里主要就講解腳手架的使用以及配置。(暫時(shí)只能用于vue2開發(fā))
地址合集
npm: www.npmjs.com/package/\@se…[1]
gitee: gitee.com/beon/v5-vue…[2]
npm安裝: npm i @seeyon-v5-vue/cli-run -g
運(yùn)行指令:v5-run
配置文件
類似與各種配置文件,你需要在項(xiàng)目根路徑下創(chuàng)建v5-run.config.js文件,并將其進(jìn)行配置對(duì)象的導(dǎo)出。
module.exports = {
// 服務(wù)運(yùn)行的配置
server: {
// 和webpack proxy一樣
proxy: {
[url: string]: {
target: string,
host?: string,
headers?: {[key: string]: string}
changOrigin?: boolean
}
},
// 是否開啟http2模式(不穩(wěn)定,嘗鮮使用)
http2:Boolean,
// 重要,自動(dòng)獲取html路徑為根路徑和public路徑,如果html不在需要手動(dòng)添加如:['src/html/']
enter: string[]
},
// 各種設(shè)置的配置
config:{
// 配置svg引入到html中
svgLoader: {
// 引入svg文件夾路徑
path: string,
// svg引入名稱配置如:my-svg-[name],引入名稱則為(svg文件名為app.svg):my-svg-app
symbolId: string
},
// 全局導(dǎo)入less、scss等
styleLoader: {
// 前面為引入類型如less、scss,數(shù)組為引入文件如['src/assets/index.scss']
[loadStyle: string]: string[]
},
// 全局變量配置如:_(loadsh)
global: {
// 前面為全局名稱如: _,后面為引入方式比如loadsh,數(shù)組則為某一項(xiàng)比如[loadsh, map],那么就會(huì)獲得loadsh.map的對(duì)象引入
[name: string]: string | string[]
}
}
}
復(fù)制代碼
使用教程
第一步配置v5-run.config.文件
基礎(chǔ)配置文件,可以按照需求改就可以了
module.exports = {
server: {
enter: ['./src'],
http2: true,
proxy: {
"/dev-api": {
target: 'http://localhost',
changOrigin: true
}
}
},
config: {
svgLoader: {
path: 'src/icons',
symbolId: 'icon-[name]'
},
global: {
_: "lodash",
$: "jquery",
jQuery: "jquery"
},
styleLoader: {
less: [path.resolve(__dirname, "./src/assets/styles/variable.less")]
}
}
};
復(fù)制代碼
第二步執(zhí)行v5-run指令
看到服務(wù)開啟成功后為成功開啟

第三步訪問(wèn)網(wǎng)頁(yè)(注意)
在網(wǎng)頁(yè)訪問(wèn)路徑需要手動(dòng)輸入到你的入口文件,比如:http://localhost:3000/src/html/index.html[3] 其次,最好加入index.html路徑,否則有可能會(huì)出現(xiàn)某些路徑解析少一層的問(wèn)題。訪問(wèn)錯(cuò)誤的時(shí)候會(huì)出現(xiàn)提示,并且有問(wèn)題也會(huì)出現(xiàn)提示頁(yè)面,可以雙擊錯(cuò)誤請(qǐng)求頁(yè)點(diǎn)進(jìn)去查看錯(cuò)誤原因

問(wèn)題點(diǎn)
那這一塊作為單獨(dú)說(shuō)明主要是強(qiáng)調(diào)現(xiàn)階段該實(shí)現(xiàn)而沒(méi)有實(shí)現(xiàn)的重要功能點(diǎn)。
沒(méi)有熱更新
暫時(shí)沒(méi)有做熱更新,雖然有現(xiàn)有實(shí)例,但是僅僅作為本人使用而言,熱更新暫時(shí)意義不大(項(xiàng)目較為特殊)。
webpack兼容性
作為兼容性只是做了幾個(gè)常用的設(shè)置以及配置,能夠滿足大多數(shù)標(biāo)準(zhǔn)的項(xiàng)目而已,特殊項(xiàng)目需要特殊處理,暫時(shí)無(wú)法解決,如果有問(wèn)題可以直接聯(lián)系我,可以查看腳手架問(wèn)題缺點(diǎn)(說(shuō)不定下個(gè)版本就修復(fù)了呢)。
三方依賴每次開啟都會(huì)處理
其實(shí)這個(gè)是個(gè)比較好處理的問(wèn)題,但是本人在使用的時(shí)候發(fā)現(xiàn)處理時(shí)間較短,所以暫時(shí)未作處理(就是懶)。
css文件中的路徑處理
比如element中scss就有這樣$--font-path: "~element-ui/lib/theme-chalk/fonts"一句,需要在其上面進(jìn)行注釋//v5-run-style-path,就會(huì)處理這個(gè)路徑參數(shù)。(只有參數(shù)需要添加,@import、正常url都不需要 )

結(jié)尾
大家感興趣去看gitee的話也可以看到,本項(xiàng)目只是整個(gè)腳手架項(xiàng)目的一塊,剩下的內(nèi)容都還沒(méi)加上去,后期會(huì)將處理方式、代理方式、管理三方包方式全部抽出來(lái),做成一個(gè)完整的腳手架項(xiàng)目。現(xiàn)在只是進(jìn)行項(xiàng)目可行性的制作。整體項(xiàng)目使用了ts進(jìn)行開發(fā),但是由于沒(méi)有具體拆分所以還沒(méi)有上單元測(cè)試。
作為一個(gè)新的腳手架內(nèi)容,我認(rèn)為提高開發(fā)效率以及項(xiàng)目穩(wěn)定性是最重要的,這也是為什么沒(méi)有一昧的進(jìn)行強(qiáng)行替換vite作為生產(chǎn),當(dāng)出現(xiàn)問(wèn)題的時(shí)候可以直接使用webpack進(jìn)行處理。(比如:ie情況、兼容性測(cè)試等問(wèn)題)所以項(xiàng)目不失為我們?cè)谇袚Q到使用esmodule上的一個(gè)嘗試階段,讓我們?nèi)プ兿嘈缘淖寃ebpack擁有著和vite一樣的速度。
本項(xiàng)目中的三方依賴處理,有一定程度借鑒vite,所以現(xiàn)階段代碼較為相似,這也是為什么我沒(méi)有急著做初始化緩存信息的原因,因?yàn)閷?lái)目標(biāo)不一樣,所以后期會(huì)進(jìn)行修改該塊內(nèi)容。
關(guān)于本文
作者:BEON
https://juejin.cn/post/6975380991762235422
The End
歡迎自薦投稿到《前端技術(shù)江湖》,如果你覺得這篇內(nèi)容對(duì)你挺有啟發(fā),記得點(diǎn)個(gè) 「在看」哦
點(diǎn)個(gè)『在看』支持下 
