diff --git a/guide/api-environment-frameworks.md b/guide/api-environment-frameworks.md index ccfac4f1..070ebd97 100644 --- a/guide/api-environment-frameworks.md +++ b/guide/api-environment-frameworks.md @@ -13,9 +13,13 @@ 请与我们分享您的反馈。 ::: -## 环境和框架 {#environments-and-frameworks} +## 开发环境通信级别 -隐式的 `ssr` 环境和其他非客户端环境在开发过程中默认使用 `RunnableDevEnvironment`。虽然这要求运行时与 Vite 服务器运行的环境相同,但这与 `ssrLoadModule` 类似,允许框架迁移并为其 SSR 开发方案启用模块热替换(HMR)。你可以使用 `isRunnableDevEnvironment` 函数来保护任何可运行的环境。 +由于环境可能在不同的运行时环境中运行,与环境的通信可能会受到运行时环境的限制。为了使框架能够轻松编写与运行时环境无关的代码,环境 API 提供了三种通信级别。 + +### `RunnableDevEnvironment` + +`RunnableDevEnvironment` 是一种能够传递任意值的环境。隐式 `ssr` 环境及其他非客户端环境在开发阶段默认使用 `RunnableDevEnvironment`。虽然这要求运行时与 Vite 服务器运行的环境一致,但其工作原理与 `ssrLoadModule` 类似,并允许框架迁移并为其 SSR 开发流程启用 HMR。您可以通过 `isRunnableDevEnvironment` 函数对任何可运行环境进行保护。 ```ts export class RunnableDevEnvironment extends DevEnvironment { @@ -43,50 +47,7 @@ if (isRunnableDevEnvironment(server.environments.ssr)) { 只有在第一次使用时,`runner` 才会被加载。请注意,当通过调用 `process.setSourceMapsEnabled` 或在不支持的情况下重写 `Error.prepareStackTrace` 创建 `runner` 时,Vite 会启用源映射支持。 ::: -那些通过 [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Window/fetch) 与它们的运行环境进行交互的框架可以使用 `FetchableDevEnvironment`,它提供了一种标准化的方式来通过 `handleRequest` 方法处理请求: - -```ts -import { - createServer, - createFetchableDevEnvironment, - isFetchableDevEnvironment, -} from 'vite' - -const server = await createServer({ - server: { middlewareMode: true }, - appType: 'custom', - environments: { - custom: { - dev: { - createEnvironment(name, config) { - return createFetchableDevEnvironment(name, config, { - handleRequest(request: Request): Promise | Response { - // 处理请求并返回响应 - }, - }) - }, - }, - }, - }, -}) - -// 现在,任何使用环境 API 的人都可以调用 `dispatchFetch` -if (isFetchableDevEnvironment(server.environments.custom)) { - const response: Response = await server.environments.custom.dispatchFetch( - new Request('/request-to-handle'), - ) -} -``` - -:::warning -Vite 会检查 `dispatchFetch` 方法的输入和输出:请求必须是全局 `Request` 类的一个实例,而响应必须是全局 `Response` 类的一个实例。如果不满足这些条件,Vite 将会抛出一个 `TypeError`。 - -尽管 `FetchableDevEnvironment` 是作为一个类来实现的,但请注意,Vite 团队可能会随时更改它,因为其被视为实现细节部分。 -::: - -## 默认 `RunnableDevEnvironment` {#default-runnabledevenvironment} - -假设我们有一个配置为中间件模式的 Vite 服务器,如 [SSR 设置指南](/guide/ssr#setting-up-the-dev-server) 所述,我们可以使用环境 API 来实现 SSR 中间件。请记住,它不必命名为 `ssr`,因此在本例中我们将其命名为 `server`。错误处理部分已省略。 +假设已按照[SSR 设置指南](/guide/ssr#setting-up-the-dev-server)中描述的方式配置了 Vite 服务器的中间件模式,现在我们使用环境 API 实现 SSR 中间件。请注意,它不必命名为 `ssr`,因此在本示例中我们将它命名为 `server`。错误处理已省略。 ```js import fs from 'node:fs' @@ -142,42 +103,62 @@ app.use('*', async (req, res, next) => { }) ``` -## 运行时无关的 SSR {#runtime-agnostic-ssr} - -由于 `RunnableDevEnvironment` 只能用于在与 Vite 服务器相同的运行时中运行代码,它需要一个可以运行 Vite 服务器的运行时(即与 Node.js 兼容的运行时)。这意味着您需要使用原始的 `DevEnvironment` 来使其对运行时无关。 +### `FetchableDevEnvironment` -:::info `FetchableDevEnvironment` 提议 +:::info -最初的提议是在 `DevEnvironment` 类上有一个 `run` 方法,该方法将允许消费者通过使用 `transport` 选项在运行器端调用一个导入。在我们的测试中,我们发现 API 还不够通用,以至于我们暂时不开始推荐它。目前,我们正在寻求对 [`FetchableDevEnvironment` 提议](https://github.com/vitejs/vite/discussions/18191) 的反馈。 +我们正在征集对[`FetchableDevEnvironment`提案](https://github.com/vitejs/vite/discussions/18191)的反馈意见。 ::: -`RunnableDevEnvironment` 有一个 `runner.import` 函数,返回模块的值。但是这个函数在原始的 `DevEnvironment` 中不可用,并且需要将使用 Vite 的 API 和用户模块的代码解耦。 +`FetchableDevEnvironment` 是一种可以通过 [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Window/fetch) 接口与运行时进行通信的环境。由于 `RunnableDevEnvironment` 仅能在有限的运行时环境中实现,我们建议使用 `FetchableDevEnvironment` 替代 `RunnableDevEnvironment`。 -例如,下面的例子中,使用 Vite API 的代码使用了用户模块的值: +该环境通过`handleRequest`方法提供了一种标准化的请求处理方式: ```ts -// 使用 Vite API 的代码 -import { createServer } from 'vite' - -const server = createServer() -const ssrEnvironment = server.environment.ssr -const input = {} +import { + createServer, + createFetchableDevEnvironment, + isFetchableDevEnvironment, +} from 'vite' -const { createHandler } = await ssrEnvironment.runner.import('./entrypoint.js') -const handler = createHandler(input) -const response = handler(new Request('/')) +const server = await createServer({ + server: { middlewareMode: true }, + appType: 'custom', + environments: { + custom: { + dev: { + createEnvironment(name, config) { + return createFetchableDevEnvironment(name, config, { + handleRequest(request: Request): Promise | Response { + // handle Request and return a Response + }, + }) + }, + }, + }, + }, +}) -// ------------------------------------- -// ./entrypoint.js -export function createHandler(input) { - return function handler(req) { - return new Response('hello') - } +// Any consumer of the environment API can now call `dispatchFetch` +if (isFetchableDevEnvironment(server.environments.custom)) { + const response: Response = await server.environments.custom.dispatchFetch( + new Request('/request-to-handle'), + ) } ``` -如果你的代码可以在与用户模块相同的运行时中运行(即,它不依赖于 Node.js 特定的 API),你可以使用虚拟模块。这种方法避免了从使用 Vite API 的代码中获取值的需求。 +:::warning +Vite 验证 `dispatchFetch` 方法的输入和输出:请求必须是全局 `Request` 类的实例,响应必须是全局 `Response` 类的实例。如果不符合此条件,Vite 将抛出 `TypeError` 异常。 + +请注意,尽管 `FetchableDevEnvironment` 作为类实现,但 Vite 团队将其视为实现细节,可能随时发生变化。 +::: + +### raw `DevEnvironment` + +如果环境未实现 `RunnableDevEnvironment` 或 `FetchableDevEnvironment` 接口,您需要手动设置通信。 + +如果您的代码可以在与用户模块相同的运行时环境中运行(即不依赖于 Node.js 特定的 API),您可以使用虚拟模块。这种方法消除了通过 Vite 的 API 从代码中访问值的必要性。 ```ts // 使用 Vite API 的代码 @@ -198,8 +179,6 @@ const input = {} // 使用每个环境工厂暴露的函数来运行代码 // 检查每个环境工厂提供了什么 if (ssrEnvironment instanceof RunnableDevEnvironment) { - ssrEnvironment.runner.import('virtual:entrypoint') -} else if (ssrEnvironment instanceof CustomDevEnvironment) { ssrEnvironment.runEntrypoint('virtual:entrypoint') } else { throw new Error(`Unsupported runtime for ${ssrEnvironment.name}`) diff --git a/guide/api-environment-runtimes.md b/guide/api-environment-runtimes.md index c5c99733..b452b6cd 100644 --- a/guide/api-environment-runtimes.md +++ b/guide/api-environment-runtimes.md @@ -110,6 +110,8 @@ function createWorkerdDevEnvironment( } ``` +[`DevEnvironment` 具有多个通信级别](/guide/api-environment-frameworks#devenvironment-communication-levels)。为了便于框架编写与运行时无关的代码,我们建议实现尽可能灵活的通信级别。 + ## `ModuleRunner` 一个模块运行器在目标运行时中实例化。下一节中的所有 API 都从 `vite/module-runner` 导入,除非另有说明。这个导出入口文件尽可能保持轻量,仅导出创建模块运行器所需的最小部分。 diff --git a/guide/rolldown.md b/guide/rolldown.md index 8a9f6b67..018ac569 100644 --- a/guide/rolldown.md +++ b/guide/rolldown.md @@ -127,7 +127,7 @@ export default { rollupOptions: { output: { advancedChunks: { - groups: [{ name: 'vendor', test: /\/react(?:-dom)?// }] + groups: [{ name: 'vendor', test: /\/react(?:-dom)?/ }] } } }