Skip to content

Commit 77a24b9

Browse files
authored
Merge pull request #954 from vitejs/dev
Release for Vite v5.2.11
2 parents b71595f + 013f1fa commit 77a24b9

16 files changed

+738
-247
lines changed

.vitepress/config.ts

+4
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,10 @@ export default defineConfig({
194194
{ text: 'Releases', link: '/releases' },
195195
{
196196
items: [
197+
{
198+
text: 'Mastodon',
199+
link: 'https://elk.zone/m.webtoo.ls/@vite',
200+
},
197201
{
198202
text: 'Twitter',
199203
link: 'https://twitter.com/vite_js',

config/dep-optimization-options.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
默认情况下,Vite 会抓取你的 `index.html` 来检测需要预构建的依赖项(忽略了`node_modules``build.outDir``__tests__``coverage`)。如果指定了 `build.rollupOptions.input`,Vite 将转而去抓取这些入口点。
1010

11-
如果这两者都不合你意,则可以使用此选项指定自定义条目——该值需要遵循 [fast-glob 模式](https://github.com/mrmlnc/fast-glob#basic-syntax) ,或者是相对于 Vite 项目根目录的匹配模式数组。当显式声明了 `optimizeDeps.entries` 时默认只有 `node_modules``build.outDir` 文件夹会被忽略。如果还需忽略其他文件夹,你可以在模式列表中使用以 `!` 为前缀的、用来匹配忽略项的模式。
11+
如果这两者都不合你意,则可以使用此选项指定自定义条目——该值需要遵循 [fast-glob 模式](https://github.com/mrmlnc/fast-glob#basic-syntax) ,或者是相对于 Vite 项目根目录的匹配模式数组。当显式声明了 `optimizeDeps.entries` 时默认只有 `node_modules``build.outDir` 文件夹会被忽略。如果还需忽略其他文件夹,你可以在模式列表中使用以 `!` 为前缀的、用来匹配忽略项的模式。如果你不想忽略 `node_modules``build.outDir`,你可以选择直接使用字符串路径(不使用 fast-glob 模式)。
1212

1313
## optimizeDeps.exclude {#optimizedeps-exclude}
1414

config/shared-options.md

+4
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,10 @@ export default defineConfig({
292292

293293
该选项用于选择用于 CSS 处理的引擎。详细信息请查看 [Lightning CSS](../guide/features.md#lightning-css)
294294

295+
::: info 重复的 `@import`
296+
需要注意的是,postcss(postcss-import)处理重复 `@import` 的行为与浏览器是不同的。详情请参考 [postcss/postcss-import#462](https://github.com/postcss/postcss-import/issues/462)
297+
:::
298+
295299
## css.lightningcss
296300

297301
- **实验性:** [提供反馈](https://github.com/vitejs/vite/discussions/13835)

guide/api-hmr.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ import.meta.hot.accept((module) => {
218218
219219
如果在连接前调用,数据会先被缓存、等到连接建立好后再发送。
220220
221-
查看 [客户端与服务器的数据交互](/guide/api-plugin.html#client-server-communication) 一节获取更多细节
221+
查看 [客户端与服务端间通信](/guide/api-plugin.html#client-server-communication) 以及 [自定义事件的 TypeScript 类型定义指南](/guide/api-plugin.html#typescript-for-custom-events) 章节获取更多细节
222222
223223
## 推荐阅读 {#further-reading}
224224

guide/api-plugin.md

+29-3
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,8 @@ Vite 插件也可以提供钩子来服务于特定的 Vite 目标。这些钩子
479479
- 带有 `enforce: 'post'` 的用户插件
480480
- Vite 后置构建插件(最小化,manifest,报告)
481481

482+
请注意,这与钩子的排序是分开的,钩子的顺序仍然会受到它们的 `order` 属性的影响,这一点 [和 Rollup 钩子的表现一样](https://rollupjs.org/plugin-development/#build-hooks)。
483+
482484
## 情景应用 {#conditional-application}
483485

484486
默认情况下插件在开发(serve)和构建(build)模式中都会调用。如果插件只需要在预览或构建期间有条件地应用,请使用 `apply` 属性指明它们仅在 `'build'``'serve'` 模式时调用:
@@ -622,16 +624,40 @@ export default defineConfig({
622624

623625
### 自定义事件的 TypeScript 类型定义指南 {#typeScript-for-custom-events}
624626

625-
可以通过扩展 `CustomEventMap` 这个 interface 来为自定义事件标注类型:
627+
Vite 会在内部从 `CustomEventMap` 这个接口推断出 payload 的类型,可以通过扩展这个接口来为自定义事件进行类型定义:
628+
629+
:::tip 提示
630+
在指定 TypeScript 声明文件时,确保包含 `.d.ts` 扩展名。否则,TypeScript 可能不会知道试图扩展的是哪个文件。
631+
:::
626632

627633
```ts
628634
// events.d.ts
629-
import 'vite/types/customEvent'
635+
import 'vite/types/customEvent.d.ts'
630636
631-
declare module 'vite/types/customEvent' {
637+
declare module 'vite/types/customEvent.d.ts' {
632638
interface CustomEventMap {
633639
'custom:foo': { msg: string }
634640
// 'event-key': payload
635641
}
636642
}
637643
```
644+
645+
这个接口扩展被 `InferCustomEventPayload<T>` 所使用,用来推断事件 `T` 的 payload 类型。要了解更多关于这个接口如何被使用的信息,请参考 [HMR API 文档](./api-hmr#hmr-api)。
646+
647+
```ts twoslash
648+
import 'vite/client'
649+
import type { InferCustomEventPayload } from 'vite/types/customEvent.d.ts'
650+
declare module 'vite/types/customEvent.d.ts' {
651+
interface CustomEventMap {
652+
'custom:foo': { msg: string }
653+
}
654+
}
655+
// ---cut---
656+
type CustomFooPayload = InferCustomEventPayload<'custom:foo'>
657+
import.meta.hot?.on('custom:foo', (payload) => {
658+
// payload 的类型为 { msg: string }
659+
})
660+
import.meta.hot?.on('unknown:event', (payload) => {
661+
// payload 的类型为 any
662+
})
663+
```

guide/api-vite-runtime.md

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
# Vite 运行时 API {#vite-runtime-api}
22

3-
:::warning 低级别 API
4-
这个 API 在 Vite 5.1 中作为一个实验性特性引入。它被添加以 [收集反馈](https://github.com/vitejs/vite/discussions/15774)。在Vite 5.2 中,它可能会有破坏性的变化,所以在使用它时,请确保将 Vite 版本固定在 `~5.1.0`。这是一个面向库和框架作者的低级别 API。如果你的目标是开发应用,请确保首先查看 [Vite SSR 精选板块](https://github.com/vitejs/awesome-vite#ssr) 的高级 SSR 插件和工具。
3+
:::warning 底层 API
4+
这个 API 在 Vite 5.1 中作为一个实验性特性引入。它被添加以 [收集反馈](https://github.com/vitejs/vite/discussions/15774)。在Vite 5.2 中,它可能会有破坏性的变化,所以在使用它时,请确保将 Vite 版本固定在 `~5.1.0`。这是一个面向库和框架作者的底层 API。如果你的目标是开发应用,请确保首先查看 [Vite SSR 精选板块](https://github.com/vitejs/awesome-vite#ssr) 的高级 SSR 插件和工具。
5+
6+
目前,这种 API 正在以 [环境 API](https://github.com/vitejs/vite/discussions/16358) 的形式进行修正,并在 `^6.0.0-alpha.0` 版本中发布。
57
:::
68

79
"Vite 运行时" 是一个工具,它允许首先用 Vite 插件处理任何代码后运行。它与 `server.ssrLoadModule` 不同,因为运行时实现是从服务器解耦的。这允许库和框架作者实现他们自己的服务器和运行时之间的通信层。

guide/backend-integration.md

+40-28
Original file line numberDiff line numberDiff line change
@@ -62,24 +62,36 @@
6262

6363
```json
6464
{
65-
"main.js": {
66-
"file": "assets/main.4889e940.js",
67-
"src": "main.js",
65+
"_shared-!~{003}~.js": {
66+
"file": "assets/shared-ChJ_j-JJ.css",
67+
"src": "_shared-!~{003}~.js"
68+
},
69+
"_shared-B7PI925R.js": {
70+
"file": "assets/shared-B7PI925R.js",
71+
"name": "shared",
72+
"css": ["assets/shared-ChJ_j-JJ.css"]
73+
},
74+
"baz.js": {
75+
"file": "assets/baz-B2H3sXNv.js",
76+
"name": "baz",
77+
"src": "baz.js",
78+
"isDynamicEntry": true
79+
},
80+
"views/bar.js": {
81+
"file": "assets/bar-gkvgaI9m.js",
82+
"name": "bar",
83+
"src": "views/bar.js",
6884
"isEntry": true,
69-
"dynamicImports": ["views/foo.js"],
70-
"css": ["assets/main.b82dbe22.css"],
71-
"assets": ["assets/asset.0ab0f9cd.png"],
72-
"imports": ["_shared.83069a53.js"]
85+
"imports": ["_shared-B7PI925R.js"],
86+
"dynamicImports": ["baz.js"]
7387
},
7488
"views/foo.js": {
75-
"file": "assets/foo.869aea0d.js",
89+
"file": "assets/foo-BRBmoGS9.js",
90+
"name": "foo",
7691
"src": "views/foo.js",
77-
"isDynamicEntry": true,
78-
"imports": ["_shared.83069a53.js"]
79-
},
80-
"_shared.83069a53.js": {
81-
"file": "assets/shared.83069a53.js",
82-
"css": ["assets/shared.a834bfc3.css"]
92+
"isEntry": true,
93+
"imports": ["_shared-B7PI925R.js"],
94+
"css": ["assets/foo-5UjPuW-k.css"]
8395
}
8496
}
8597
```
@@ -108,35 +120,35 @@
108120
<script type="module" src="/{{ manifest[name].file }}"></script>
109121

110122
<!-- 对于 importedChunks(manifest, name) 中的 chunk -->
111-
<link rel="modulepreload" src="/{{ chunk.file }}" />
123+
<link rel="modulepreload" href="/{{ chunk.file }}" />
112124
```
113125

114126
具体来说,一个生成 HTML 的后端在给定 manifest 文件和一个入口文件的情况下,
115127
应该包含以下标签:
116128

117129
- 对于入口文件 chunk 的 `css` 列表中的每个文件,都应包含一个 `<link rel="stylesheet">` 标签。
118-
- 递归追踪入口文件的 `imports` 列表中的所有 chunk,并为每个导入的 chunk 的每个 css 文件
130+
- 递归追踪入口文件的 `imports` 列表中的所有 chunk,并为每个导入的 chunk 的每个 CSS 文件
119131
包含一个 `<link rel="stylesheet">` 标签。
120-
- 对于入口文件 chunk 的 `file` 键的标签(对于 Javascript 是
121-
`<script type="moudle">`,对于 css`<link rel="stylesheet">`
122-
- 可选项,对于每个导入的 Javascript chunk 的 `file` 键的 `<link rel="modulepreload">` 标签,
132+
- 对于入口文件 chunk 的 `file` 键的标签(对于 JavaScript 是
133+
`<script type="module">`,对于 CSS`<link rel="stylesheet">`
134+
- 可选项,对于每个导入的 JavaScript chunk 的 `file` 键的 `<link rel="modulepreload">` 标签,
123135
同样从入口文件 chunk 开始递归追踪导入。
124136

125-
按照上面的示例 manifest,对于入口文件 `main.js`,在生产环境中应包含以下标签:
137+
按照上面的示例 manifest,对于入口文件 `views/foo.js`,在生产环境中应包含以下标签:
126138

127139
```html
128-
<link rel="stylesheet" href="assets/main.b82dbe22.css" />
129-
<link rel="stylesheet" href="assets/shared.a834bfc3.css" />
130-
<script type="module" src="assets/main.4889e940.js"></script>
140+
<link rel="stylesheet" href="assets/foo-5UjPuW-k.css" />
141+
<link rel="stylesheet" href="assets/shared-ChJ_j-JJ.css" />
142+
<script type="module" src="assets/foo-BRBmoGS9.js"></script>
131143
<!-- 可选 -->
132-
<link rel="modulepreload" src="assets/shared.83069a53.js" />
144+
<link rel="modulepreload" href="assets/shared-B7PI925R.js" />
133145
```
134146

135-
而对于入口文件 `views/foo.js`,应该包含以下标签:
147+
而对于入口文件 `views/bar.js`,应该包含以下标签:
136148

137149
```html
138-
<link rel="stylesheet" href="assets/shared.a834bfc3.css" />
139-
<script type="module" src="assets/foo.869aea0d.js"></script>
150+
<link rel="stylesheet" href="assets/shared-ChJ_j-JJ.css" />
151+
<script type="module" src="assets/bar-gkvgaI9m.js"></script>
140152
<!-- 可选 -->
141-
<link rel="modulepreload" src="assets/shared.83069a53.js" />
153+
<link rel="modulepreload" href="assets/shared-B7PI925R.js" />
142154
```

guide/build.md

+15-27
Original file line numberDiff line numberDiff line change
@@ -47,21 +47,7 @@ export default defineConfig({
4747

4848
## 产物分块策略 {#chunking-strategy}
4949

50-
你可以通过配置 `build.rollupOptions.output.manualChunks` 来自定义 chunk 分割策略(查看 [Rollup 相应文档](https://rollupjs.org/configuration-options/#output-manualchunks))。在 Vite 2.8 及更早版本中,默认的策略是将 chunk 分割为 `index``vendor`。这对一些 SPA 来说是好的策略,但是要对所有应用场景提供一种通用解决方案是非常困难的。从 Vite 2.9 起,`manualChunks` 默认情况下不再被更改。你可以通过在配置文件中添加 `splitVendorChunkPlugin` 来继续使用 “分割 Vendor Chunk” 策略:
51-
52-
```js
53-
// vite.config.js
54-
import { splitVendorChunkPlugin } from 'vite'
55-
export default defineConfig({
56-
plugins: [splitVendorChunkPlugin()],
57-
})
58-
```
59-
60-
也可以用一个工厂函数 `splitVendorChunk({ cache: SplitVendorChunkCache })` 来提供该策略,在需要与自定义逻辑组合的情况下,`cache.reset()` 需要在 `buildStart` 阶段被调用,以便构建的 watch 模式在这种情况下正常工作。
61-
62-
::: warning
63-
你应该使用 `build.rollupOptions.output.manualChunks` 函数形式来使用此插件。如果使用对象形式,插件将不会生效。
64-
:::
50+
你可以通过配置 `build.rollupOptions.output.manualChunks` 来自定义 chunk 分割策略(查看 [Rollup 相应文档](https://cn.rollupjs.org/configuration-options/#output-manualchunks))。如果你使用的是一个框架,那么请参考他们的文档来了解如何配置分割 chunk。
6551

6652
## 处理加载报错 {#load-error-handling}
6753

@@ -271,24 +257,26 @@ experimental: {
271257

272258
如果 hash 后的资源和公共文件没有被部署在一起,可以根据该函数的第二个参数 `context` 上的字段 `type` 分别定义各个资源组的选项:
273259

260+
<!-- prettier-ignore-start -->
274261
```ts twoslash
275262
import type { UserConfig } from 'vite'
276263
import path from 'node:path'
277264
const config: UserConfig = {
278-
// ---cut-before---
279-
experimental: {
280-
renderBuiltUrl(filename, { hostId, hostType, type }) {
281-
if (type === 'public') {
282-
return 'https://www.domain.com/' + filename
283-
} else if (path.extname(hostId) === '.js') {
284-
return { runtime: `window.__assetsPath(${JSON.stringify(filename)})` }
285-
} else {
286-
return 'https://cdn.domain.com/assets/' + filename
287-
}
288-
},
265+
// ---cut-before---
266+
experimental: {
267+
renderBuiltUrl(filename, { hostId, hostType, type }) {
268+
if (type === 'public') {
269+
return 'https://www.domain.com/' + filename
270+
} else if (path.extname(hostId) === '.js') {
271+
return { runtime: `window.__assetsPath(${JSON.stringify(filename)})` }
272+
} else {
273+
return 'https://cdn.domain.com/assets/' + filename
274+
}
289275
},
290-
// ---cut-after---
276+
},
277+
// ---cut-after---
291278
}
292279
```
280+
<!-- prettier-ignore-end -->
293281

294282
请注意,传递的 `filename` 是一个已解码的 URL,如果函数返回了一个 URL 字符串,那么它也应该是已解码的。当 Vite 渲染 URL 时会自动处理编码。如果返回的是一个带有 `runtime` 的对象,就需要在必要的地方自行处理编码,因为运行时的代码将会按照原样呈现。

guide/env-and-mode.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
## 环境变量 {#env-variables}
44

5-
Vite 在一个特殊的 **`import.meta.env`** 对象上暴露环境变量。这里有一些在所有情况下都可以使用的内建变量:
5+
Vite 在一个特殊的 **`import.meta.env`** 对象上暴露环境变量,这些变量在构建时会被静态地替换掉。这里有一些在所有情况下都可以使用的内建变量:
66

77
- **`import.meta.env.MODE`**: {string} 应用运行的[模式](#modes)
88

guide/features.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -699,7 +699,7 @@ import MyWorker from './worker?worker&url'
699699

700700
### [`'nonce-{RANDOM}'`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/Sources#nonce-base64-value)
701701

702-
当设置了 [`html.cspNonce`](/config/shared-options#html-cspnonce) 时,Vite 会在输出的脚本标签和样式表的链接标签中添加一个带有指定值的 nonce 属性。请注意,Vite 不会将 nonce 属性添加到其他标签中,例如 `<style>`。此外,设置此选项时,Vite 将注入一个 meta 标签`<meta property="csp-nonce" nonce="PLACEHOLDER" />`
702+
当设置了 [`html.cspNonce`](/config/shared-options#html-cspnonce) 时,Vite 会为任何 `<script>``<style>` 标签,以及样式表和模块预加载的 `<link>` 标签添加一个 nonce 属性。此外,当设置了这个选项时,Vite 会注入一个 meta 标签 (`<meta property="csp-nonce" nonce="PLACEHOLDER" />`)
703703

704704
带有 `property="csp-nonce"` 的 meta 标签的 nonce 值将在开发和构建后的必要时刻被 Vite 使用。
705705

guide/ssr.md

+6-11
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@ SSR 特别指支持在 Node.js 中运行相同应用程序的前端框架(例
66
下面的指南还假定你在选择的框架中有使用 SSR 的经验,并且只关注特定于 Vite 的集成细节。
77
:::
88

9-
:::warning Low-level API
9+
:::warning 底层 API
1010
这是一个底层 API,是为库和框架作者准备的。如果你的目标是构建一个应用程序,请确保优先查看 [Vite SSR 章节](https://github.com/vitejs/awesome-vite#ssr) 中更上层的 SSR 插件和工具。也就是说,大部分应用都是基于 Vite 的底层 API 之上构建的。
11+
12+
目前,Vite 正在用 [环境 API](https://github.com/vitejs/vite/discussions/16358) 来改进 SSR API。查看链接了解更多详情。
1113
:::
1214

1315
:::tip 帮助
@@ -138,17 +140,10 @@ app.use('*', async (req, res, next) => {
138140
// 例如:@vitejs/plugin-react 中的 global preambles
139141
template = await vite.transformIndexHtml(url, template)
140142

141-
// 3a. 加载服务器入口。vite.ssrLoadModule 将自动转换
143+
// 3. 加载服务器入口。vite.ssrLoadModule 将自动转换
142144
// 你的 ESM 源码使之可以在 Node.js 中运行!无需打包
143145
// 并提供类似 HMR 的根据情况随时失效。
144146
const { render } = await vite.ssrLoadModule('/src/entry-server.js')
145-
// 3b. 从 Vite 5.1 版本开始,你可以试用实验性的 createViteRuntime
146-
// API。
147-
// 这个 API 完全支持热更新(HMR),其工作原理与 ssrLoadModule 相似
148-
// 如果你想尝试更高级的用法,可以考虑在另一个线程,甚至是在另一台机器上,
149-
// 使用 ViteRuntime 类来创建运行环境。
150-
const runtime = await vite.createViteRuntime(server)
151-
const { render } = await runtime.executeEntrypoint('/src/entry-server.js')
152147

153148
// 4. 渲染应用的 HTML。这假设 entry-server.js 导出的 `render`
154149
// 函数调用了适当的 SSR 框架 API。
@@ -183,7 +178,7 @@ app.use('*', async (req, res, next) => {
183178
为了将 SSR 项目交付生产,我们需要:
184179
185180
1. 正常生成一个客户端构建;
186-
2. 再生成一个 SSR 构建,使其通过 `import()` 直接加载,这样便无需再使用 Vite 的 `ssrLoadModule``runtime.executeEntrypoint`
181+
2. 再生成一个 SSR 构建,使其通过 `import()` 直接加载,这样便无需再使用 Vite 的 `ssrLoadModule`
187182
188183
`package.json` 中的脚本应该看起来像这样:
189184
@@ -203,7 +198,7 @@ app.use('*', async (req, res, next) => {
203198
204199
- 使用 `dist/client/index.html` 作为模板,而不是根目录的 `index.html`,因为前者包含了到客户端构建的正确资源链接。
205200
206-
- 使用 `import('./dist/server/entry-server.js')` (该文件是 SSR 构建产物),而不是使用 `await vite.ssrLoadModule('/src/entry-server.js')``await runtime.executeEntrypoint('/src/entry-server.js')`
201+
- 使用 `import('./dist/server/entry-server.js')` (该文件是 SSR 构建产物),而不是使用 `await vite.ssrLoadModule('/src/entry-server.js')`
207202
208203
- 将 `vite` 开发服务器的创建和所有使用都移到 dev-only 条件分支后面,然后添加静态文件服务中间件来服务 `dist/client` 中的文件。
209204

0 commit comments

Comments
 (0)