vite —— 一種尤雨溪開發(fā)的新的、更快地 web 開發(fā)工具

文末福利:開發(fā)者藏經(jīng)閣
NO.1
vite 是什么
vite —— 一個由 vue 作者尤雨溪開發(fā)的 web 開發(fā)工具,它具有以下特點:
快速的冷啟動
即時的模塊熱更新
真正的按需編譯
?
從作者在微博上的發(fā)言:
Vite,一個基于瀏覽器原生 ES imports 的開發(fā)服務(wù)器。利用瀏覽器去解析 imports,在服務(wù)器端按需編譯返回,完全跳過了打包這個概念,服務(wù)器隨起隨用。同時不僅有 Vue 文件支持,還搞定了熱更新,而且熱更新的速度不會隨著模塊增多而變慢。針對生產(chǎn)環(huán)境則可以把同一份代碼用 rollup 打。雖然現(xiàn)在還比較粗糙,但這個方向我覺得是有潛力的,做得好可以徹底解決改一行代碼等半天熱更新的問題。
?
中可以看出 vite 主要特點是基于瀏覽器 native 的 ES module (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import)?來開發(fā),省略打包這個步驟,因為需要什么資源直接在瀏覽器里引入即可。
基于瀏覽器 ES module 來開發(fā) web 應(yīng)用也不是什么新鮮事,snowpack 也基于此,不過目前此項目社區(qū)中并沒有流行起來,vite 的出現(xiàn)也許會讓這種開發(fā)方式再火一陣子。
有趣的是 vite 算是革了 webpack 的命了(生產(chǎn)環(huán)境用 rollup),所以 webpack 的開發(fā)者直接喊大哥了...

作者注:本文完成于 vite 早期時候,vite 部分功能和原理有更新。
NO.2
vite 的使用方式
同常見的開發(fā)工具一樣,vite 提供了用 npm 或者 yarn 一建生成項目結(jié)構(gòu)的方式,使用 yarn 在終端執(zhí)行:
$?yarn?create?vite-app?
$?cd?
$?yarn
$?yarn?dev
即可初始化一個 vite 項目(默認(rèn)應(yīng)用模板為 vue3.x),生成的項目結(jié)構(gòu)十分簡潔:
|____node_modules
|____App.vue?//?應(yīng)用入口
|____index.html?//?頁面入口
|____vite.config.js?//?配置文件
|____package.json
執(zhí)行 yarn dev 即可啟動應(yīng)用 。
NO.3
vite 啟動鏈路
命令解析
這部分代碼在 src/node/cli.ts 里,主要內(nèi)容是借助 minimist —— 一個輕量級的命令解析工具解析 npm scripts,解析的函數(shù)是 resolveOptions ,精簡后的代碼片段如下。
function?resolveOptions()?{
????//?command?可以是?dev/build/optimize
????if?(argv._[0])?{
????????argv.command?=?argv._[0];
????}
????return?argv;
}
拿到 options 后,會根據(jù) options.command 的值判斷是執(zhí)行在開發(fā)環(huán)境需要的 runServe 命令或生產(chǎn)環(huán)境需要的 runBuild 命令。
if?(!options.command?||?options.command?===?'serve')?{
????runServe(options)
?}?else?if?(options.command?===?'build')?{
????runBuild(options)
?}?else?if?(options.command?===?'optimize')?{
????runOptimize(options)
?}
在 runServe 方法中,執(zhí)行 server 模塊的創(chuàng)建開發(fā)服務(wù)器方法,同樣在 runBuild 中執(zhí)行 build 模塊的構(gòu)建方法。
最新的版本中還增加了 optimize 命令的支持,關(guān)于 optimize 做了什么,我們下文再說。
server
這部分代碼在 src/node/server/index.ts 里,主要暴露一個 createServer 方法。
vite 使用 koa 作 web server,使用 clmloader 創(chuàng)建了一個監(jiān)聽文件改動的 watcher,同時實現(xiàn)了一個插件機制,將 koa-app 和 watcher 以及其他必要工具組合成一個 context 對象注入到每個 plugin 中。
context 組成如下:

plugin 依次從 context 里獲取上面這些組成部分,有的 plugin 在 koa 實例添加了幾個 middleware,有的借助 watcher 實現(xiàn)對文件的改動監(jiān)聽,這種插件機制帶來的好處是整個應(yīng)用結(jié)構(gòu)清晰,同時每個插件處理不同的事情,職責(zé)更分明,
plugin
上文我們說到 plugin,那么有哪些 plugin 呢?它們分別是:
用戶注入的 plugins —— 自定義 plugin
hmrPlugin —— 處理 hmr
htmlRewritePlugin —— 重寫 html 內(nèi)的 script 內(nèi)容
moduleRewritePlugin —— 重寫模塊中的 import 導(dǎo)入
moduleResolvePlugin ——獲取模塊內(nèi)容
vuePlugin —— 處理 vue 單文件組件
esbuildPlugin —— 使用 esbuild 處理資源
assetPathPlugin —— 處理靜態(tài)資源
serveStaticPlugin —— 托管靜態(tài)資源
cssPlugin —— 處理 css/less/sass 等引用
...
我們來看 plugin 的實現(xiàn)方式,開發(fā)一個用來攔截 json 文件 plugin 可以這么實現(xiàn):
interface?ServerPluginContext?{
??root:?string
??app:?Koa
??server:?Server
??watcher:?HMRWatcher
??resolver:?InternalResolver
??config:?ServerConfig
}
type?ServerPlugin?=?(ctx:ServerPluginContext)=>?void;
const?JsonInterceptPlugin:ServerPlugin?=?({app})=>{
????app.use(async?(ctx,?next)?=>?{
??????await?next()
??????if?(ctx.path.endsWith('.json')?&&?ctx.body)?{
????????ctx.type?=?'js'
????????ctx.body?=?`export?default?json`
??????}
??})
}
vite 背后的原理都在 plugin 里,這里不再一一解釋每個 plugin 的作用,會放在下文背后的原理中一并討論。
build
這部分代碼在 node/build/index.ts 中,build 目錄的結(jié)構(gòu)雖然與 server 相似,同樣導(dǎo)出一個 build 方法,同樣也有許多 plugin,不過這些 plugin 與 server 中的用途不一樣,因為 build 使用了 rollup ,所以這些 plugin 也是為 rollup 打包的 plugin ,本文就不再多提。
NO.4
vite 運行原理
ES module
要了解 vite 的運行原理,首先要知道什么是 ES module,目前流覽器對其的支持如下:

主流的瀏覽器(IE11除外)均已經(jīng)支持,其最大的特點是在瀏覽器端使用 export import 的方式導(dǎo)入和導(dǎo)出模塊,在 script 標(biāo)簽里設(shè)置 type="module" ,然后使用模塊內(nèi)容。
當(dāng) html 里嵌入上面的 script 標(biāo)簽時候,瀏覽器會發(fā)起 http 請求,請求 htttp server 托管的 bar.js ,在 bar.js 里,我們用 named export 導(dǎo)出 bar 變量,在上面的 script 中能獲取到 bar 的定義。
//?bar.js?
export?const?bar?=?'bar';
在 vite 中的作用
打開運行中的 vite 項目,訪問 view-source 可以發(fā)現(xiàn) html 里有段這樣的代碼:
天天射天天操天天日
|
91日日日日日
|
天天干天天爽
|
黑人操逼视频在线播放
|
手机能看的av网站
|
