ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

React Router 如何按 v8 最低版本要求与 future 标志分步从 v7 升级到 v8?

React Router 如何按 v8 最低版本要求与 future 标志分步从 v7 升级到 v8? React Router 如何按 v8 最低版本要求与 future 标志分步从 v7 升级到 v8【免费下载链接】react-routerDeclarative routing for React项目地址: https://gitcode.com/GitHub_Trending/re/react-router如果你的 React Router 应用还停在 v7想升到 v8官方升级指南 Upgrading from v7 给出的思路是先在 v7 上把最低依赖版本提上去、逐个开启 v8 的 future 标志并改好相关代码最后再执行一次npm install跳到 v8。官方明确建议每完成一步就提交一次代码并发布而不是全部改完再一次性上线——大多数标志可以按任意顺序采纳文档中会标注例外。适用对象包括 Framework、Data、Declarative 三种模式的项目模式区别本文会按模式区分每个步骤是否适用。第一步升级到最新的 v7.x在开启任何 future 标志或做调用点改动之前先把react-router升到 v7 的次新版本确保能拿到全部 v8 相关的标志npm install react-router7 react-router/{dev,node,etc.}7其中react-router/{dev,node,etc.}是文档中的占位写法代表你实际在用的配套包比如react-router/dev、react-router/node按项目里实际安装的替换。升级过程中可能出现一批 deprecation 警告这是预期现象文档说明这些警告对应下面各节要处理的变更。第二步核对 v8 的最低版本要求Upgrading from v7 的 Minimum Versions 一节列出依赖最低版本适用模式Node22.22framework、data、declarativeReact / react-dom19.2.7framework、data、declarativeVite7且需要开启future.v8_viteEnvironmentApi仅 framework 模式文档同时要求Framework 模式下要确认项目里任何自定义的 Vite 插件或配置都兼容 Vite 7。这些依赖要在升级 React Router 到 v8 之前更新完成。第三步逐个开启 v8 的 future 标志标志机制是 API 开发策略 的一部分破坏性变更先通过 future flag 引入开启后行为立即切换不开启则应用不受影响。以下按 v7 文档的顺序列出每个标志标注了适用模式。future.v8_middlewareframework、data 模式Middleware 让你能在匹配路径的Response生成前后运行代码支撑认证、日志、错误处理等可复用逻辑用法见 Middleware 文档。Framework 模式在react-router.config.ts中开启import type { Config } from react-router/dev/config; export default { future: { v8_middleware: true, }, } satisfies Config;Data 模式则在创建路由器时开启import { createBrowserRouter } from react-router; const router createBrowserRouter(routes, { future: { v8_middleware: true, }, });代码改动方面v7 文档给出的判断依据是如果你只在loader和action里使用了context参数——Framework 模式下使用react-router-serve的项目通常不需要改动只有自定义了带getLoadContext的服务器才需要按 middleware 文档迁移到新 API。Data 模式下需要按 middleware 文档补充Future模块的 TypeScript 类型增强让context获得正确类型。future.v8_splitRouteModulesframework 模式把clientLoader、clientAction、clientMiddleware、HydrateFallback等客户端路由导出拆成独立 chunk让它们在组件代码还在下载时就能获取并执行。设为true是选择性开启设为enforce则强制所有路由必须可拆分因共享代码无法拆分的路由会导致构建失败。import type { Config } from react-router/dev/config; export default { future: { v8_splitRouteModules: true, }, } satisfies Config;文档说明此标志是纯优化功能开启后无需任何代码改动。future.v8_viteEnvironmentApiframework 模式启用 Vite Environment API 支持文档说明此标志仅在 Vite 6 可用而 Framework 模式升到 v8 的最低要求是vite7且依赖此标志。多数用户不需要改动如果你的自定义 Vite 配置依赖旧的isSsrBuild参数——例如自定义服务器构建里设置build.rollupOptions.input——需要把这些配置移到按环境的 Environment API 配置下。v7 文档给出的 diff 示例import { reactRouter } from react-router/dev/vite; import { defineConfig } from vite; -export default defineConfig(({ isSsrBuild }) ({ - build: { - rollupOptions: isSsrBuild - ? { - input: ./server/app.ts, - } - : undefined, - }, export default defineConfig({ environments: { ssr: { build: { rollupOptions: { input: ./server/app.ts, }, }, }, }, plugins: [reactRouter()], -})); });即把顶层build里的 SSRrollupOptions移到environments.ssr.build下isSsrBuild参数不再使用。future.v8_passThroughRequestsframework 模式默认情况下 React Router 会规范化传给loader、action、middleware的request.url去掉.data后缀和?index、?_routes这类内部参数。开启该标志后直接透传原始 HTTPRequest好处是减少关键路径上的new Request()调用并且可以在 handler 里通过 URL 是否带.data后缀区分 document 请求和数据请求。import type { Config } from react-router/dev/config; export default { future: { v8_passThroughRequests: true, }, } satisfies Config;如果你的代码依赖检查request.url要排查对 URL 格式的假设。v7 文档给出前后对照Before 是旧行为After 是开启标志后的写法// ❌ Before: assuming no .data suffix in request.url pathname export async function loader({ request, }: Route.LoaderArgs) { let url new URL(request.url); if (url.pathname /path) { // This check might now behave differently because the request pathname will // contain the .data suffix on data requests } } // ✅ After: use url for normalized routing logic and request.url // for raw routing logic export async function loader({ request, url, }: Route.LoaderArgs) { if (url.pathname /path) { // This will always have the .data suffix stripped } // And now you can distinguish between document versus data requests let isDataRequest new URL( request.url, ).pathname.endsWith(.data); }即规范化的路由判断改用新的url参数一个去掉了.data后缀的URL实例原始请求特征判断才用request.url。future.v8_trailingSlashAwareDataRequestsframework 模式Framework 模式从.dataURL 提供数据请求。此前带尾斜杠与不带尾斜杠的路由可能映射到同一个.dataURL因为生成 URL 时没有考虑尾斜杠。该标志让数据请求 URL 保留尾斜杠语义避免应用区分/a/b/c与/a/b/c/时产生歧义。import type { Config } from react-router/dev/config; export default { future: { v8_trailingSlashAwareDataRequests: true, }, } satisfies Config;开启后/a/b/c/这类带尾斜杠路由的数据请求从/a/b/c.data变为新的/a/b/c/_.data格式根路由的数据请求也从/_root.data变为/_.data。文档给出的完整对照以/a/b/c与/a/b/c/两个 URL 为例URL/a/b/cHTTP pathnamerequestpathnameDocument/a/b/c/a/b/cData/a/b/c.data/a/b/cURL/a/b/c/开启标志后HTTP pathnamerequestpathnameDocument/a/b/c//a/b/c/Data/a/b/c/_.data/a/b/c/代码改动点只有一处如果你的应用、CDN、缓存或 rewrite 规则会匹配.data请求 URL要更新它们以处理新的_.data格式。第四步处理不受标志控制的其他破坏性变更以下变更没有 future flag 开关但都允许你在 v7 上先把代码改好Upgrading from v7 的 Other Breaking Changes 一节。meta/matches的data改为loaderDataframework 模式v8 在几个位置移除了废弃的data字段改用loaderDatameta函数的data参数、meta函数的matches参数matches[i].data、以及useMatches()的返回值。meta函数中把data换成loaderDataexport function meta({ - data, loaderData, matches, }: Route.MetaArgs) { return [ { - title: data.title, title: loaderData.title, }, ]; }读取父级匹配的数据时同样替换export function meta({ matches }: Route.MetaArgs) { let rootMatch matches.find((match) match.id root); - let rootData rootMatch?.data; let rootData rootMatch?.loaderData; return [{ title: rootData?.siteTitle }]; }useMatches()的调用处export default function Component({ matches, loaderData }: ComponentProps) { let matches useMatches(); - const rootLoaderData matches[0].data; const rootLoaderData matches[0].loaderData; // ... }移除react-router-dom包framework、data、declarative 模式v8 移除react-router-dom这个 re-export 包DOM 相关 API 从react-router/dom导入其余全部从react-router导入。npm uninstall react-router-dom-import { Link, useLocation } from react-router-dom; import { Link, useLocation } from react-router;DOM 专属 API 走react-router/dom-import { RouterProvider } from react-router-dom; import { RouterProvider } from react-router/dom;Cloudflare Vite 插件framework 模式v8 移除了 React Router 内置的 Cloudflare dev proxyCloudflare 项目改用语义为cloudflare的官方插件。把cloudflareDevProxy替换为cloudflareimport { reactRouter } from react-router/dev/vite; -import { cloudflareDevProxy } from react-router/dev/vite/cloudflare; import { cloudflare } from cloudflare/vite-plugin; import { defineConfig } from vite; export default defineConfig({ plugins: [ - cloudflareDevProxy(), cloudflare(), reactRouter(), ], });react-router/architect的useRequestContextDomainNameframework 模式v7 中 architect adapter 创建request时使用X-Forwarded-Host回退到Host头v8 默认改用event.requestContext.domainName回退到Host头。想在 v7 上提前采纳 v8 行为就传入useRequestContextDomainName: trueimport { createRequestHandler } from react-router/architect; import * as build from ./build/server; export const handler createRequestHandler({ build, useRequestContextDomainName: true, });该选项在 v8 中会被移除因为event.requestContext.domainName行为成为默认。第五步升级 React Router 到 v8前面的依赖、标志和代码改动都完成后执行最终安装。data / declarative 模式npm install react-routerlatestframework 模式npm install react-routerlatest react-router/{dev,node,etc.}latest同样{dev,node,etc.}替换为你实际使用的react-router/*包。验证方式与限制文档对每个阶段的完成判定是流程性的升级 v7.x 时留意新出现的 deprecation 警告对应上文各节每个 future 标志和代码改动单独提交并跑通后再继续下一个官方推荐 make a commit after each step and ship it。标志顺序基本任意但 v7 文档把future.v8_viteEnvironmentApi与 Vite 7 绑定Framework 模式的vite7明确要求该标志所以 Framework 模式应把它和 Vite 升级放在同一批处理。v8_splitRouteModules设为enforce时无法拆分的路由会直接构建失败这是文档明确给出的失败判定不确定时先保持true。本文不涉及 v8 之后的升级Future Changes 目前只预告了 v9 的最低版本node24和一个尚无已知计划的 breaking changes 列表属于另一个升级周期。【免费下载链接】react-routerDeclarative routing for React项目地址: https://gitcode.com/GitHub_Trending/re/react-router创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表