This documentation is available as Markdown for AI agents and LLMs. See the full Markdown index or append .md to any documentation URL.
静态渲染
编辑页面
了解如何使用 Expo Router 将路由渲染为静态 HTML 和 CSS 文件。
要在网页上启用搜索引擎优化(SEO),你必须对应用进行静态渲染。本指南将带你完成 Expo Router 应用的静态渲染过程。
使用静态渲染时,数据加载器 会在构建过程中执行,并将其结果嵌入到输出的 HTML 文件中。
设置
1
在你项目的 应用配置 中启用静态渲染:
2
启动开发服务器:
生产环境
在 SDK 58 及更高版本中,你可以通过在 expo-router 配置插件中设置 apiRoutes: true,将静态渲染与 API routes 结合使用。这会将预渲染的 HTML 和 API routes 导出到 dist/server,客户端资源则放在 dist/client,并且需要部署服务器。
要为生产环境打包静态网站,请运行导出命令:
这会创建一个 dist 目录,其中包含静态渲染的网站。如果本地 public 目录中有文件,这些文件也会一并复制。
启用 API routes 后,请使用 npx expo serve 在本地测试生产构建。否则,请运行以下命令,并在浏览器中打开链接:
禁用 API routes 后,该项目几乎可以部署到任何托管服务。请注意,这既不是单页应用,也不包含自定义服务器 API。这意味着动态路由(例如 src/app/[id].tsx)不会自动生效。你可能需要构建 serverless function 来处理动态路由。
动态路由
static 输出会为每个路由生成 HTML 文件。这意味着动态路由(src/app/[id].tsx)开箱即用并不起作用。你可以使用 generateStaticParams 函数提前生成已知路由。
这会在 dist 目录中为每篇文章输出一个文件。例如,如果 generateStaticParams 方法返回 [{ id: "alpha" }, { id: "beta" }],则会生成以下文件:
distblogalpha.htmlbeta.htmlgenerateStaticParams
由 Expo CLI 在 Node.js 环境中于构建时求值的仅服务器函数。这意味着它可以访问 __dirname、process.cwd()、process.env 等更多内容。它还可以访问进程中可用的每个环境变量。不过,前缀为 EXPO_PUBLIC_ 的值不会在浏览器环境中运行,因此它无法访问诸如 localStorage 或 document 之类的浏览器 API。它也无法访问诸如 expo-camera 或 expo-location 之类的原生 Expo API。
generateStaticParams 会从嵌套父级向子级级联传递。级联参数会传递给每一个导出 generateStaticParams 的动态子路由。
现在,动态子路由将被调用两次,一次使用 { id: 'one' },另一次使用 { id: 'two' }。所有组合都必须被考虑到。
使用 process.cwd() 读取文件
由于 Expo Router 会将你的代码编译到一个单独的目录中,因此你不能使用 __dirname 来构造路径,因为它的值会与预期不同。
相反,请使用 process.cwd(),它会返回项目正在编译的目录。
根 HTML
默认情况下,每个页面都会被一些简短的 HTML 脚手架包裹,这称为 根 HTML。
你可以在项目中创建 src/app/+html.tsx 文件来自定义根 HTML 文件。该文件导出一个 React 组件,它只会在 Node.js 中运行,这意味着其中不能导入全局 CSS。该组件会包裹 app 目录中的所有路由。这对于添加全局 <head> 元素或禁用页面滚动非常有用。
注意:全局上下文提供者应放在 根布局 组件中,而不是根 HTML 组件中。
children属性会包含根<div id="root" />标签。- JavaScript 脚本会在静态渲染之后附加。
- React Native Web 样式会自动进行静态注入。
- 不要将全局 CSS 导入到这个文件中。应改为使用 根布局。Expo Router 会从根布局开始遍历依赖图,因此在其他地方导入 CSS 可能会导致意外的加载顺序,使 node_modules 中的 CSS 优先于你的自定义样式。
- 诸如
window.location之类的浏览器 API 在此组件中不可用,因为它只会在静态渲染期间于 Node.js 中运行。
expo-router/html
来自 expo-router/html 的导出与根 HTML 组件相关。
ScrollViewStyleReset:对于带有根<ScrollView />的全屏 React Native Web 应用,应使用根样式重置,以确保与原生端保持一致。
Meta 标签
你可以使用 expo-router 中的 <Head /> 模块为页面添加 meta 标签:
可以使用相同的 API 动态更新 head 元素。不过,为了 SEO,提前静态渲染 head 元素会很有用。
静态文件
Expo CLI 支持一个根 public 目录,在静态渲染期间会被复制到 dist 目录。这对于添加图片、字体和其他资源等静态文件非常有用。
publicfavicon.icologo.png.well-knownapple-app-site-association警告 某些路径(例如
/assets)是 Metro 预留的。请避免将文件放在 public/assets/ 或其他预留路径中。完整列表请参见 预留路径。
这些文件会在静态渲染期间被复制到 dist 目录:
distindex.htmlfavicon.icologo.png.well-knownapple-app-site-association_expostaticjsindex-xxx.jscssindex-xxx.css提示 仅限 Web:静态资源可以在运行时代码中通过相对路径访问。例如,logo.png 可以通过
/logo.png访问:
字体
Expo Font 在 Expo Router 中对字体加载提供自动静态优化。当你使用 expo-font 加载字体时,Expo CLI 会自动提取字体资源并将其嵌入页面的 HTML 中,从而实现预加载、更快的 hydration 以及更少的布局偏移。
下面的代码片段会将 Inter 加载到命名空间中,并在 Web 上进行静态优化:
这会生成以下静态 HTML:
- 静态字体优化要求字体同步加载。如果字体没有被静态优化,可能是因为它是在
useEffect、延迟组件或异步函数中加载的。 - 静态优化仅支持
expo-font中的Font.loadAsync和Font.useFonts。只要包装函数是同步的,就支持包装函数。
常见问题
如何添加自定义服务器?
添加自定义服务器没有规定的方式。你可以使用任何你想要的服务器。不过,你需要自己处理动态路由。你可以使用 generateStaticParams 函数为已知路由生成静态 HTML 文件。
在 SDK 58 及更高版本中,在 expo-router 配置插件中设置 apiRoutes: true,即可在静态 HTML 的同时添加 API routes。要在请求时渲染页面,请使用服务器渲染。
服务端渲染
当 web.output: 'static' 时,不支持在请求时进行渲染。要在每次请求时动态渲染页面,请改用服务器渲染,并将 web.output 设置为 'server'。
我可以将静态渲染的网站部署到哪里?
你可以将静态渲染的网站部署到任何静态托管服务。以下是一些常见的选项:
注意: 你不需要在静态托管服务上添加单页应用风格的重定向。静态网站不是单页应用。它是由静态 HTML 文件组成的集合。