菜单

服务器端渲染

相关源文件

Vite 中的服务器端渲染 (SSR) 指的是在服务器上渲染 JavaScript 前端框架(如 React、Vue、Svelte)的能力,生成 HTML,然后在客户端进行应用程序的水合(hydration)。这是一个底层的 API,主要面向库和框架作者。

要将 Vite 与传统服务器端框架(如 Rails、Laravel、Express)集成,请参阅 后端集成 文档。

系统概览

Vite 中的 SSR 系统提供了开发和生产工作流程,以支持在服务器上渲染前端应用程序。核心组件处理服务器端执行的模块转换和加载。

SSR 开发架构

SSR 构建管线

来源:packages/vite/src/node/ssr/ssrModuleLoader.ts14-105 packages/vite/src/node/ssr/ssrTransform.ts50-61 packages/vite/src/node/ssr/runtime/serverModuleRunner.ts1-20

源代码结构

Vite 中的典型 SSR 应用程序具有以下文件结构

- index.html          # Template with placeholder for server-rendered markup
- server.js           # Main application server
- src/
  - main.js           # Exports env-agnostic (universal) app code
  - entry-client.js   # Mounts the app to a DOM element
  - entry-server.js   # Renders the app using the framework's SSR API

index.html 将引用 entry-client.js 并包含一个占位符,用于注入服务器渲染的标记。

您可以改用任何您喜欢的占位符,而不是 <!--ssr-outlet-->

对于 SSR 和客户端环境之间的条件逻辑,请使用

来源:docs/guide/ssr.md28-63

设置开发服务器

对于开发中的 SSR,建议使用 Vite 的中间件模式

示例服务器实现

ssrLoadModule 函数使用 SSRCompatModuleRunner 类在 SSR 环境中加载和执行模块。

模块加载架构

SSRCompatModuleRunner 扩展了 ModuleRunner,并通过以下方式提供了与 Vite 开发服务器的兼容性:

  • 通过 createServerModuleRunnerTransport 创建服务器端模块运行器传输
  • 与开发环境的热重载通道集成
  • viteMod.ssrModule 中缓存模块导出
  • 将错误存储在 viteMod.ssrError 中以供重用
  • 使用 ESModulesEvaluator 进行模块执行

来源:packages/vite/src/node/ssr/ssrModuleLoader.ts14-105 packages/vite/src/node/ssr/runtime/serverModuleRunner.ts1-30

模块转换

ssrTransform 函数通过重写导入、导出和引用来转换 ES 模块,使其与服务器端执行兼容。

转换过程

运行时键常量

转换使用在 ssrTransform.ts 中定义的特定运行时键

常量目的用途
ssrModuleExportsKey模块导出对象__vite_ssr_exports__
ssrImportKey导入函数__vite_ssr_import__
ssrDynamicImportKey动态导入函数__vite_ssr_dynamic_import__
ssrExportAllKey导出所有函数__vite_ssr_exportAll__
ssrImportMetaKeyimport.meta 替换__vite_ssr_import_meta__

转换示例

命名导入转换

导出函数转换

动态导入转换

导入语句提升

