Vite 中的服务器端渲染 (SSR) 指的是在服务器上渲染 JavaScript 前端框架(如 React、Vue、Svelte)的能力,生成 HTML,然后在客户端进行应用程序的水合(hydration)。这是一个底层的 API,主要面向库和框架作者。
要将 Vite 与传统服务器端框架(如 Rails、Laravel、Express)集成,请参阅 后端集成 文档。
Vite 中的 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 和客户端环境之间的条件逻辑,请使用
对于开发中的 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__ |
ssrImportMetaKey | import.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 项目进行生产,您需要
--ssr 标志指示 SSR 构建并指定 SSR 入口点。生产服务器将
dist/client/index.html 作为模板dist/server/entry-server.js 导入服务器入口dist/client 提供静态文件--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
如果路由和数据是预先知道的,您可以使用与生产 SSR 相同的逻辑将路由预渲染为静态 HTML。这也被称为静态站点生成 (SSG)。
示例脚本
Vite 的 SSR 系统包含一个模块运行器架构,用于高效的服务器端执行和依赖处理。
SSR 环境支持通过配置进行依赖优化
配置示例
| 选项 | 目的 | 示例 |
|---|---|---|
ssr.external | 强制外部化 | ['lodash', 'axios'] |
ssr.noExternal | 防止外部化 | ['@my/package'] |
ssr.optimizeDeps.include | 预打包以用于 SSR | ['@vitejs/cjs-external'] |
SSRCompatModuleRunner 实现了智能缓存
viteMod.ssrModule 获取缓存的导出viteMod.ssrError 中getModuleById() 与 Vite 的模块图链接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 特定逻辑。
resolveId、load 和 transform 钩子都在其 options 参数中接收一个 ssr 标志。
来源: docs/guide/ssr.md282-309 docs/guide/api-plugin.md159-170
Vite 开发服务器通过 ViteDevServer 接口公开了特定于 SSR 的方法。
ssrLoadModule 函数的签名和行为
实现细节
server.environments.ssr 进行 SSR 环境设置server._ssrCompatModuleRunnerunwrapId() 来规范化 URLinstantiateModule() 进行实际加载environment.moduleGraph.ensureEntryFromUrl() 处理模块图入口创建mod.ssrError 中,以实现一致的错误抛出ssrFixStacktrace 方法与 Vite 的错误处理集成
ssrFixStacktrace()buildErrorMessage() 集成,以实现一致的错误格式化environment.logger.error() 记录带有时间戳的错误SSR 系统使用兼容层 (SSRCompatModuleRunner),该层
ModuleRunner 类createServerModuleRunnerTransport() 集成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 设置作为参考。
这些示例可在 create-vite-extra 仓库中找到,并且可以使用 create-vite 通过在框架选项中选择 Others > create-vite-extra 来脚手架化。
来源: docs/guide/ssr.md15-26 packages/create-vite/README.md1-71