總覽
Vite(法語意為 "快速的"曙聂,發(fā)音 /vit/
[圖片上傳失敗...(image-7771a7-1647833168481)] 廊镜,發(fā)音同 "veet")是一種新型前端構(gòu)建工具榜聂,能夠顯著提升前端開發(fā)體驗(yàn)。它主要由兩部分組成:
一個(gè)開發(fā)服務(wù)器陌凳,它基于 原生 ES 模塊 提供了 豐富的內(nèi)建功能剥懒,如速度快到驚人的 模塊熱更新(HMR)。
一套構(gòu)建指令合敦,它使用 Rollup 打包你的代碼初橘,并且它是預(yù)配置的,可輸出用于生產(chǎn)環(huán)境的高度優(yōu)化過的靜態(tài)資源充岛。
Vite 意在提供開箱即用的配置保檐,同時(shí)它的 插件 API 和 JavaScript API 帶來了高度的可擴(kuò)展性,并有完整的類型支持裸准。
你可以在 為什么選 Vite 中了解更多關(guān)于項(xiàng)目的設(shè)計(jì)初衷。
Vue 第一優(yōu)先級支持
Vite 最初是作為 Vue.js 開發(fā)工具的未來基礎(chǔ)而創(chuàng)建的赔硫。盡管 Vite 2.0 版本完全不依賴于任何框架炒俱,但官方 Vue 插件仍然對 Vue 的單文件組件格式提供了第一優(yōu)先級的支持,涵蓋了所有高級特性爪膊,如模板資源引用解析权悟、<script setup>
,<style module>
推盛,自定義塊等等峦阁。除此之外,Vite 還對 Vue 單文件組件提供了細(xì)粒度的 HMR耘成。舉個(gè)例子榔昔,更新一個(gè)單文件組件的 <template>
或 <style>
會(huì)執(zhí)行不重置其狀態(tài)的熱更新驹闰。
瀏覽器支持
- 默認(rèn)的構(gòu)建目標(biāo)瀏覽器是能 在 script 標(biāo)簽上支持原生 ESM 和 原生 ESM 動(dòng)態(tài)導(dǎo)入。傳統(tǒng)瀏覽器可以通過官方插件 @vitejs/plugin-legacy 支持 —— 查看 構(gòu)建生產(chǎn)版本 章節(jié)獲取更多細(xì)節(jié)撒会。
搭建第一個(gè) Vite 項(xiàng)目
兼容性注意, Vite 需要 Node.js 版本 >= 12.0.0嘹朗。
### npm 7+, 需要額外的雙橫線:
npm init vite@latest my-vue-app -- --template vue
查看 create-vite 以獲取每個(gè)模板的更多細(xì)節(jié):
vanilla
,vanilla-ts
诵肛,vue
屹培,vue-ts
,react
怔檩,react-ts
褪秀,preact
,preact-ts
薛训,lit
媒吗,lit-ts
,svelte
许蓖,svelte-ts
蝴猪。
index.html 與項(xiàng)目根目錄
Vite 將 index.html 視為源碼和模塊圖的一部分。Vite 解析 <script type="module" src="..."> 膊爪,這個(gè)標(biāo)簽指向你的 JavaScript 源碼自阱。甚至內(nèi)聯(lián)引入 JavaScript 的 <script type="module"> 和引用 CSS 的 <link href> 也能利用 Vite 特有的功能被解析。另外米酬,index.html 中的 URL 將被自動(dòng)轉(zhuǎn)換沛豌,因此不再需要 %PUBLIC_URL% 占位符了。
Vite 也支持多個(gè) .html
作入口點(diǎn)的 多頁面應(yīng)用模式赃额。
指定替代根目錄
vite
以當(dāng)前工作目錄作為根目錄啟動(dòng)開發(fā)服務(wù)器加派。你也可以通過 vite serve some/sub/dir
來指定一個(gè)替代的根目錄。
在安裝了 Vite 的項(xiàng)目中跳芳,可以在 npm scripts 中使用 vite 可執(zhí)行文件芍锦,或者直接使用 npx vite 運(yùn)行它。下面是通過腳手架創(chuàng)建的 Vite 項(xiàng)目中默認(rèn)的 npm scripts:
### package.json
{
"name": "vite-henrypt",
"private": true,
"version": "0.0.0",
"scripts": {
"dev": "vite", # 啟動(dòng)開發(fā)服務(wù)器飞盆,別名:`vite dev`, `vite serve`
"build": "vite build", # 為生產(chǎn)環(huán)境構(gòu)建產(chǎn)物
"preview": "vite preview" # 本地預(yù)覽生產(chǎn)構(gòu)建產(chǎn)物
},
"dependencies": {
"vue": "^3.2.25"
},
"devDependencies": {
"@vitejs/plugin-vue": "^2.2.0",
"vite": "^2.8.0"
}
}
可以指定額外的命令行選項(xiàng)娄琉,如 --port 或 --https。運(yùn)行 npx vite --help 獲得完整的命令行選項(xiàng)列表吓歇。
功能
對非衬跛基礎(chǔ)的使用來說,使用 Vite 開發(fā)和使用一個(gè)靜態(tài)文件服務(wù)器并沒有太大區(qū)別城看。然而女气,Vite 還通過原生 ESM 導(dǎo)入提供了許多主要用于打包場景的增強(qiáng)功能。
NPM 依賴解析和預(yù)構(gòu)建#
原生 ES 導(dǎo)入不支持下面這樣的裸模塊導(dǎo)入:import { add } from 'my-dep'
上面的代碼會(huì)在瀏覽器中拋出一個(gè)錯(cuò)誤测柠。Vite 將會(huì)檢測到所有被加載的源文件中的此類裸模塊導(dǎo)入炼鞠,并執(zhí)行以下操作:
預(yù)構(gòu)建 它們可以提高頁面加載速度缘滥,并將 CommonJS / UMD 轉(zhuǎn)換為 ESM 格式。預(yù)構(gòu)建這一步由 esbuild 執(zhí)行簇搅,這使得 Vite 的冷啟動(dòng)時(shí)間比任何基于 JavaScript 的打包器都要快得多完域。
重寫導(dǎo)入為合法的 URL,例如
/node_modules/.vite/my-dep.js?v=f3sf2ebd
以便瀏覽器能夠正確導(dǎo)入它們瘩将。
依賴是強(qiáng)緩存的
Vite 通過 HTTP 頭來緩存請求得到的依賴吟税,所以如果你想要編輯或調(diào)試一個(gè)依賴,請按照 這里 的步驟操作姿现。
模塊熱重載
Vite 提供了一套原生 ESM 的 HMR API肠仪。 具有 HMR 功能的框架可以利用該 API 提供即時(shí)、準(zhǔn)確的更新备典,而無需重新加載頁面或清除應(yīng)用程序狀態(tài)异旧。Vite 內(nèi)置了 HMR 到 Vue 單文件組件(SFC) 和 React Fast Refresh 中。也通過 @prefresh/vite 對 Preact 實(shí)現(xiàn)了官方集成提佣。
注意吮蛹,你不需要手動(dòng)設(shè)置這些 —— 當(dāng)你通過 create-vite
創(chuàng)建應(yīng)用程序時(shí),所選模板已經(jīng)為你預(yù)先配置了這些拌屏。
TypeScript#
略過
Vue
Vite 為 Vue 提供第一優(yōu)先級支持:
- Vue 3 單文件組件支持:@vitejs/plugin-vue
- Vue 3 JSX 支持:@vitejs/plugin-vue-jsx
- Vue 2 支持:underfin/vite-plugin-vue2
JSX
略過
CSS
CSS 預(yù)處理器支持
Vite 為 Sass and Less 提供了更精細(xì)化的支持潮针,包括改進(jìn) @import
解析(可使用別名與 npm 依賴)和 提供 url()
內(nèi)聯(lián)引入與變基。
導(dǎo)入 .css 文件將會(huì)把內(nèi)容插入到 <style> 標(biāo)簽中倚喂,同時(shí)也帶有 HMR 支持每篷。也能夠以字符串的形式檢索處理后的、作為其模塊默認(rèn)導(dǎo)出的 CSS端圈。
@import 內(nèi)聯(lián)和變基
Vite 通過 postcss-import 預(yù)配置支持了 CSS @import 內(nèi)聯(lián)焦读,Vite 的路徑別名也遵從 CSS @import。換句話說舱权,所有 CSS url() 引用矗晃,即使導(dǎo)入的文件在不同的目錄中,也總是自動(dòng)變基宴倍,以確保正確性张症。PostCSS
如果項(xiàng)目包含有效的 PostCSS 配置 (任何受 postcss-load-config 支持的格式,例如postcss.config.js
)啊楚,它將會(huì)自動(dòng)應(yīng)用于所有已導(dǎo)入的 CSS吠冤。CSS Modules
任何以.module.css
為后綴名的 CSS 文件都被認(rèn)為是一個(gè) CSS modules 文件浑彰。CSS 預(yù)處理器
由于 Vite 的目標(biāo)僅為現(xiàn)代瀏覽器恭理,因此建議使用原生 CSS 變量和實(shí)現(xiàn) CSSWG 草案的 PostCSS 插件(例如 postcss-nesting)來編寫簡單的、符合未來標(biāo)準(zhǔn)的 CSS郭变。
話雖如此颜价,但 Vite 也同時(shí)提供了對 .scss
, .sass
, .less
, .styl
和 .stylus
文件的內(nèi)置支持涯保。沒有必要為它們安裝特定的 Vite 插件,但必須安裝相應(yīng)的預(yù)處理器依賴:
# .scss and .sass
npm install -D sass
# .less
npm install -D less
# .styl and .stylus
npm install -D stylus
如果是用的是單文件組件周伦,可以通過 <style lang="sass">(或其他預(yù)處理器)自動(dòng)開啟夕春。
靜態(tài)資源處理
導(dǎo)入一個(gè)靜態(tài)資源會(huì)返回解析后的 URL:
import imgUrl from './img.png'
document.getElementById('hero-img').src = imgUrl
添加一些特殊的查詢參數(shù)可以更改資源被引入的方式:
// 顯式加載資源為一個(gè) URL
import assetAsURL from './asset.js?url'
// 以字符串形式加載資源
import assetAsString from './shader.glsl?raw'
// 加載為 Web Worker
import Worker from './worker.js?worker'
// 在構(gòu)建時(shí) Web Worker 內(nèi)聯(lián)為 base64 字符串
import InlineWorker from './worker.js?worker&inline'
更多細(xì)節(jié)請見 靜態(tài)資源處理。
JSON
JSON 可以被直接導(dǎo)入 —— 同樣支持具名導(dǎo)入:
// 導(dǎo)入整個(gè)對象
import json from './example.json'
// 對一個(gè)根字段使用具名導(dǎo)入 —— 有效幫助 Tree Shaking专挪!
import { field } from './example.json'
Glob 導(dǎo)入
Vite 支持使用特殊的 import.meta.glob 函數(shù)從文件系統(tǒng)導(dǎo)入多個(gè)模塊:
const modules = import.meta.glob('./dir/*.js')
以上將會(huì)被轉(zhuǎn)譯為下面的樣子:
// vite 生成的代碼
const modules = {
'./dir/foo.js': () => import('./dir/foo.js'),
'./dir/bar.js': () => import('./dir/bar.js')
}
你可以遍歷 modules 對象的 key 值來訪問相應(yīng)的模塊:
for (const path in modules) {
modules[path]().then((mod) => {
console.log(path, mod)
})
}
WebAssembly
預(yù)編譯的 .wasm 文件可以直接被導(dǎo)入 —— 默認(rèn)導(dǎo)出一個(gè)函數(shù)及志,返回值為所導(dǎo)出 wasm 實(shí)例對象的 Promise:...
Web Worker
一個(gè) web worker 腳本可以直接通過添加一個(gè) ?worker 或 ? shared worker 查詢參數(shù)來導(dǎo)入。默認(rèn)導(dǎo)出一個(gè)自定義的 worker 構(gòu)造器:
import MyWorker from './worker?worker'
const worker = new MyWorker()
注意寨腔,在開發(fā)過程中速侈,這依賴于瀏覽器原生支持,目前只在 Chrome 中適用迫卢,而在生產(chǎn)版本中倚搬,它已經(jīng)被編譯掉了。
構(gòu)建優(yōu)化
下面所羅列的功能會(huì)自動(dòng)應(yīng)用為構(gòu)建過程的一部分乾蛤,除非你想禁用它們每界,否則沒有必要顯式配置。
- CSS 代碼分割
- 預(yù)加載指令生成
- 異步 Chunk 加載優(yōu)化
在無優(yōu)化的情境下家卖,當(dāng)異步 chunk A 被導(dǎo)入時(shí)眨层,瀏覽器將必須請求和解析 A,然后它才能弄清楚它也需要共用 chunk C篡九。這會(huì)導(dǎo)致額外的網(wǎng)絡(luò)往返:Entry ---> A ---> C
Vite 將使用一個(gè)預(yù)加載步驟自動(dòng)重寫代碼谐岁,來分割動(dòng)態(tài)導(dǎo)入調(diào)用,以實(shí)現(xiàn)當(dāng) A 被請求時(shí)榛臼,C 也將 同時(shí) 被請求:Entry ---> (A + C)
C 也可能有更深的導(dǎo)入伊佃,在未優(yōu)化的場景中,這會(huì)導(dǎo)致更多的網(wǎng)絡(luò)往返沛善。Vite 的優(yōu)化會(huì)跟蹤所有的直接導(dǎo)入航揉,無論導(dǎo)入的深度如何,都能夠完全消除不必要的往返金刁。
使用插件
Vite 可以使用插件進(jìn)行擴(kuò)展帅涂,這得益于 Rollup 優(yōu)秀的插件接口設(shè)計(jì)和一部分 Vite 獨(dú)有的額外選項(xiàng)。這意味著 Vite 用戶可以利用 Rollup 插件的強(qiáng)大生態(tài)系統(tǒng)尤蛮,同時(shí)根據(jù)需要也能夠擴(kuò)展開發(fā)服務(wù)器和 SSR 功能媳友。
添加一個(gè)插件
若要使用一個(gè)插件,需要將它添加到項(xiàng)目的 devDependencies
并在 vite.config.js
配置文件中的 plugins
數(shù)組中引入它产捞。例如醇锚,要想為傳統(tǒng)瀏覽器提供支持,可以按下面這樣使用官方插件 @vitejs/plugin-legacy:
$ npm i -D @vitejs/plugin-legacy
// vite.config.js
import legacy from '@vitejs/plugin-legacy'
import { defineConfig } from 'vite'
export default defineConfig({
plugins: [
legacy({
targets: ['defaults', 'not IE 11']
})
]
})
查找插件
查看 Plugins 章節(jié) 獲取官方插件信息。社區(qū)插件列表請參見 awesome-vite焊唬。而對于兼容的 Rollup 插件恋昼,請查看 Vite Rollup 插件 獲取一個(gè)帶使用說明的兼容 Rollup 官方插件列表,若列表中沒有找到赶促,則請參閱 Rollup 插件兼容性章節(jié)液肌。
你也可以使用此 npm Vite 插件搜索鏈接 來找到一些遵循了 推薦約定 的 Vite 插件,或者通過 npm Rollup 插件搜索鏈接 獲取 Rollup 插件鸥滨。
強(qiáng)制插件排序
為了與某些 Rollup 插件兼容嗦哆,可能需要強(qiáng)制執(zhí)行插件的順序,或者只在構(gòu)建時(shí)使用婿滓。這應(yīng)該是 Vite 插件的實(shí)現(xiàn)細(xì)節(jié)吝秕。可以使用 enforce 修飾符來強(qiáng)制插件的位置:
- pre:在 Vite 核心插件之前調(diào)用該插件
- 默認(rèn):在 Vite 核心插件之后調(diào)用該插件
- post:在 Vite 構(gòu)建插件之后調(diào)用該插件
// vite.config.js
import image from '@rollup/plugin-image'
import { defineConfig } from 'vite'
export default defineConfig({
plugins: [
{
...image(),
enforce: 'pre'
}
]
})
查看 Plugins API Guide 獲取細(xì)節(jié)信息空幻,并在 Vite Rollup 插件 兼容性列表中注意 enforce
標(biāo)簽和流行插件的使用說明烁峭。
按需應(yīng)用
默認(rèn)情況下插件在開發(fā) (serve
) 和生產(chǎn) (build
) 模式中都會(huì)調(diào)用。如果插件在服務(wù)或構(gòu)建期間按需使用秕铛,請使用 apply
屬性指明它們僅在 'build' 或 'serve' 模式時(shí)調(diào)用:
// vite.config.js
import typescript2 from 'rollup-plugin-typescript2'
import { defineConfig } from 'vite'
export default defineConfig({
plugins: [
{
...typescript2(),
apply: 'build'
}
]
})
創(chuàng)建插件
閱讀 插件 API 指引 文檔了解如何創(chuàng)建插件约郁。
依賴預(yù)構(gòu)建
原因
這就是 Vite 執(zhí)行的所謂的“依賴預(yù)構(gòu)建”。這個(gè)過程有兩個(gè)目的:
- CommonJS 和 UMD 兼容性
- 性能
Vite 將有許多內(nèi)部模塊的 ESM 依賴關(guān)系轉(zhuǎn)換為單個(gè)模塊但两,以提高后續(xù)頁面加載性能鬓梅。
自動(dòng)依賴搜尋
如果沒有找到相應(yīng)的緩存,Vite 將抓取你的源碼谨湘,并自動(dòng)尋找引入的依賴項(xiàng)(即 "bare import"绽快,表示期望從 node_modules 解析),并將這些依賴項(xiàng)作為預(yù)構(gòu)建包的入口點(diǎn)紧阔。預(yù)構(gòu)建通過 esbuild 執(zhí)行坊罢,所以它通常非常快擅耽。在服務(wù)器已經(jīng)啟動(dòng)之后活孩,如果遇到一個(gè)新的依賴關(guān)系導(dǎo)入,而這個(gè)依賴關(guān)系還沒有在緩存中乖仇,Vite 將重新運(yùn)行依賴構(gòu)建進(jìn)程并重新加載頁面憾儒。
Monorepo 和鏈接依賴
略過
自定義行為
默認(rèn)的依賴項(xiàng)發(fā)現(xiàn)為啟發(fā)式可能并不總是可取的。在你想要顯式地從列表中包含/排除依賴項(xiàng)的情況下, 請使用 optimizeDeps
配置項(xiàng)乃沙。
緩存
- 文件系統(tǒng)緩存
Vite 會(huì)將預(yù)構(gòu)建的依賴緩存到 node_modules/.vite起趾。它根據(jù)幾個(gè)源來決定是否需要重新運(yùn)行預(yù)構(gòu)建步驟:
- package.json 中的 dependencies 列表
- 包管理器的 lockfile,例如 package-lock.json, yarn.lock警儒,或者 pnpm-lock.yaml
- 可能在 vite.config.js 相關(guān)字段中配置過的
只有在上述其中一項(xiàng)發(fā)生更改時(shí)训裆,才需要重新運(yùn)行預(yù)構(gòu)建。
如果出于某些原因,你想要強(qiáng)制 Vite 重新構(gòu)建依賴缭保,你可以用 --force 命令行選項(xiàng)啟動(dòng)開發(fā)服務(wù)器,或者手動(dòng)刪除 node_modules/.vite 目錄蝙茶。
- 瀏覽器緩存
解析后的依賴請求會(huì)以 HTTP 頭 max-age=31536000,immutable 強(qiáng)緩存艺骂,以提高在開發(fā)時(shí)的頁面重載性能。一旦被緩存隆夯,這些請求將永遠(yuǎn)不會(huì)再到達(dá)開發(fā)服務(wù)器钳恕。如果安裝了不同的版本(這反映在包管理器的 lockfile 中),則附加的版本 query 會(huì)自動(dòng)使它們失效蹄衷。如果你想通過本地編輯來調(diào)試依賴項(xiàng)忧额,你可以:
- 通過瀏覽器調(diào)試工具的 Network 選項(xiàng)卡暫時(shí)禁用緩存;
- 重啟 Vite dev server愧口,并添加 --force 命令以重新構(gòu)建依賴睦番;
- 重新載入頁面。
靜態(tài)資源處理
- 相關(guān): 公共基礎(chǔ)路徑
- 相關(guān):
assetsInclude
配置項(xiàng)
將資源引入為 URL
服務(wù)時(shí)引入一個(gè)靜態(tài)資源會(huì)返回解析后的公共路徑:
import imgUrl from './img.png'
document.getElementById('hero-img').src = imgUrl
例如耍属,imgUrl 在開發(fā)時(shí)會(huì)是 /img.png托嚣,在生產(chǎn)構(gòu)建后會(huì)是 /assets/img.2d8efhg.png。
行為類似于 Webpack 的 file-loader
厚骗。區(qū)別在于導(dǎo)入既可以使用絕對公共路徑(基于開發(fā)期間的項(xiàng)目根路徑)示启,也可以使用相對路徑。
-
url()
在 CSS 中的引用也以同樣的方式處理领舰。 - 如果 Vite 使用了 Vue 插件夫嗓,Vue SFC 模板中的資源引用都將自動(dòng)轉(zhuǎn)換為導(dǎo)入。
- 常見的圖像冲秽、媒體和字體文件類型被自動(dòng)檢測為資源舍咖。你可以使用
assetsInclude
選項(xiàng) 擴(kuò)展內(nèi)部列表。 - 引用的資源作為構(gòu)建資源圖的一部分包括在內(nèi)锉桑,將生成散列文件名谎仲,并可以由插件進(jìn)行處理以進(jìn)行優(yōu)化。
- 較小的資源體積小于
assetsInlineLimit
選項(xiàng)值 則會(huì)被內(nèi)聯(lián)為 base64 data URL刨仑。
顯式 URL 引入
未被包含在內(nèi)部列表或 assetsInclude
中的資源郑诺,可以使用 ?url
后綴顯式導(dǎo)入為一個(gè) URL。這十分有用杉武,例如辙诞,要導(dǎo)入 Houdini Paint Worklets 時(shí):
import workletURL from 'extra-scalloped-border/worklet.js?url'
CSS.paintWorklet.addModule(workletURL)
// 顯式加載資源為一個(gè) URL
import assetAsURL from './asset.js?url'
// 以字符串形式加載資源
import assetAsString from './shader.glsl?raw'
// 在生產(chǎn)構(gòu)建中將會(huì)分離出 chunk
import Worker from './shader.js?worker'
const worker = new Worker()
// sharedworker
import SharedWorker from './shader.js?sharedworker'
const sharedWorker = new SharedWorker()
// 內(nèi)聯(lián)為 base64 字符串
import InlineWorker from './shader.js?worker&inline'
查看 Web Worker 小節(jié) 獲取更多細(xì)節(jié)。
public 目錄
如果你有下列這些資源:
- 不會(huì)被源碼引用(例如
robots.txt
) - 必須保持原有文件名(沒有經(jīng)過 hash)
- ...或者你壓根不想引入該資源轻抱,只是想得到其 URL飞涂。
那么你可以將該資源放在指定的 public
目錄中,它應(yīng)位于你的項(xiàng)目根目錄。該目錄中的資源在開發(fā)時(shí)能直接通過 /
根路徑訪問到较店,并且打包時(shí)會(huì)被完整復(fù)制到目標(biāo)目錄的根目錄下士八。
目錄默認(rèn)是 <root>/public
,但可以通過 publicDir
選項(xiàng) 來配置梁呈。
請注意:
- 引入
public
中的資源永遠(yuǎn)應(yīng)該使用根絕對路徑
, 舉例public/icon.png
應(yīng)該在源碼中被引用為/icon.png
婚度。 -
public
中的資源不應(yīng)該被 JavaScript 文件引用。
new URL(url, import.meta.url)
import.meta.url 是一個(gè) ESM 的原生功能官卡,會(huì)暴露當(dāng)前模塊的 URL蝗茁。將它與原生的 URL 構(gòu)造器 組合使用,在一個(gè) JavaScript 模塊中寻咒,通過相對路徑我們就能得到一個(gè)被完整解析的靜態(tài)資源 URL:
const imgUrl = new URL('./img.png', import.meta.url).href
document.getElementById('hero-img').src = imgUrl
這在現(xiàn)代瀏覽器中能夠原生使用 - 實(shí)際上哮翘,Vite 并不需要在開發(fā)階段處理這些代碼!
這個(gè)模式同樣還可以通過字符串模板支持動(dòng)態(tài) URL:
function getImageUrl(name) {
return new URL(`./dir/${name}.png`, import.meta.url).href
}
在生產(chǎn)構(gòu)建時(shí)毛秘,Vite 才會(huì)進(jìn)行必要的轉(zhuǎn)換保證 URL 在打包和資源哈希后仍指向正確的地址饭寺。
注意:無法在 SSR 中使用
如果你正在以服務(wù)端渲染模式使用 Vite 則此模式不支持,因?yàn)?import.meta.url
在瀏覽器和 Node.js 中有不同的語義叫挟。服務(wù)端的產(chǎn)物也無法預(yù)先確定客戶端主機(jī) URL佩研。
構(gòu)建生產(chǎn)版本
當(dāng)需要將應(yīng)用部署到生產(chǎn)環(huán)境時(shí),只需運(yùn)行 vite build
命令霞揉。默認(rèn)情況下旬薯,它使用 <root>/index.html
作為其構(gòu)建入口點(diǎn),并生成能夠靜態(tài)部署的應(yīng)用程序包适秩。請查閱 部署靜態(tài)站點(diǎn) 獲取常見服務(wù)的部署指引绊序。
瀏覽器兼容性
用于生產(chǎn)環(huán)境的構(gòu)建包會(huì)假設(shè)目標(biāo)瀏覽器支持現(xiàn)代 JavaScript 語法。默認(rèn)情況下秽荞,Vite 的目標(biāo)瀏覽器是指能夠 支持原生 ESM script 標(biāo)簽 和 支持原生 ESM 動(dòng)態(tài)導(dǎo)入 的骤公。作為參考,Vite 使用這個(gè) browserslist 作為查詢標(biāo)準(zhǔn):defaults and supports es6-module and supports es6-module-dynamic-import, not opera > 0, not samsung > 0, not and_qq > 0
你也可以通過 build.target
配置項(xiàng) 指定構(gòu)建目標(biāo)扬跋,最低支持 es2015
阶捆。
請注意,默認(rèn)情況下 Vite 只處理語法轉(zhuǎn)譯钦听,且 默認(rèn)不包含任何 polyfill洒试。你可以前往 Polyfill.io 查看,這是一個(gè)基于用戶瀏覽器 User-Agent 字符串自動(dòng)生成 polyfill 包的服務(wù)朴上。
傳統(tǒng)瀏覽器可以通過插件 @vitejs/plugin-legacy 來支持垒棋,它將自動(dòng)生成傳統(tǒng)版本的 chunk 及與其相對應(yīng) ES 語言特性方面的 polyfill。兼容版的 chunk 只會(huì)在不支持原生 ESM 的瀏覽器中進(jìn)行按需加載痪宰。
公共基礎(chǔ)路徑
- 相關(guān)內(nèi)容:靜態(tài)資源處理
如果你需要在嵌套的公共路徑下部署項(xiàng)目叼架,只需指定 base
配置項(xiàng)畔裕,然后所有資源的路徑都將據(jù)此配置重寫。這個(gè)選項(xiàng)也可以通過命令行參數(shù)指定乖订,例如 vite build --base=/my/public/path/
扮饶。
由 JS 引入的資源 URL,CSS 中的 url()
引用以及 .html
文件中引用的資源在構(gòu)建過程中都會(huì)自動(dòng)調(diào)整乍构,以適配此選項(xiàng)甜无。
當(dāng)然,情況也有例外蜡吧,當(dāng)訪問過程中需要使用動(dòng)態(tài)連接的 url 時(shí),可以使用全局注入的 import.<wbr style="box-sizing: border-box;">meta.env.BASE_URL
變量占键,它的值為公共基礎(chǔ)路徑昔善。注意,這個(gè)變量在構(gòu)建時(shí)會(huì)被靜態(tài)替換畔乙,因此君仆,它必須按 import.<wbr style="box-sizing: border-box;">meta.env.BASE_URL
的原樣出現(xiàn)(例如 import.<wbr style="box-sizing: border-box;">meta.env['BASE_URL']
是無效的)
自定義構(gòu)建
略過
文件變化時(shí)重新構(gòu)建
略過
多頁面應(yīng)用模式
假設(shè)你有下面這樣的項(xiàng)目文件結(jié)構(gòu)
├── package.json
├── vite.config.js
├── index.html
├── main.js
└── nested
├── index.html
└── nested.js
在開發(fā)過程中,簡單地導(dǎo)航或鏈接到 /nested/ - 將會(huì)按預(yù)期工作牲距,與正常的靜態(tài)文件服務(wù)器表現(xiàn)一致返咱。
在構(gòu)建過程中,你只需指定多個(gè) .html 文件作為入口點(diǎn)即可:
// vite.config.js
const { resolve } = require('path')
const { defineConfig } = require('vite')
module.exports = defineConfig({
build: {
rollupOptions: {
input: {
main: resolve(__dirname, 'index.html'),
nested: resolve(__dirname, 'nested/index.html')
}
}
}
})
如果你指定了另一個(gè)根目錄牍鞠,請記住咖摹,在解析輸入路徑時(shí),__dirname 的值將仍然是 vite.config.js 文件所在的目錄难述。因此萤晴,你需要把對應(yīng)入口文件的 root 的路徑添加到 resolve 的參數(shù)中。
庫模式
當(dāng)你開發(fā)面向?yàn)g覽器的庫時(shí)胁后,你可能會(huì)將大部分時(shí)間花在該庫的測試/演示頁面上店读。在 Vite 中你可以使用 index.html 獲得如絲般順滑的開發(fā)體驗(yàn)。
略過
部署靜態(tài)站點(diǎn)
本指南建立在以下幾個(gè)假設(shè)基礎(chǔ)之上:
- 你正在使用的是默認(rèn)的構(gòu)建輸出路徑(
dist
)攀芯。這個(gè)路徑 可以通過build.outDir
更改屯断,在這種情況下,你可以從這篇指南中找到出所需的指引侣诺。 - 你正在使用 NPM殖演;或者 Yarn 等其他可以運(yùn)行下面的腳本指令的包管理工具。
- Vite 已作為一個(gè)本地開發(fā)依賴(dev dependency)安裝在你的項(xiàng)目中年鸳,并且你已經(jīng)配置好了如下的 npm scripts:
{
"scripts": {
"build": "vite build",
"preview": "vite preview"
}
}
值得注意的是 vite preview
用作預(yù)覽本地構(gòu)建剃氧,而不應(yīng)直接作為生產(chǎn)服務(wù)器。
注意
本篇指南提供了部署 Vite 靜態(tài)站點(diǎn)的說明阻星。Vite 也對服務(wù)端渲染(SSR)有了實(shí)驗(yàn)性的支持朋鞍。SSR 是指支持在 Node 中運(yùn)行相應(yīng)應(yīng)用的前端框架已添,預(yù)渲染成 HTML,最后在客戶端激活(hydrate)滥酥。查看 SSR 指南 了解更多細(xì)節(jié)更舞。另一方面,如果你在尋找與傳統(tǒng)服務(wù)端框架集成的方式坎吻,那么請查看 后端集成 章節(jié)缆蝉。
構(gòu)建應(yīng)用
你可以運(yùn)行 npm run build
命令來執(zhí)行應(yīng)用的構(gòu)建。默認(rèn)情況下瘦真,構(gòu)建會(huì)輸出到 dist
文件夾中刊头。你可以部署這個(gè) dist
文件夾到任何你喜歡的平臺。
本地測試應(yīng)用
當(dāng)你構(gòu)建完成應(yīng)用后诸尽,你可以通過運(yùn)行 npm run preview
命令原杂,在本地測試該應(yīng)用。
vite preview
命令會(huì)在本地啟動(dòng)一個(gè)靜態(tài) Web 服務(wù)器您机,將 dist
文件夾運(yùn)行在 http://localhost:5000穿肄。這樣在本地環(huán)境下查看該構(gòu)建產(chǎn)物是否正常可用就方便了际看。
你可以通過 --port 參數(shù)來配置服務(wù)的運(yùn)行端口咸产。package.json { "scripts": { "preview": "vite preview --port 8080" } }
GitHub Pages
部署
騰訊云-Webify
- 開通云托管
登錄騰訊云https://webify.cloudbase.net/, 我是用微信登錄的,實(shí)用認(rèn)證后開啟服務(wù)仲闽,“新建應(yīng)用”
https://console.cloud.tencent.com/webify/index
image.png
應(yīng)用創(chuàng)建之后脑溢,等待構(gòu)建、部署完畢赖欣,便可以通過應(yīng)用的默認(rèn)域名(xxx.app.tcloudbase.com)來訪問應(yīng)用焚志。
我的是https://vite-henrypt-0gitm56jd2697f0e-1310395618.ap-shanghai.app.tcloudbase.com/
注:創(chuàng)建云托管成功不久,我的信息就被賣了畏鼓,有人給我打電話問我注冊云托管酱酬,要不要買服務(wù)器!
- 使用xxx.sh腳本(測試沒成功)
在你的項(xiàng)目中云矫,創(chuàng)建一個(gè) deploy.sh 腳本膳沽,包含以下內(nèi)容(注意高亮的行,按需使用)让禀,運(yùn)行腳本來部署站點(diǎn):
#!/usr/bin/env sh
# 發(fā)生錯(cuò)誤時(shí)終止
set -e
# 構(gòu)建
npm run build
# 進(jìn)入構(gòu)建文件夾
cd dist
# 如果你要部署到自定義域名
# echo 'www.example.com' > CNAME
# git init
git add -A
git commit -m "deploy"
# 如果你要部署在 https://<USERNAME>.github.io
# git push -f git@github.com:<USERNAME>/<USERNAME>.github.io.git main
# 如果你要部署在 https://<USERNAME>.github.io/<REPO>
# git push -f git@github.com:<USERNAME>/<REPO>.git master:branch-test1 [master是默認(rèn)主分支; branch-test1是子分支]
git push -f https://gitee.com/henrypt1213/vite-henrypt master:branch-test1
cd -
*** .sh文件執(zhí)行 ***
image.png
image.png
環(huán)境變量和模式
環(huán)境變量
Vite 在一個(gè)特殊的 import.meta.env
對象上暴露環(huán)境變量验残。這里有一些在所有情況下都可以使用的內(nèi)建變量:
import.meta.env.MODE
: {string} 應(yīng)用運(yùn)行的模式培己。import.meta.env.BASE_URL
: {string} 部署應(yīng)用時(shí)的基本 URL盈咳。他由base
配置項(xiàng)決定油够。import.meta.env.PROD
: {boolean} 應(yīng)用是否運(yùn)行在生產(chǎn)環(huán)境。import.meta.env.DEV
: {boolean} 應(yīng)用是否運(yùn)行在開發(fā)環(huán)境 (永遠(yuǎn)與import.<wbr style="box-sizing: border-box;">meta.env.PROD
相反)腮敌。
生產(chǎn)環(huán)境替換
在生產(chǎn)環(huán)境中阱当,這些環(huán)境變量會(huì)在構(gòu)建時(shí)被靜態(tài)替換俏扩,因此,在引用它們時(shí)請使用完全靜態(tài)的字符串弊添。動(dòng)態(tài)的 key 將無法生效录淡。例如,動(dòng)態(tài) key 取值 import.meta.env[key] 是無效的油坝。
它還將替換出現(xiàn)在 JavaScript 和 Vue 模板中的字符串嫉戚。這本應(yīng)是非常少見的,但也可能是不小心為之的澈圈。在這種情況下你可能會(huì)看到類似 Missing Semicolon
或 Unexpected token
等錯(cuò)誤彬檀,例如當(dāng) "process.env.NODE_ENV"
被替換為 ""development": "
。有一些方法可以避免這個(gè)問題:
對于 JavaScript 字符串瞬女,你可以使用 unicode 零寬度空格
\u200b
(一個(gè)看不見的分隔符)來分割這個(gè)字符串窍帝,例如:'import.meta.env.MODE'
。對于 Vue 模板或其他編譯到 JavaScript 字符串的 HTML拆魏,你可以使用
<wbr>
標(biāo)簽盯桦,例如:import.meta.env.MODE
慈俯。
略過
服務(wù)端渲染
實(shí)驗(yàn)性
SSR 支持還處于試驗(yàn)階段渤刃,你可能會(huì)遇到 bug 和不受支持的用例。請考慮你可能承擔(dān)的風(fēng)險(xiǎn)贴膘。
注意
SSR 特別指支持在 Node.js 中運(yùn)行相同應(yīng)用程序的前端框架(例如 React卖子、Preact、Vue 和 Svelte)刑峡,將其預(yù)渲染成 HTML洋闽,最后在客戶端進(jìn)行注水化處理。如果你正在尋找與傳統(tǒng)服務(wù)器端框架的集成突梦,請查看 后端集成指南诫舅。
下面的指南還假定你在選擇的框架中有使用 SSR 的經(jīng)驗(yàn),并且只關(guān)注特定于 Vite 的集成細(xì)節(jié)宫患。
示例項(xiàng)目
Vite 為服務(wù)端渲染(SSR)提供了內(nèi)建支持刊懈。這里的 Vite 范例包含了 Vue 3 和 React 的 SSR 設(shè)置示例,可以作為本指南的參考:
源碼結(jié)構(gòu)
一個(gè)典型的 SSR 應(yīng)用應(yīng)該有如下的源文件結(jié)構(gòu):
- index.html
- src/
- main.js # 導(dǎo)出環(huán)境無關(guān)的(通用的)應(yīng)用代碼
- entry-client.js # 將應(yīng)用掛載到一個(gè) DOM 元素上
- entry-server.js # 使用某框架的 SSR API 渲染該應(yīng)用
index.html 將需要引用 entry-client.js 并包含一個(gè)占位標(biāo)記供給服務(wù)端渲染時(shí)注入:
<div id="app"><!--ssr-outlet--></div>
<script type="module" src="/src/entry-client.js"></script>
你可以使用任何你喜歡的占位標(biāo)記來替代 娃闲,只要它能夠被正確替換虚汛。
情景邏輯
如果需要執(zhí)行 SSR 和客戶端間情景邏輯,可以使用:
if ( import.meta.env.SSR ) {
// ... 僅在服務(wù)端執(zhí)行的邏輯
}
這是在構(gòu)建過程中被靜態(tài)替換的皇帮,因此它將允許對未使用的條件分支進(jìn)行搖樹優(yōu)化卷哩。
設(shè)置開發(fā)服務(wù)器
在構(gòu)建 SSR 應(yīng)用程序時(shí),你可能希望完全控制主服務(wù)器属拾,并將 Vite 與生產(chǎn)環(huán)境脫鉤将谊。因此冷溶,建議以中間件模式使用 Vite。下面是一個(gè)關(guān)于 express 的例子:
# server.js
const fs = require('fs')
const path = require('path')
const express = require('express')
const { createServer: createViteServer } = require('vite')
async function createServer() {
const app = express()
// 以中間件模式創(chuàng)建 Vite 應(yīng)用瓢娜,這將禁用 Vite 自身的 HTML 服務(wù)邏輯
// 并讓上級服務(wù)器接管控制
//
// 如果你想使用 Vite 自己的 HTML 服務(wù)邏輯(將 Vite 作為
// 一個(gè)開發(fā)中間件來使用)挂洛,那么這里請用 'html'
const vite = await createViteServer({
server: { middlewareMode: 'ssr' }
})
// 使用 vite 的 Connect 實(shí)例作為中間件
app.use(vite.middlewares)
app.use('*', async (req, res) => {
// 服務(wù) index.html - 下面我們來處理這個(gè)問題
})
app.listen(3000)
}
createServer()
這里 vite
是 ViteDevServer 的一個(gè)實(shí)例。vite.middlewares
是一個(gè) Connect 實(shí)例眠砾,它可以在任何一個(gè)兼容 connect 的 Node.js 框架中被用作一個(gè)中間件虏劲。
下一步是實(shí)現(xiàn) *
處理程序供給服務(wù)端渲染的 HTML:
app.use('*', async (req, res) => {
const url = req.originalUrl
try {
// 1. 讀取 index.html
let template = fs.readFileSync(
path.resolve(__dirname, 'index.html'),
'utf-8'
)
// 2. 應(yīng)用 Vite HTML 轉(zhuǎn)換。這將會(huì)注入 Vite HMR 客戶端褒颈,
// 同時(shí)也會(huì)從 Vite 插件應(yīng)用 HTML 轉(zhuǎn)換柒巫。
// 例如:@vitejs/plugin-react-refresh 中的 global preambles
template = await vite.transformIndexHtml(url, template)
// 3. 加載服務(wù)器入口。vite.ssrLoadModule 將自動(dòng)轉(zhuǎn)換
// 你的 ESM 源碼使之可以在 Node.js 中運(yùn)行谷丸!無需打包
// 并提供類似 HMR 的根據(jù)情況隨時(shí)失效堡掏。
const { render } = await vite.ssrLoadModule('/src/entry-server.js')
// 4. 渲染應(yīng)用的 HTML。這假設(shè) entry-server.js 導(dǎo)出的 `render`
// 函數(shù)調(diào)用了適當(dāng)?shù)?SSR 框架 API刨疼。
// 例如 ReactDOMServer.renderToString()
const appHtml = await render(url)
// 5. 注入渲染后的應(yīng)用程序 HTML 到模板中泉唁。
const html = template.replace(`<!--ssr-outlet-->`, appHtml)
// 6. 返回渲染后的 HTML。
res.status(200).set({ 'Content-Type': 'text/html' }).end(html)
} catch (e) {
// 如果捕獲到了一個(gè)錯(cuò)誤揩慕,讓 Vite 來修復(fù)該堆棧亭畜,這樣它就可以映射回
// 你的實(shí)際源碼中。
vite.ssrFixStacktrace(e)
console.error(e)
res.status(500).end(e.message)
}
})
package.json 中的 dev 腳本也應(yīng)該相應(yīng)地改變迎卤,使用服務(wù)器腳本:
"scripts": {
- "dev": "vite"
+ "dev": "node server"
}
生產(chǎn)環(huán)境構(gòu)建
為了將 SSR 項(xiàng)目交付生產(chǎn)拴鸵,我們需要:
- 正常生成一個(gè)客戶端構(gòu)建;
- 再生成一個(gè) SSR 構(gòu)建蜗搔,使其通過
require()
直接加載劲藐,這樣便無需再使用 Vite 的ssrLoadModule
;
package.json
中的腳本應(yīng)該看起來像這樣:
{
"scripts": {
"dev": "node server",
"build:client": "vite build --outDir dist/client",
"build:server": "vite build --outDir dist/server --ssr src/entry-server.js "
}
}
注意使用 --ssr
標(biāo)志表明這將會(huì)是一個(gè) SSR 構(gòu)建樟凄。同時(shí)需要指定 SSR 的入口聘芜。
接著,在 server.js
中缝龄,通過 process.env.NODE_ENV
條件分支汰现,需要添加一些用于生產(chǎn)環(huán)境的特定邏輯:
使用
dist/client/index.html
作為模板,而不是根目錄的index.html
二拐,因?yàn)榍罢甙说娇蛻舳藰?gòu)建的正確資源鏈接服鹅。使用
require('./dist/server/entry-server.js')
,而不是await vite.ssrLoadModule('/src/entry-server.js')
(前者是 SSR 構(gòu)建后的最終結(jié)果)百新。將
vite
開發(fā)服務(wù)器的創(chuàng)建和所有使用都移到 dev-only 條件分支后面企软,然后添加靜態(tài)文件服務(wù)中間件來服務(wù)dist/client
中的文件。
可以在此參考 Vue 和 React 的設(shè)置范例饭望。
生成預(yù)加載指令
略過
預(yù)渲染 / SSG
如果預(yù)先知道某些路由所需的路由和數(shù)據(jù)仗哨,我們可以使用與生產(chǎn)環(huán)境 SSR 相同的邏輯將這些路由預(yù)先渲染到靜態(tài) HTML 中形庭。這也被視為一種靜態(tài)站點(diǎn)生成(SSG)的形式。查看 示例渲染代碼 獲取有效示例厌漂。
SSR 外部化
略過
SSR 專有插件邏輯
一些框架萨醒,如 Vue 或 Svelte,會(huì)根據(jù)客戶端渲染和服務(wù)端渲染的區(qū)別苇倡,將組件編譯成不同的格式富纸。可以向以下的插件鉤子中旨椒,給 Vite 傳遞額外的 options 對象晓褪,對象中包含 ssr 屬性來支持根據(jù)情景轉(zhuǎn)換:
- resolveId
- load
- transform
...
SSR Target
SSR 構(gòu)建的默認(rèn)目標(biāo)為 node 環(huán)境,但你也可以讓服務(wù)運(yùn)行在 Web Worker 上综慎。每個(gè)平臺的打包條目解析是不同的涣仿。你可以將ssr.target 設(shè)置為 webworker,以將目標(biāo)配置為 Web Worker示惊。
SSR Bundle
在某些如 webworker 運(yùn)行時(shí)等特殊情況中好港,你可能想要將你的 SSR 打包成單個(gè) JavaScript 文件。你可以通過設(shè)置 ssr.noExternal 為 true 來啟用這個(gè)行為米罚。這將會(huì)做兩件事:
- 將所有依賴視為 noExternal(非外部化)
- 若任何 Node.js 內(nèi)置內(nèi)容被引入钧汹,將拋出一個(gè)錯(cuò)誤
后端集成
如果你想使用傳統(tǒng)的后端(如 Rails, Laravel)來服務(wù) HTML,但使用 Vite 來服務(wù)其他資源阔拳,可以查看在 Awesome Vite 上的已有的后端集成列表崭孤。
如果你需要自定義集成类嗤,你可以按照本指南的步驟配置它:
略過
與其它非打包解決方案比較
略過
插件 API
略過
HMR API
注意
這里是客戶端 HMR API糊肠。若要在插件中處理 HMR 更新,詳見 handleHotUpdate遗锣。
手動(dòng) HMR API 主要用于框架和工具作者货裹。作為最終用戶,HMR 可能已經(jīng)在特定于框架的啟動(dòng)器模板中為你處理過了精偿。
Vite 通過特殊的 import.meta.hot 對象暴露手動(dòng) HMR API弧圆。
略過
JavaScript API
Vite 的 JavaScript API 是完全類型化的,我們推薦使用 TypeScript 或者在 VSCode 中啟用 JS 類型檢查來利用智能提示和類型校驗(yàn)笔咽。
createServer 類型簽名:
InlineConfig
#
ViteDevServer
build
preview
resolveConfig
transformWithEsbuild
配置 Vite
配置文件解析
當(dāng)以命令行方式運(yùn)行 vite
時(shí)搔预,Vite 會(huì)自動(dòng)解析 項(xiàng)目根目錄 下名為 vite.config.js
的文件
配置智能提示
因?yàn)?Vite 本身附帶 Typescript 類型,所以你可以通過 IDE 和 jsdoc 的配合來實(shí)現(xiàn)智能提示
情景配置
如果配置文件需要基于(dev
/serve
或 build
)命令或者不同的 模式 來決定選項(xiàng)叶组,則可以選擇導(dǎo)出這樣一個(gè)函數(shù)
異步配置
共享配置
vite.config.js的全部配置都在這里
開發(fā)服務(wù)器選項(xiàng)
構(gòu)建選項(xiàng)
預(yù)覽選項(xiàng)
依賴優(yōu)化選項(xiàng)
SSR 選項(xiàng)
插件
官方插件#
@vitejs/plugin-vue#
- 提供 Vue 3 單文件組件支持
@vitejs/plugin-vue-jsx#
- 提供 Vue 3 JSX 支持(通過 專用的 Babel 轉(zhuǎn)換插件)拯田。
@vitejs/plugin-react#
- 提供完整的 React 支持
@vitejs/plugin-legacy#
- 為打包后的文件提供傳統(tǒng)瀏覽器兼容性支持
Rollup 插件
Vite 插件 是 Rollup 插件接口的一種擴(kuò)展。查看 Rollup 插件兼容性章節(jié) 獲取更多信息甩十。