尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Remix 3 怎么渲染路由级 404 页面

Remix 3 怎么渲染路由级 404 页面 Remix 3 怎么渲染路由级 404 页面【免费下载链接】remixThe fully-stacked web framework项目地址: https://gitcode.com/GitHub_Trending/re/remix在 Remix 3 应用里返回 404 有两个不同的触发点路由已经匹配、但 action 发现记录不存在这是典型的“路由级 404”由 action 自己返回404响应以及 URL 没有匹配到任何路由由路由器的defaultHandler兜底。这篇文章覆盖两条路径前者在 action 里渲染一个完整的 404 页面后者自定义未匹配 URL 的 404 响应并给出用router.fetch(...)验证结果的方式。内容基于 Remix 3 指南文档和remix-run/fetch-router的源码与测试。先分清两种 404Errors 章节 给出的原则是记录缺失属于路由契约的一部分action 应该直接返回预期的状态码和响应体而不是抛错再在别处翻译Return a route-specific404page when the action understands what is missing. Let an unmatched URL use the routers not-found response, and keep internal record identifiers or exception details out of public error bodies.所以写法上分两层action 负责“我理解这个 URL但资源不在”路由器负责“这个 URL 我不认识”。两层的代码位置不同下面分别处理。路由级 404在 action 里返回 404 响应以 Routing 章节 的示例结构为例路由在app/routes.ts里声明import { get, route } from remix/routes; export const routes route({ albums: { show: get(/albums/:albumId), }, });action 匹配成功后从context.params拿到albumId查不到记录时直接返回404。Rendering UI 章节 里的完整示例import { createController } from remix/router; import { routes } from ../../routes.ts; import { getAlbum } from ./data.ts; import { AlbumPage } from ./show-page.tsx; export default createController(routes.albums, { actions: { async show(context) { let album await getAlbum(context.params.albumId); if (album undefined) { return new Response(Album not found, { status: 404 }); } return context.render(AlbumPage album{album} /); }, }, });new Response(..., { status: 404 })是最简形式适合纯文本或 JSON 场景Response.json(...)同样接受ResponseInit。如果要在 Remix UI 渲染管线里输出一个完整的 HTML 404 页面前提是路由上装了render()中间件remix/middleware/render指南生成的应用已经安装context.render(...)接受ResponseInit来附加状态码和响应头// 当记录不存在时渲染 404 页面而不是抛错 return context.render(NotFoundPage /, { status: 404, headers: { Cache-Control: no-store }, });如果这段 HTML 不走 Remix 的组件渲染管线比如只需要一个最简单的文档壳remix/html-template的html模板标签加createHtmlResponse(...)可以设置 HTML 内容类型并附加状态码。html标签会转义插值防止 XSShtml.raw不转义只用于已确认安全的内容import { html } from remix/html-template; import { createHtmlResponse } from remix/response/html; // 在 action 或 handler 中 return createHtmlResponse(htmlh1Album not found/h1, { status: 404 });注意 Errors 章节 的另一条要求不要把内部记录 ID 或异常细节放进公开的 404 响应体页面文案保持面向用户。未匹配 URL 的 404自定义 defaultHandlerURL 没有匹配到任何路由时createRouter的defaultHandler选项负责处理。它的默认行为见 router 实现返回Not Found: 路径的文本响应状态码404。RouterOptions.defaultHandler的注释明确其语义router.tsThe default request handler that runs when no route matches. Defaults to a 404Not Foundresponse.Remix 3 应用里createRouter从remix/router导入它是对remix-run/fetch-router的再导出见 manifest.json。要自定义兜底 404 页面在创建路由器的地方传入defaultHandler。指南示例中的app/router.ts原本是export const router createRouter();改成import { createRouter } from remix/router; import { html } from remix/html-template; import { createHtmlResponse } from remix/response/html; export const router createRouter({ defaultHandler({ url }) { return createHtmlResponse(htmlh1404 Not Found: ${url.pathname}/h1, { status: 404, }); }, });defaultHandler收到的参数是请求上下文示例里用到了其中的url。上面这段写法与仓库测试 router.test.ts 中的supports a custom defaultHandler用例一致——该用例断言未匹配 URL 返回状态404、自定义正文和自定义响应头。验证 404 页面是否生效fetch-router使用标准fetch()API测试不需要 mock直接router.fetch(...)然后断言状态码和正文README Testing 一节 展示了同一模式。两类 404 的验证各写一条import * as assert from node:assert/strict; import { describe, it } from node:test; describe(404 pages, () { it(returns a route-level 404 when the album is missing, async () { let response await router.fetch(https://example.com/albums/missing); assert.equal(response.status, 404); }); it(uses the custom defaultHandler for unmatched URLs, async () { let response await router.fetch(https://example.com/does-not-exist); assert.equal(response.status, 404); assert.match(await response.text(), /404 Not Found/); }); });两条判断标准都来自仓库现有测试路由级 404请求一个 pattern 能匹配但记录不存在的 URLresponse.status应为404正文是你 action 返回的内容兜底 404defaultHandler只在没有任何路由匹配时被调用router.test.ts 的calls defaultHandler only when no routes match用例验证了命中路由时它不会被触发。边界405 不是 404一个容易混淆的场景URL 匹配到了某个路由 pattern但请求方法没有注册。此时路由器不返回 404而是返回405 Method Not Allowed并附带列出该 URL 已注册方法的Allow响应头fetch-router README。匹配会先降级到能处理该方法的更宽松路由包括ANY路由全都处理不了才落到 405。如果你的意图是让某个 URL 接收所有方法注册一个ANY路由而不是依赖 404/405 的兜底行为。另外路由 pattern 本身不参与 404 页面的渲染——pattern 只决定请求是否进入你的 action“记录不存在”这个判断由 action 自己完成并返回 404。404 页面的文档壳、head等内容与正常页面一致通过共享的 Document 组件输出见 Rendering UI 章节 的 “Document shells, head content, and HTML responses” 一节。【免费下载链接】remixThe fully-stacked web framework项目地址: https://gitcode.com/GitHub_Trending/re/remix创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表