构建生产版本
当需要为生产环境部署应用时,只需运行 vite build 命令。默认情况下,它使用 <root>/index.html 作为构建入口,并生成一个适合在静态托管服务上部署的应用包。查看 部署静态站点 以获取关于热门服务的部署指南。
浏览器兼容性
默认情况下,生产构建产物假定目标浏览器为 Baseline(基线)广泛支持的范围。默认支持的浏览器版本范围如下:
- Chrome >=111
- Edge >=111
- Firefox >=114
- Safari >=16.4
你可以通过 build.target 配置选项指定自定义目标,最低支持 es2015。如果设置了更低的目标,Vite 依然要求满足上述最低浏览器支持范围,因为它依赖 原生 ESM 动态导入 和 import.meta。
- Chrome >=64
- Firefox >=67
- Safari >=11.1
- Edge >=79
请注意,默认情况下,Vite 仅处理语法转换,不提供 polyfills(垫片)。你可以访问 https://cdnjs.cloudflare.com/polyfill/,它会根据用户的浏览器 UserAgent 字符串自动生成 polyfill 包。
可以通过 @vitejs/plugin-legacy 支持旧版浏览器,它会自动生成旧版 chunk 以及相应的 ES 语言特性 polyfills。这些旧版 chunk 只会在不支持原生 ESM 的浏览器中按需加载。
公共基础路径
- 相关内容:资源处理
如果你的项目部署在嵌套的公共路径下,只需指定 base 配置选项,所有资源路径都会相应地重写。该选项也可以通过命令行参数指定,例如 vite build --base=/my/public/path/。
在构建过程中,JS 导入的资源 URL、CSS 中的 url() 引用以及 .html 文件中的资源引用都会自动调整以遵循此选项。
例外情况是当你需要动态拼接 URL 时。在这种情况下,你可以使用全局注入的 import.meta.env.BASE_URL 变量,它即为公共基础路径。注意该变量在构建时会被静态替换,因此必须以原样出现(例如 import.meta.env['BASE_URL'] 是无效的)。
若需更高级的基础路径控制,请查看 高级基础路径选项。
相对基础路径
如果你无法提前预知基础路径,可以设置相对基础路径,如 "base": "./" 或 "base": ""。这将使所有生成的 URL 相对于每个文件进行定位。
使用相对基础路径时对旧版浏览器的支持
相对路径需要 import.meta 支持。如果你需要支持 不支持 import.meta 的浏览器,可以使用 legacy 插件。
自定义构建
可以通过各种 构建配置选项 自定义构建。具体来说,你可以通过 build.rolldownOptions 直接调整底层的 Rolldown 选项。
export default defineConfig({
build: {
rolldownOptions: {
// https://rolldown.node.org.cn/reference/
},
},
})例如,你可以指定多个 Rolldown 输出,并使用仅在构建时应用的插件。
分块策略
你可以使用 build.rolldownOptions.output.codeSplitting 来配置如何进行代码分块(参考 Rolldown 文档)。如果你使用的是某个框架,请查阅其文档以了解如何配置分块。
加载错误处理
当动态导入加载失败时,Vite 会触发 vite:preloadError 事件。event.payload 包含原始的导入错误。如果你调用了 event.preventDefault(),该错误将不会被抛出。
window.addEventListener('vite:preloadError', (event) => {
window.location.reload() // for example, refresh the page
})当进行新部署时,托管服务可能会删除旧部署的资源。结果就是,在新部署之前访问过你站点的用户可能会遇到导入错误。这是因为用户设备上运行的资源已过期,且尝试导入对应的旧 chunk,但该文件已被删除。此事件有助于处理这种情况。在这种情况下,请确保在 HTML 文件上设置 Cache-Control: no-cache,否则旧资源仍会被引用。
文件变更时重新构建
你可以通过 vite build --watch 启用 rollup 观察器,或者通过 build.watch 直接调整底层的 WatcherOptions。
export default defineConfig({
build: {
watch: {
// https://rolldown.node.org.cn/reference/InputOptions.watch
},
},
})启用 --watch 标志后,对要打包的文件的更改将触发重新构建。请注意,修改配置文件及其依赖项需要重启构建命令。
多页应用
假设你拥有以下源码结构:
├── package.json
├── vite.config.js
├── index.html
├── main.js
└── nested
├── index.html
└── nested.js在开发环境下,直接导航或链接到 /nested/ 即可——它能按预期工作,就像普通的静态文件服务器一样。
在构建时,你只需要将多个 .html 文件指定为入口点:
import { dirname, resolve } from 'node:path'
import { defineConfig } from 'vite'
export default defineConfig({
build: {
rolldownOptions: {
input: {
main: resolve(import.meta.dirname, 'index.html'),
nested: resolve(import.meta.dirname, 'nested/index.html'),
},
},
},
})如果你指定了不同的根目录 (root),请记住在解析输入路径时,import.meta.dirname 仍然会是你的 vite.config.js 文件所在的文件夹。因此,你需要将你的 root 条目添加到 resolve 的参数中。
注意,对于 HTML 文件,Vite 会忽略 rolldownOptions.input 对象中给定的名称,而是在 dist 文件夹中生成 HTML 资源时尊重文件的已解析 ID。这确保了结构与开发服务器工作方式的一致性。
库模式
当你开发面向浏览器的库时,大部分时间可能是在测试/演示页面中导入你的实际库。使用 Vite,你可以将 index.html 用于此目的,以获得流畅的开发体验。
当需要打包库以供发布时,请使用 build.lib 配置选项。确保将不希望打包到库中的依赖项外部化(externalize),例如 vue 或 react。
import { dirname, resolve } from 'node:path'
import { defineConfig } from 'vite'
export default defineConfig({
build: {
lib: {
entry: resolve(import.meta.dirname, 'lib/main.js'),
name: 'MyLib',
// the proper extensions will be added
fileName: 'my-lib',
},
rolldownOptions: {
// make sure to externalize deps that shouldn't be bundled
// into your library
external: ['vue'],
output: {
// Provide global variables to use in the UMD build
// for externalized deps
globals: {
vue: 'Vue',
},
},
},
},
})import { dirname, resolve } from 'node:path'
import { defineConfig } from 'vite'
export default defineConfig({
build: {
lib: {
entry: {
'my-lib': resolve(import.meta.dirname, 'lib/main.js'),
secondary: resolve(import.meta.dirname, 'lib/secondary.js'),
},
name: 'MyLib',
},
rollupOptions: {
// make sure to externalize deps that shouldn't be bundled
// into your library
external: ['vue'],
output: {
// Provide global variables to use in the UMD build
// for externalized deps
globals: {
vue: 'Vue',
},
},
},
},
})入口文件应包含用户可以从你的包中导入的导出内容:
import Foo from './Foo.vue'
import Bar from './Bar.vue'
export { Foo, Bar }使用此配置运行 vite build 时,将使用一个面向库发布的 Rollup 预设,并生成两种捆绑格式:
es和umd(针对单入口)es和cjs(针对多入口)
格式可以通过 build.lib.formats 选项进行配置。
$ vite build
building for production...
dist/my-lib.js 0.08 kB / gzip: 0.07 kB
dist/my-lib.umd.cjs 0.30 kB / gzip: 0.16 kB推荐的库 package.json 配置:
{
"name": "my-lib",
"type": "module",
"files": ["dist"],
"main": "./dist/my-lib.umd.cjs",
"module": "./dist/my-lib.js",
"exports": {
".": {
"import": "./dist/my-lib.js",
"require": "./dist/my-lib.umd.cjs"
}
}
}{
"name": "my-lib",
"type": "module",
"files": ["dist"],
"main": "./dist/my-lib.cjs",
"module": "./dist/my-lib.js",
"exports": {
".": {
"import": "./dist/my-lib.js",
"require": "./dist/my-lib.cjs"
},
"./secondary": {
"import": "./dist/secondary.js",
"require": "./dist/secondary.cjs"
}
}
}CSS 支持
如果你的库导入了任何 CSS,它将被打包成一个独立的 CSS 文件,随构建后的 JS 文件一起发布,例如 dist/my-lib.css。文件名默认为 build.lib.fileName,也可以通过 build.lib.cssFileName 进行修改。
你可以在 package.json 中导出 CSS 文件,供用户导入:
{
"name": "my-lib",
"type": "module",
"files": ["dist"],
"main": "./dist/my-lib.umd.cjs",
"module": "./dist/my-lib.js",
"exports": {
".": {
"import": "./dist/my-lib.js",
"require": "./dist/my-lib.umd.cjs"
},
"./style.css": "./dist/my-lib.css"
}
}文件扩展名
如果 package.json 中没有包含 "type": "module",Vite 为了与 Node.js 兼容将生成不同的文件扩展名。.js 将变为 .mjs,.cjs 将保持为 .cjs。
环境变量
在库模式下,所有的 import.meta.env.* 使用在生产构建时会被静态替换。然而,process.env.* 的使用则不会,这样库的使用者就可以动态更改它们。如果这不是你想要的,可以使用例如 define: { 'process.env.NODE_ENV': '"production"' } 来静态替换它们,或者使用 esm-env 以获得与打包器和运行环境更好的兼容性。
高级基础路径选项
警告
此功能处于实验阶段。提供反馈。
对于高级用例,部署的资源和公共文件可能位于不同的路径,例如为了使用不同的缓存策略。用户可能选择部署到三个不同的路径:
- 生成的入口 HTML 文件(可能在 SSR 期间处理)
- 生成的带哈希的资源(JS、CSS 和其他类型文件如图片)
- 复制的 public 文件
在这些场景下,单一的静态 基础路径 是不够的。Vite 在构建过程中通过 experimental.renderBuiltUrl 提供了对高级基础路径选项的实验性支持。
experimental: {
renderBuiltUrl(filename, { hostType }) {
if (hostType === 'js') {
return { runtime: `window.__toCdnUrl(${JSON.stringify(filename)})` }
} else {
return { relative: true }
}
},
},
如果带哈希的资源和公共文件没有部署在一起,可以使用传递给函数的第二个 context 参数中包含的资源 type,分别为每组定义选项。
experimental: {
renderBuiltUrl(filename, { hostId, hostType, type }) {
if (type === 'public') {
return 'https://www.domain.com/' + filename
} else if (path.extname(hostId) === '.js') {
return {
runtime: `window.__assetsPath(${JSON.stringify(filename)})`
}
} else {
return 'https://cdn.domain.com/assets/' + filename
}
},
},
注意,传入的 filename 是已解码的 URL,如果函数返回一个 URL 字符串,它也应该是已解码的。Vite 在渲染 URL 时会自动处理编码。如果返回一个带有 runtime 的对象,则需要自行在需要的地方处理编码,因为运行时代码将按原样渲染。
