後端整合
注意
如果你希望使用傳統的後端(例如 Rails、Laravel)來渲染 HTML,但使用 Vite 來提供資源服務,請檢視 Awesome Vite 中列出的現有整合。
如果你需要自定義整合,可以按照本指南中的步驟進行手動配置。
在你的 Vite 配置檔案中,配置入口點並啟用構建清單(build manifest)
jsexport defaultdefineConfig({server: {cors: { // the origin you will be accessing via browserorigin: 'http://my-backend.example.com', }, },build: { // generate .vite/manifest.json in outDirmanifest: true,rollupOptions: { // overwrite default .html entryinput: '/path/to/main.js', }, }, })如果你沒有停用 module preload polyfill,你還需要在入口檔案中匯入該 polyfill
js// add the beginning of your app entry import 'vite/modulepreload-polyfill'在開發過程中,請在伺服器的 HTML 模板中注入以下內容(將
https://:5173替換為 Vite 執行的本地 URL)html<!-- if development --> <script type="module" src="https://:5173/@vite/client"></script> <script type="module" src="https://:5173/main.js"></script>為了正確提供資源服務,你有兩個選擇
- 確保伺服器配置為將靜態資源請求代理到 Vite 伺服器
- 設定
server.origin,以便生成的資源 URL 將使用後端伺服器 URL 解析,而不是使用相對路徑
這對於圖片等資源的正常載入是必需的。
注意:如果你在使用帶有
@vitejs/plugin-react的 React,你還需要在上述指令碼之前新增此內容,因為該外掛無法修改你所提供的 HTML(將https://:5173替換為 Vite 執行的本地 URL)html<script type="module"> import RefreshRuntime from 'https://:5173/@react-refresh' RefreshRuntime.injectIntoGlobalHook(window) window.$RefreshReg$ = () => {} window.$RefreshSig$ = () => (type) => type window.__vite_plugin_react_preamble_installed__ = true </script>在生產環境中,執行
vite build後,會在其他資原始檔旁邊生成一個.vite/manifest.json檔案。清單檔案的示例如下json{ "_shared-B7PI925R.js": { "file": "assets/shared-B7PI925R.js", "name": "shared", "css": ["assets/shared-ChJ_j-JJ.css"] }, "_shared-ChJ_j-JJ.css": { "file": "assets/shared-ChJ_j-JJ.css", "src": "_shared-ChJ_j-JJ.css" }, "logo.svg": { "file": "assets/logo-BuPIv-2h.svg", "src": "logo.svg" }, "baz.js": { "file": "assets/baz-B2H3sXNv.js", "name": "baz", "src": "baz.js", "isDynamicEntry": true }, "views/bar.js": { "file": "assets/bar-gkvgaI9m.js", "name": "bar", "src": "views/bar.js", "isEntry": true, "imports": ["_shared-B7PI925R.js"], "dynamicImports": ["baz.js"] }, "views/foo.js": { "file": "assets/foo-BRBmoGS9.js", "name": "foo", "src": "views/foo.js", "isEntry": true, "imports": ["_shared-B7PI925R.js"], "css": ["assets/foo-5UjPuW-k.css"] } }該清單將原始檔對映到它們的構建輸出及依賴項
清單具有
Record<name, chunk>結構,其中每個 chunk 都遵循ManifestChunk介面tsinterface ManifestChunk { /** * The input file name of this chunk / asset if known */ src?: string /** * The output file name of this chunk / asset */ file: string /** * The list of CSS files imported by this chunk */ css?: string[] /** * The list of asset files imported by this chunk, excluding CSS files */ assets?: string[] /** * Whether this chunk or asset is an entry point */ isEntry?: boolean /** * The name of this chunk / asset if known */ name?: string /** * Whether this chunk is a dynamic entry point * * This field is only present in JS chunks. */ isDynamicEntry?: boolean /** * The list of statically imported chunks by this chunk * * The values are the keys of the manifest. This field is only present in JS chunks. */ imports?: string[] /** * The list of dynamically imported chunks by this chunk * * The values are the keys of the manifest. This field is only present in JS chunks. */ dynamicImports?: string[] }清單中的每個條目代表以下內容之一
- 入口 chunk(Entry chunks):由
build.rollupOptions.input中指定的檔案生成。這些 chunk 的isEntry: true,其鍵是專案根目錄的相對源路徑。 - 動態入口 chunk(Dynamic entry chunks):由動態匯入生成。這些 chunk 的
isDynamicEntry: true,其鍵是專案根目錄的相對源路徑。 - 非入口 chunk(Non-entry chunks):其鍵是生成檔案的基本名稱,並帶有
_字首。 - 資源 chunk(Asset chunks):由匯入的資源(如圖片、字型)生成。其鍵是專案根目錄的相對源路徑。
- CSS 檔案:當
build.cssCodeSplit為false時,會生成一個帶有鍵style.css的單個 CSS 檔案。當build.cssCodeSplit不為false時,鍵的生成方式類似於 JS chunk(即入口 chunk 不會帶有_字首,而非入口 chunk 則會帶有_字首)。
JS chunk(除資源或 CSS 以外的 chunk)將包含其靜態和動態匯入的資訊(兩者均為對映到清單中相應 chunk 的鍵)。如果 chunk 有對應的 CSS 和資原始檔,它們也會被列出。
- 入口 chunk(Entry chunks):由
你可以使用此檔案來渲染帶有雜湊檔名的連結或預載入指令。
以下是渲染正確連結的 HTML 模板示例。此處的語法僅供參考,請替換為你所使用的伺服器模板語言。
importedChunks函式僅為演示說明,Vite 未提供該函式。html<!-- if production --> <!-- for cssFile of manifest[name].css --> <link rel="stylesheet" href="/{{ cssFile }}" /> <!-- for chunk of importedChunks(manifest, name) --> <!-- for cssFile of chunk.css --> <link rel="stylesheet" href="/{{ cssFile }}" /> <script type="module" src="/{{ manifest[name].file }}"></script> <!-- for chunk of importedChunks(manifest, name) --> <link rel="modulepreload" href="/{{ chunk.file }}" />具體來說,生成 HTML 的後端在給定清單檔案和入口點時,應包含以下標籤。注意,為了獲得最佳效能,建議遵循此順序
- 為入口 chunk 的
css列表中的每個檔案(如果存在)新增一個<link rel="stylesheet">標籤 - 遞迴遍歷入口點
imports列表中的所有 chunk,併為每個匯入 chunk 的css列表中的每個 CSS 檔案(如果存在)新增一個<link rel="stylesheet">標籤。 - 為入口 chunk 的
file鍵新增一個標籤。對於 JavaScript,這可以是<script type="module">;對於 CSS,則為<link rel="stylesheet">。 - 可選地,為每個匯入的 JavaScript chunk 的
file新增<link rel="modulepreload">標籤,同樣需要從入口 chunk 開始遞迴遍歷匯入。
根據上述示例清單,對於入口點
views/foo.js,在生產環境中應包含以下標籤html<link rel="stylesheet" href="assets/foo-5UjPuW-k.css" /> <link rel="stylesheet" href="assets/shared-ChJ_j-JJ.css" /> <script type="module" src="assets/foo-BRBmoGS9.js"></script> <!-- optional --> <link rel="modulepreload" href="assets/shared-B7PI925R.js" />而對於入口點
views/bar.js,則應包含以下內容html<link rel="stylesheet" href="assets/shared-ChJ_j-JJ.css" /> <script type="module" src="assets/bar-gkvgaI9m.js"></script> <!-- optional --> <link rel="modulepreload" href="assets/shared-B7PI925R.js" />importedChunks的偽實現TypeScript 中
importedChunks的偽實現示例(你需要根據自己的程式語言和模板語言進行調整)tsimport type { Manifest, ManifestChunk } from 'vite' export default function importedChunks( manifest: Manifest, name: string, ): ManifestChunk[] { const seen = new Set<string>() function getImportedChunks(chunk: ManifestChunk): ManifestChunk[] { const chunks: ManifestChunk[] = [] for (const file of chunk.imports ?? []) { const importee = manifest[file] if (seen.has(file)) { continue } seen.add(file) chunks.push(...getImportedChunks(importee)) chunks.push(importee) } return chunks } return getImportedChunks(manifest[name]) }- 為入口 chunk 的
