准备将应用部署到生产环境时,只需运行 vite build。默认情况下,它以 <root>/index.html 为构建入口,生成适合由静态托管服务提供的应用包。常见服务的部署指南见 部署静态站点。
也可以在 Scrimba 观看交互式课程。
浏览器兼容性
默认情况下,生产构建面向符合 Baseline Widely Available 的最低浏览器版本;基准日期由每个主版本固定。本主版本默认支持:
- 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 只处理语法转换,不包含 polyfill。可查看 cdnjs 的 polyfill 服务,它会根据用户浏览器的 UserAgent 自动生成 polyfill 包。
可通过 @vitejs/plugin-legacy 支持旧浏览器。它自动生成旧版代码块及对应的 ECMAScript 语言特性 polyfill;这些代码块只会在不支持原生 ESM 的浏览器中加载。
公共基础路径
相关内容:静态资源处理。
如果项目部署在嵌套的公共路径下,只需设置 base,全部资源路径就会相应重写。也可以使用命令行标志,例如 vite build --base=/my/public/path/。
构建时,JavaScript 导入的资源 URL、CSS 的 url() 引用以及 HTML 文件中的资源引用,都会自动根据该选项调整。
例外情况是运行时需要动态拼接 URL。此时可使用全局注入的 import.meta.env.BASE_URL,其值即公共基础路径。这个变量在构建时被静态替换,因此必须原样书写;import.meta.env['BASE_URL'] 不会生效。
更多控制方式见下文的高级基础路径选项。
相对基础路径
如果事先不知道基础路径,可以设定 "base": "./" 或 "base": ""。这样,生成的全部 URL 都相对于各自所在文件。
自定义构建
可以通过各种 构建配置选项 定制构建。特别是,可用 build.rolldownOptions 直接调整底层 Rolldown 选项:
vite.config.js
export default defineConfig({
build: {
rolldownOptions: {
// https://rolldown.rs/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
})
新部署发生时,托管服务可能删除上一次部署的资源。因此,在新部署前访问过站点的用户可能遇到导入错误:设备上运行的资源已过期,代码试图导入的旧代码块也已被删除。这个事件可用于处理该情况。此时,务必为 HTML 文件设置 Cache-Control: no-cache,否则仍可能引用旧资源。
文件变化时重新构建
使用 vite build --watch 可启用 Rolldown 监听器。也可以通过 build.watch 直接调整底层 WatcherOptions:
vite.config.js
export default defineConfig({
build: {
watch: {
// https://rolldown.rs/reference/InputOptions.watch
},
},
})
启用 --watch 后,待打包文件发生变化就会触发重建。注意,配置及其依赖发生变化时,需要重新启动构建命令。
多页面应用
假设源码目录结构如下:
├── package.json
├── vite.config.js
├── index.html
├── main.js
└── nested
├── index.html
└── nested.js
开发时,直接访问或链接到 /nested/ 即可,行为与常规静态文件服务器一致。构建时,只需把多个 HTML 文件指定为入口:
vite.config.js
import { resolve } from 'node:path'
import { defineConfig } from 'vite'
export default defineConfig({
input: {
main: resolve(import.meta.dirname, 'index.html'),
nested: resolve(import.meta.dirname, 'nested/index.html'),
},
})
如果指定了不同的 root,请记住:解析输入路径时,import.meta.dirname 仍表示 vite.config.js 所在文件夹。因此,需要把项目根目录作为参数加入 resolve 调用。
对于 HTML 文件,Vite 会忽略 rolldownOptions.input 对象中赋予入口的名称,而依据文件解析后的 ID 生成 dist 中的 HTML 资源,确保目录结构与开发服务器一致。
库模式
开发面向浏览器的库时,大部分时间可能都在使用一个导入实际库的测试或演示页面。通过 Vite,可以用 index.html 承担此用途,并获得流畅的开发体验。
准备打包发布库时,使用 build.lib 配置。务必将不希望打入库包的依赖设为外部依赖,例如 vue 或 react:
vite.config.js:单入口
import { 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',
},
},
},
},
})
vite.config.js:多入口
import { 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',
},
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',
},
},
},
},
})
入口文件包含导出,供软件包用户导入:
lib/main.js
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"
}
}
}
package.json:多入口
{
"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 文件,与生成的 JavaScript 文件放在一起,例如 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"
}
}
环境变量
库模式的生产构建会静态替换所有 import.meta.env.* 用法,但不会替换 process.env.*,以便库的使用者动态更改。如果不希望如此,可以使用 define: { 'process.env.NODE_ENV': '"production"' } 将其静态替换,或者使用 esm-env,获得更好的打包器和运行时兼容性。
高级用法
库模式为面向浏览器的库和 JavaScript 框架库提供简单、带有明确约定的配置。如果构建的库不面向浏览器,或需要高级构建流程,可以直接使用 tsdown 或 Rolldown。
高级基础路径选项
对于高级场景,部署后的资源和公共文件可能位于不同路径,例如采用不同的缓存策略。用户可能希望部署到三条不同路径:
- 生成的入口 HTML 文件,可能在 SSR 期间处理。
- 生成的带哈希资源,包括 JavaScript、CSS、图片等。
- 复制过去的 public 文件。
在这些情况下,单一静态 base 并不足够。Vite 通过 experimental.renderBuiltUrl,为构建时的高级基础路径选项提供实验性支持:
experimental: {
renderBuiltUrl(filename, { hostType }) {
if (hostType === 'js') {
return { runtime: `window.__toCdnUrl(${JSON.stringify(filename)})` }
} else {
return { relative: true }
}
},
},
如果带哈希资源与公共文件并非部署在一起,可以使用函数第二个上下文参数中的资源类型,为两类资源分别定义选项:
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 的对象,则需在必要时自行编码,因为运行时代码会原样输出。











暂无评论内容