注意
如果你希望使用传统后端(例如 Rails 或 Laravel)提供 HTML,同时使用 Vite 提供资源,可以先查看 Awesome Vite 中列出的现成集成方案。
如果需要自定义集成,可以按以下指南手动配置。
-
在 Vite 配置中设置入口,并启用构建清单(manifest):
vite.config.jsjs
export default defineConfig({ // overwrite default .html entry input: '/path/to/main.js', server: { cors: { // the origin you will be accessing via browser origin: 'http://my-backend.example.com', }, }, build: { // generate .vite/manifest.json in outDir manifest: true, }, })如果没有禁用 模块预加载 polyfill,还需要在入口中导入它:
js
// add the beginning of your app entry import 'vite/modulepreload-polyfill' -
开发期间,在服务器的 HTML 模板中注入以下代码;将
http://localhost:5173替换为 Vite 实际运行的本地地址:html
<!-- if development --> <script type="module" src="http://localhost:5173/@vite/client"></script> <script type="module" src="http://localhost:5173/main.js"></script>此外,为了正确提供资源,可以选择以下两种做法之一:
- 将服务器的静态资源请求代理到 Vite。
- 设置
server.origin,使生成的资源 URL 使用后端服务器的地址,而不是相对路径。
只有完成这项配置,图片等资源才能正确加载。
如果将 React 与
@vitejs/plugin-react一起使用,还需要在前面提到的脚本之前加入下面的代码,因为该插件无法修改你正在提供的 HTML。将http://localhost:5173替换为 Vite 实际运行的本地地址。html
<script type="module"> import RefreshRuntime from 'http://localhost: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,以及其他资源文件。一个 manifest 文件示例如下:.vite/manifest.jsonjson
{ "_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"] } }manifest 将源文件映射到构建输出及其依赖。
manifest 的结构为
Record<name, chunk>。其中每个 chunk 都符合ManifestChunk接口:ts
interface 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[] }manifest 中的 chunk 类型包括:
- 入口 chunk 在
build.rolldownOptions.input中指定,带有isEntry: true标志;其键是相对于项目根目录的源文件路径。 - 动态导入的入口 chunk 带有
isDynamicEntry: true标志;其键也是相对于项目根目录的源文件路径。 - 非入口 chunk 的键由生成文件的基础文件名加上
_前缀构成。 - 图片、字体等资源 chunk 的键,是相对于项目根目录的源文件路径。
- 当
build.cssCodeSplit为false时,会生成一个键为style.css的 CSS 文件。如果build.cssCodeSplit为 true,则 CSS chunk 的生成方式与 JavaScript chunk 类似:入口 chunk 的键使用其源文件路径,非入口 chunk 的键使用_前缀和生成文件的基础文件名。
JavaScript chunk 包含 imports 和 dynamicImports 字段,用于列出其静态导入和动态导入的 chunk(这些值是 manifest 中的键);css 和 assets 字段则用于列出对应的 CSS 与资源文件。
- 入口 chunk 在
-
你可以使用这个文件,通过带哈希的文件名渲染链接或预加载指令。
下面是渲染正确链接的 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 }}" />建议在后端按照以下顺序渲染标签:
- 为入口 chunk 的
css列表中的每个文件渲染一个<link rel="stylesheet">标签(如果该列表存在)。 - 沿入口 chunk 的
imports列表递归访问所有导入的 chunk,并为各 chunk 的css列表中的每个文件渲染一个<link rel="stylesheet">标签(如果该列表存在)。 - 为入口 chunk 的
file字段渲染标签:如果它是 JavaScript 文件,渲染<script type="module">;如果是 CSS 文件,渲染<link rel="stylesheet">。 - 可选:从入口 chunk 的 imports 列表出发递归访问导入的 chunk,为每个 JavaScript chunk 的
file文件渲染一个<link rel="modulepreload">标签。
接着,为
views/foo.js入口渲染生产环境中的 HTML: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: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" />Pseudo implementation of importedChunks下面是
importedChunks的 TypeScript 伪代码。应根据后端编程语言或模板语言调整它:ts
import 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 导入映射支持(实验性)
如果启用了实验性的
build.chunkImportMap,你还需要手动在 HTML 中注入导入映射。导入映射会输出到输出目录中的
importmap.json。应读取它的内容,在任何<script type="module">标签或<link rel="modulepreload">标签之前注入<script type="importmap">标签。 - 为入口 chunk 的
来源:Vite 官方文档。
© 2019 至今 VoidZero Inc. 和 Vite 贡献者。来源页面版本标识:39ddf7cc。











暂无评论内容