生产环境构建
当准备将你的应用部署到生产环境时,只需运行 vite build
命令。默认情况下,它使用 <root>/index.html
作为构建入口点,并生成适合在静态托管服务上提供的应用程序包。查看部署静态站点以获取关于流行服务的指南。
浏览器兼容性
默认情况下,生产环境包假定使用包含在Baseline广泛可用目标中的现代浏览器。默认浏览器支持范围是
- Chrome >=107
- Edge >=107
- Firefox >=104
- Safari >=16
你可以通过 build.target
配置选项指定自定义目标,其中最低目标是 es2015
。如果设置了较低的目标,Vite 仍然需要这些最低浏览器支持范围,因为它依赖于 native ESM dynamic import 和 import.meta
- Chrome >=64
- Firefox >=67
- Safari >=11.1
- Edge >=79
请注意,默认情况下,Vite 仅处理语法转换,不包括 polyfill。你可以查看 https://cdnjs.cloudflare.com/polyfill/,它会根据用户的浏览器 UserAgent 字符串自动生成 polyfill 包。
可以通过 @vitejs/plugin-legacy 支持旧版浏览器,它将自动生成旧版块和相应的 ES 语言特性 polyfill。旧版块仅在不支持 native 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.rollupOptions
直接调整底层Rollup 选项
export default defineConfig({
build: {
rollupOptions: {
// https://rollup.node.org.cn/configuration-options/
},
},
})
例如,你可以指定多个 Rollup 输出,其中包含仅在构建期间应用的插件。
分块策略
你可以使用 build.rollupOptions.output.manualChunks
配置如何拆分块(请参阅 Rollup 文档)。如果使用框架,请参阅其文档以配置如何拆分块。
加载错误处理
当 Vite 无法加载动态导入时,会发出 vite:preloadError
事件。event.payload
包含原始导入错误。如果调用 event.preventDefault()
,则不会抛出该错误。
window.addEventListener('vite:preloadError', (event) => {
window.location.reload() // for example, refresh the page
})
发生新部署时,托管服务可能会删除先前部署中的资源。因此,在新部署之前访问过你网站的用户可能会遇到导入错误。发生此错误是因为用户设备上运行的资源已过时,并且它尝试导入相应的旧块,该块已被删除。此事件对于解决这种情况很有用。
文件更改时重新构建
你可以使用 vite build --watch
启用 Rollup 监视器。或者,你可以通过 build.watch
直接调整底层 WatcherOptions
export default defineConfig({
build: {
watch: {
// https://rollup.node.org.cn/configuration-options/#watch
},
},
})
启用 --watch
标志后,对 vite.config.js
以及任何要打包的文件的更改都将触发重新构建。
多页应用
假设你有以下源代码结构
├── package.json
├── vite.config.js
├── index.html
├── main.js
└── nested
├── index.html
└── nested.js
在开发期间,只需导航或链接到 /nested/
- 它会按预期工作,就像普通的静态文件服务器一样。
在构建期间,你需要做的就是指定多个 .html
文件作为入口点
import { dirname, resolve } from 'node:path'
import { fileURLToPath } from 'node:url'
import { defineConfig } from 'vite'
const __dirname = dirname(fileURLToPath(import.meta.url))
export default defineConfig({
build: {
rollupOptions: {
input: {
main: resolve(__dirname, 'index.html'),
nested: resolve(__dirname, 'nested/index.html'),
},
},
},
})
如果指定了不同的根目录,请记住在解析输入路径时,__dirname
仍然是 vite.config.js 文件的文件夹。因此,你需要将 root
条目添加到 resolve
的参数中。
请注意,对于 HTML 文件,Vite 会忽略在 rollupOptions.input
对象中给定的条目名称,而是在 dist 文件夹中生成 HTML 资源时遵守文件的已解析 ID。这确保了与开发服务器工作方式一致的结构。
库模式
当你开发面向浏览器的库时,你可能会将大部分时间花在导入实际库的测试/演示页面上。使用 Vite,你可以将 index.html
用于此目的,以获得流畅的开发体验。
当准备好打包库以进行分发时,请使用 build.lib
配置选项。确保还外部化任何你不希望打包到库中的依赖项,例如 vue
或 react
import { dirname, resolve } from 'node:path'
import { fileURLToPath } from 'node:url'
import { defineConfig } from 'vite'
const __dirname = dirname(fileURLToPath(import.meta.url))
export default defineConfig({
build: {
lib: {
entry: resolve(__dirname, 'lib/main.js'),
name: 'MyLib',
// the proper extensions will be added
fileName: 'my-lib',
},
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 { dirname, resolve } from 'node:path'
import { fileURLToPath } from 'node:url'
import { defineConfig } from 'vite'
const __dirname = dirname(fileURLToPath(import.meta.url))
export default defineConfig({
build: {
lib: {
entry: {
'my-lib': resolve(__dirname, 'lib/main.js'),
secondary: resolve(__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,它将作为内置 JS 文件之外的单个 CSS 文件进行捆绑,例如 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
将变为 .js
。
环境变量
在库模式下,所有 import.meta.env.*
用法在为生产环境构建时都会被静态替换。但是,不会静态替换 process.env.*
用法,以便库的使用者可以动态地更改它。如果这是不可取的,你可以使用 define: { 'process.env.NODE_ENV': '"production"' }
例如静态替换它们,或者使用 esm-env
以获得与捆绑器和运行时更好的兼容性。
高级基础选项
警告
此功能是实验性的。 提供反馈。
对于高级用例,已部署的资源和公共文件可能位于不同的路径中,例如使用不同的缓存策略。用户可以选择在三个不同的路径中部署
- 生成的入口 HTML 文件(可能在 SSR 期间处理)
- 生成的哈希资源(JS、CSS 和其他文件类型,如图像)
- 复制的 公共目录
在这些情况下,单个静态 base 不够。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
的对象,则应根据需要自行处理编码,因为运行时代码将按原样呈现。