Expo Router 从 SDK 55 升级到 56 后如何用 codemod 替换 @react-navigation/* 导入
从 SDK 56 开始,Expo Router 不再支持在应用代码中从外部 @react-navigation/* 包导入,需要把这些导入换成对应的 expo-router 入口。运行时 API 本身没有变化,只有模块说明符(module specifier)发生了移动。如果你的项目已从 SDK 55 升到 SDK 56、应用代码里仍残留 @react-navigation/* 导入,就可以按本文流程:在仓库根目录运行官方的 expo-codemod transform 批量改写导入,处理两个没有直接替代项的包,再用 bundler 验证没有漏改的旧导入。
本文依据官方迁移页 SDK 55 to 56 与 expo-codemod 包文档。
变更范围:只是导入路径
先确认改动边界:这次升级只替换导入的包名,你调用的 API 不变。文档给出的映射如下:
| React Navigation source | Expo Router target |
|---|---|
@react-navigation/native |
expo-router/react-navigation |
@react-navigation/core |
expo-router/react-navigation |
@react-navigation/elements |
expo-router/react-navigation |
@react-navigation/routers |
expo-router/react-navigation |
@react-navigation/stack |
expo-router/js-stack |
@react-navigation/bottom-tabs |
expo-router/js-tabs |
@react-navigation/material-top-tabs |
expo-router/js-top-tabs |
@react-navigation/native-stack |
无直接替代,改用 Stack layout |
@react-navigation/drawer |
无直接替代,改用 Drawer layout |
最后两个包不会被 codemod 自动改写,需要结构化的手动迁移,见“处理两个没有直接替代项的包”。
运行 codemod
在项目根目录执行。注意这条命令会改写指定路径下源文件中的导入语句,transform 只处理你传入的路径或 glob 匹配到的文件:
# npm
npx expo-codemod sdk-56-expo-router-react-navigation-replace src
# yarn
yarn dlx expo-codemod sdk-56-expo-router-react-navigation-replace src
# pnpm
pnpm dlx expo-codemod sdk-56-expo-router-react-navigation-replace src
# bun
bunx expo-codemod sdk-56-expo-router-react-navigation-replace src
把 src 替换成你应用代码所在的目录或 glob。expo-codemod CLI 的用法是 npx expo-codemod <transform> <paths...>,可以传多个路径;glob 需要加引号防止 shell 先展开:
npx expo-codemod sdk-56-expo-router-react-navigation-replace '**/*.{ts,tsx,js,jsx}'
这个 transform 做的事:
- 把映射表中的
@react-navigation/*命名导入改写为对应的expo-router入口; - 把同一文件中重复的
expo-router导入合并成一条(type-only 导入与 value 导入混合时按 inlinetype标记处理)。
两个限制来自 codemod 的文档与实现 sdk-56-expo-router-react-navigation-replace.ts:
- 对映射包而言,默认导入(
import X from ...)和命名空间导入(import * as X from ...)不支持,只有命名导入(import { A } from ...)能被安全改写。遇到时 codemod 会输出 “Unsupported import style — manual change needed” 错误块,要求你改成命名导入后重新运行; - 遇到不支持的包(
native-stack、drawer)时不会改写该文件的导入,只输出 “Migration required — manual change needed” 并列出文件位置。
处理两个没有直接替代项的包
如果代码里用了 @react-navigation/native-stack 或 @react-navigation/drawer,codemod 无法自动替换,它只报告位置并提示手动修改:
@react-navigation/native-stack→ 改用 expo-router 的Stacklayout;@react-navigation/drawer→ 改用 expo-router 的Drawerlayout。
迁移页的映射表中这两行分别链到对应的 layout 文档(/router/advanced/stack 与 /router/advanced/drawer),按这些页面把对应导航代码改为基于文件的 layout。这两处是唯一需要真正重构代码的部分,codemod 覆盖不到。
验证迁移是否完整
文档给出了两类可核对的信号:
- codemod 的输出。运行后,错误块中列出的文件需要逐个手动处理;没有出现在输出里、且文件内容已按映射表改写的,即为完成。
- bundler 报错。SDK 56 中,应用代码如果仍从
@react-navigation/*导入,bundler 会报错。改完后正常启动项目(如npx expo start),不再出现这类报错,说明应用代码中的旧导入已清完。
阅读改写后的代码时,按第一节的映射表核对导入路径。这里有一处文档不一致需要你注意:expo-codemod README 的表格把 @react-navigation/native 写成映射到 expo-router(主入口),而迁移页和 codemod 实现源码都使用 expo-router/react-navigation。本文以迁移页与代码实际生成的导入为准;./react-navigation 入口在 expo-router 包的 exports 中确有声明,./js-stack、./js-tabs、./js-top-tabs 同样如此。
手动迁移:codemod 跑不了时的替代路径
如果环境不允许运行 codemod,就按映射表逐个改。文档给出的示例:
// Before (SDK 55)
import { ThemeProvider, DarkTheme } from '@react-navigation/native';
import { createMaterialTopTabNavigator } from '@react-navigation/material-top-tabs';
// After (SDK 56)
import { ThemeProvider, DarkTheme } from 'expo-router/react-navigation';
import { createMaterialTopTabNavigator } from 'expo-router/js-top-tabs';
完整映射见第一节表格;native-stack 与 drawer 仍需改用 Stack / Drawer layout。
第三方库与兼容 shim
很多第三方库仍然从 @react-navigation/core 导入。为平滑 SDK 56 过渡,Expo CLI 会在这些导入来自 node_modules 时自动把它们改写成 expo-router,你的应用代码不受这次改写影响。文档明确说明这是临时的兼容 shim:在自动改写移除之前,会有一份专门的库迁移指南解释替代方式。
如果你要关闭这个行为,在启动 bundler 前设置环境变量 EXPO_ROUTER_DISABLE_RN_NAVIGATION_CHECK=1。注意这同时会禁用“应用代码从 @react-navigation/* 导入”时的 bundler 报错:
# npm
EXPO_ROUTER_DISABLE_RN_NAVIGATION_CHECK=1 npx expo start
# yarn
EXPO_ROUTER_DISABLE_RN_NAVIGATION_CHECK=1 yarn expo start
# pnpm
EXPO_ROUTER_DISABLE_RN_NAVIGATION_CHECK=1 pnpm expo start
# bun
EXPO_ROUTER_DISABLE_RN_NAVIGATION_CHECK=1 bun expo start
这个变量会同时关掉检测漏改旧导入的报错,迁移完成前使用它会让未改完的导入不被暴露,只在你明确需要绕过这个检查时使用。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0629
MiniCPM5-2BMiniCPM5-2B 是一款面向端侧、本地部署和资源受限场景的 2B 稠密 Transformer,能够达到同尺寸开源模型 SOTA 水平。Markdown00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
HivisionIDPhotos⚡️HivisionIDPhotos: a lightweight and efficient AI ID photos tools. 一个轻量级的AI证件照制作算法。Python07
DragonOSDragonOS is an operating system developed from scratch using Rust, with Linux compatibility. It is designed for **Serverless** scenarios. 使用Rust从0自研内核,具有Linux兼容性的操作系统,面向云计算Serverless场景而设计。Rust00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00