转换会提升导入语句,以确保正确的执行顺序。defineImport 函数处理此过程。

  • 生成唯一的导入标识符(__vite_ssr_import_${uid}__
  • 使用 MagicString.move() 将导入语句移动到顶部
  • 通过 hoistIndex 跟踪保留执行顺序
  • 处理重新导出和命名空间导入

来源:packages/vite/src/node/ssr/ssrTransform.ts42-153 packages/vite/src/node/ssr/ssrTransform.ts255-349 packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts15-37

为生产环境构建

要部署 SSR 项目进行生产,您需要

  1. 正常生成客户端构建
  2. 生成 SSR 构建,可以直接导入

--ssr 标志指示 SSR 构建并指定 SSR 入口点。生产服务器将

  • 使用 dist/client/index.html 作为模板
  • dist/server/entry-server.js 导入服务器入口
  • dist/client 提供静态文件

来源:docs/guide/ssr.md170-199

生成预加载指令

--ssrManifest 标志生成一个 JSON 文件,其中包含模块 ID 与其关联的块和资源的映射。

这将生成 dist/client/.vite/ssr-manifest.json,其内容如下:

框架需要收集渲染期间使用的模块 ID 来利用此清单。例如,Vue 会自动注册使用的组件模块 ID。

来源:docs/guide/ssr.md201-226 packages/vite/src/node/ssr/ssrManifestPlugin.ts1-30

预渲染/SSG

如果路由和数据是预先知道的,您可以使用与生产 SSR 相同的逻辑将路由预渲染为静态 HTML。这也被称为静态站点生成 (SSG)。

示例脚本

来源:docs/guide/ssr.md224-227

模块运行器和优化

Vite 的 SSR 系统包含一个模块运行器架构,用于高效的服务器端执行和依赖处理。

模块运行器架构

SSR 依赖优化

SSR 环境支持通过配置进行依赖优化

配置示例

选项目的示例
ssr.external强制外部化['lodash', 'axios']
ssr.noExternal防止外部化['@my/package']
ssr.optimizeDeps.include预打包以用于 SSR['@vitejs/cjs-external']

模块执行和缓存

SSRCompatModuleRunner 实现了智能缓存

  • 模块重用:使用 viteMod.ssrModule 获取缓存的导出
  • 错误持久化:将错误存储在 viteMod.ssrError
  • 图集成:通过 getModuleById() 与 Vite 的模块图链接
  • 外部模块支持:处理没有服务器 ID 的外部模块

directRequest() 方法提供了核心执行逻辑。

此方法与 Vite 的模块图集成,以确保在开发和生产环境中的一致模块加载和错误处理。

来源:packages/vite/src/node/ssr/ssrModuleLoader.ts65-105 packages/vite/src/node/ssr/runtime/__tests__/server-runtime.spec.ts395-410 packages/vite/src/node/ssr/runtime/__tests__/utils.ts20-50

SSR 特定插件逻辑

插件可以使用 ssr 标志来实现 SSR 特定逻辑。

resolveIdloadtransform 钩子都在其 options 参数中接收一个 ssr 标志。

来源: docs/guide/ssr.md282-309 docs/guide/api-plugin.md159-170

SSR 的 JavaScript API

Vite 开发服务器通过 ViteDevServer 接口公开了特定于 SSR 的方法。

核心 SSR 方法

ssrLoadModule 方法

ssrLoadModule 函数的签名和行为

实现细节

  • 使用 server.environments.ssr 进行 SSR 环境设置
  • 创建或重用 server._ssrCompatModuleRunner
  • 调用 unwrapId() 来规范化 URL
  • 委托给 instantiateModule() 进行实际加载
  • 通过 environment.moduleGraph.ensureEntryFromUrl() 处理模块图入口创建
  • 将 SSR 错误缓存到 mod.ssrError 中,以实现一致的错误抛出

错误处理和堆栈跟踪

ssrFixStacktrace 方法与 Vite 的错误处理集成

  • 使用 SSR 堆栈跟踪工具中的 ssrFixStacktrace()
  • 应用源映射更正以改进调试
  • buildErrorMessage() 集成,以实现一致的错误格式化
  • 通过 environment.logger.error() 记录带有时间戳的错误

模块运行程序集成

SSR 系统使用兼容层 (SSRCompatModuleRunner),该层

  • 扩展了核心的 ModuleRunner
  • 提供 createServerModuleRunnerTransport() 集成
  • 默认禁用源映射拦截和 HMR
  • 实现 directRequest() 重写以集成 Vite 模块图

来源: packages/vite/src/node/ssr/ssrModuleLoader.ts14-105 packages/vite/src/node/ssr/ssrStacktrace.ts1-20 packages/vite/src/node/server/middlewares/error.ts1-30

示例项目

Vite 提供了各种框架的示例 SSR 设置作为参考。

  • Vanilla
  • Vue
  • React
  • Preact
  • Svelte
  • Solid

这些示例可在 create-vite-extra 仓库中找到,并且可以使用 create-vite 通过在框架选项中选择 Others > create-vite-extra 来脚手架化。

来源: docs/guide/ssr.md15-26 packages/create-vite/README.md1-71