尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
<!-- src/blog/hello-world.md -->
【免费下载链接】router A client-first, server-capable, fully type-safe router and full-stack framework for the web (React and more).项目地址: https://gitcode.com/GitHub_Trending/ro/routertitle: Hello World published: 2024-01-15 authors:Jane Doe description: My first blog postHero ImageWelcome to my blog! This is my first post.Getting StartedHeres some content withboldanditalictext.console.log(Hello, world!)published 使用 z.string().date() 校验确保必须是合法日期字符串authors 使用数组类型对应 frontmatter 中的列表语法。 ### 3.5 在路由中消费集合 构建时生成 content-collections 模块直接导入即可获得类型完整的文章数组。列表页按发布日期倒序排列并渲染为链接列表 tsx // src/routes/blog.index.tsx import { createFileRoute } from tanstack/react-router import { allPosts } from content-collections export const Route createFileRoute(/blog/)({ component: BlogIndex, }) function BlogIndex() { // Posts are sorted by published date const sortedPosts allPosts.sort( (a, b) new Date(b.published).getTime() - new Date(a.published).getTime(), ) return ( div h1Blog/h1 ul {sortedPosts.map((post) ( li key{post.slug} Link to/blog/$slug params{{ slug: post.slug }} h2{post.title}/h2 p{post.excerpt}/p span{post.published}/span /Link /li ))} /ul /div ) } ### 3.6 渲染单篇文章详情 详情页通过 $slug 动态段匹配在 loader 中查找对应文章未命中时抛出 notFound()交由 TanStack Router 内置的 404 机制处理——notFound/isNotFound 由 tanstack/router-core 导出并在 packages/router-core/src/not-found.ts 中实现路由层会拦截这类错误并渲染 Not Found 匹配项参见 [router-core 导出](https://link.gitcode.com/i/fc474d5546ecc79127116799d6be78ed) tsx // src/routes/blog.$slug.tsx import { createFileRoute, notFound } from tanstack/react-router import { allPosts } from content-collections import { Markdown } from ~/components/Markdown export const Route createFileRoute(/blog/$slug)({ loader: ({ params }) { const post allPosts.find((p) p.slug params.slug) if (!post) { throw notFound() } return post }, component: BlogPost, }) function BlogPost() { const post Route.useLoaderData() return ( article header h1{post.title}/h1 p By {post.authors.join(, )} on {post.published} /p /header Markdown content{post.content} classNameprose / /article ) } 注意 Markdown 使用了 Tailwind 风格的 prose 类名若未使用 Tailwind Typography 插件可自行编写文章排版样式。 --- ## 四、方式二从远程源动态获取 Markdown 当内容存放在仓库外部如 GitHub 仓库、需要实时更新时可借助 TanStack Start 的 **Server Function** 动态抓取并渲染。createServerFn 是 TanStack Start 的核心原语由 tanstack/react-start 直接导出见 [react-start 公共 API](https://link.gitcode.com/i/eb6a8bb15667880fbc3268c54a68bc39)其底层实现来自 tanstack/start-client-core它保证逻辑只在服务端执行同时维持跨网络边界的类型安全。 ### 4.1 创建服务端抓取工具 tsx // src/utils/docs.server.ts import { createServerFn } from tanstack/react-start import matter from gray-matter type FetchDocsParams { repo: string // e.g., tanstack/router branch: string // e.g., main filePath: string // e.g., docs/guide/getting-started.md } export const fetchDocs createServerFn({ method: GET }) .validator((params: FetchDocsParams) params) .handler(async ({ data: { repo, branch, filePath } }) { const url https://raw.githubusercontent.com/${repo}/${branch}/${filePath} const response await fetch(url, { headers: { // Add GitHub token for private repos or higher rate limits // Authorization: token ${process.env.GITHUB_TOKEN}, }, }) if (!response.ok) { throw new Error(Failed to fetch: ${response.status}) } const rawContent await response.text() const { data: frontmatter, content } matter(rawContent) return { frontmatter, content, filePath, } }) 要点说明 - createServerFn({ method: GET }) 声明 HTTP 方法GET 为默认值适合可缓存的读取操作 - .validator() 在请求进入 handler 前校验参数保证类型安全 - 拉取后立即用 gray-matter 剥离 frontmatter返回结构化的 { frontmatter, content, filePath } - 私有仓库或需要更高速率限制时可在 headers 中注入 Authorization: token ${process.env.GITHUB_TOKEN}。 ### 4.2 为生产环境添加缓存头 在 handler 中通过 context.response 设置缓存头让 CDN 层缓存文档内容 tsx export const fetchDocs createServerFn({ method: GET }) .validator((params: FetchDocsParams) params) .handler(async ({ data: { repo, branch, filePath }, context }) { // Set cache headers for CDN caching context.response.headers.set( Cache-Control, public, max-age0, must-revalidate, ) context.response.headers.set( CDN-Cache-Control, max-age300, stale-while-revalidate300, ) // ... fetch logic }) 这里采用了浏览器缓存与 CDN 缓存分层的经典策略Cache-Control 对浏览器要求每次重新验证must-revalidate而 CDN-Cache-Control 允许 CDN 缓存 300 秒并支持 stale-while-revalidate300 的过期后后台刷新兼顾内容新鲜度与边缘性能。 ### 4.3 在路由中使用动态文档 tsx // src/routes/docs.$path.tsx import { createFileRoute } from tanstack/react-router import { fetchDocs } from ~/utils/docs.server import { Markdown } from ~/components/Markdown export const Route createFileRoute(/docs/$path)({ loader: async ({ params }) { return fetchDocs({ data: { repo: your-org/your-repo, branch: main, filePath: docs/${params.path}.md, }, }) }, component: DocsPage, }) function DocsPage() { const { frontmatter, content } Route.useLoaderData() return ( article h1{frontmatter.title}/h1 Markdown content{content} classNameprose / /article ) } $path 参数直接映射为 GitHub 仓库内的文件路径天然支持多级文档目录如 /docs/api/router → docs/api/router.md。 ### 4.4 拉取目录结构构建导航 若要基于 GitHub 目录动态生成侧边导航可调用 GitHub Contents API 并过滤 Markdown 文件 tsx // src/utils/docs.server.ts type GitHubContent { name: string path: string type: file | dir } export const fetchRepoContents createServerFn({ method: GET }) .validator((params: { repo: string; branch: string; path: string }) params) .handler(async ({ data: { repo, branch, path } }) { const url https://api.github.com/repos/${repo}/contents/${path}?ref${branch} const response await fetch(url, { headers: { Accept: application/vnd.github.v3json, // Authorization: token ${process.env.GITHUB_TOKEN}, }, }) if (!response.ok) { throw new Error(Failed to fetch contents: ${response.status}) } const contents: ArrayGitHubContent await response.json() return contents .filter((item) item.type file item.name.endsWith(.md)) .map((item) ({ name: item.name.replace(.md, ), path: item.path, })) }) 该函数返回按字母序过滤后的 { name, path } 列表可直接喂给导航组件渲染Accept: application/vnd.github.v3json 头可确保收到结构化 JSON。 --- ## 五、使用 Shiki 添加语法高亮 在客户端组件内直接跑完整高亮管线开销较大更推荐的做法是先用 Shiki 在服务端或构建期把代码块转成带主题样式的 HTML再交给 Markdown 组件渲染。 定义独立的高亮工具函数 tsx // src/utils/markdown.ts import { codeToHtml } from shiki // Process code blocks after parsing export async function highlightCode( code: string, language: string, ): Promisestring { return codeToHtml(code, { lang: language, themes: { light: github-light, dark: tokyo-night, }, }) } themes 同时声明亮色与暗色主题Shiki 会生成双主题 CSS 变量配合 prefers-color-scheme 自动切换。 随后在 Markdown 组件的 replace 函数中拦截 pre 元素提取语言与源码并替换为自定义 CodeBlock tsx // In your Markdown components replace function if (domNode.name pre) { const codeElement domNode.children.find( (child) child instanceof Element child.name code, ) if (codeElement) { const className codeElement.attribs.class || const language className.replace(language-, ) || text const code getText(codeElement) return CodeBlock code{code} language{language} / } }【免费下载链接】router A client-first, server-capable, fully type-safe router and full-stack framework for the web (React and more).项目地址: https://gitcode.com/GitHub_Trending/ro/router创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED

相关推荐

MATLAB车型识别实战:从监控图像到ResNet-18部署

MATLAB车型识别实战:从监控图像到ResNet-18部署

简介:本资源是一套基于MATLAB实现的车型识别系统完整工程,面向图像处理初学者与自动化识别方向实践者,解决交通监控场景下车型分类(小轿车/面包车/公交车)的轻量级算法落地问题。系统采用差影法提取运动车辆轮廓&#…

📅 2026/9/16 16:23:52
Python自动化抢票脚本技术拆解:从HTTP请求到Playwright实战

Python自动化抢票脚本技术拆解:从HTTP请求到Playwright实战

简介:这份代码是一套基于Python的大麦网演唱会抢票自动化程序,面向有一定Python基础的开发者、自动化测试工程师及运维人员,用于解决手动抢票操作繁琐、时机难把握的问题。压缩包共2个文件,包含1个py脚本和1个txt说明文档&#xf…

📅 2026/9/16 16:23:52
深入理解Linux进程程序替换:exec原理与实战指南

深入理解Linux进程程序替换:exec原理与实战指南

进程程序替换这个话题,看着是操作系统教材里一个偏理论的小节,但一旦你在真实代码里跑过一次,就会意识到它几乎是整个 Linux“命令行世界”的地基。我最早接触它时也犯过一个经典错误:在 fork 之后的父子进程分支没写清楚&#xf…

📅 2026/9/16 16:23:52
MORE NEWS

更多资讯

📰

3步搞定3D打印振纹:Klipper 输入整形的完整调参指南

3步搞定3D打印振纹:Klipper 输入整形的完整调参指南 【免费下载链接】klipper Klipper is a 3d-printer firmware 项目地址: https://gitcode.com/GitHub_Trending/kl/klipper Klipper 是一款 3D 打印机固件,输入整形(Input Shaping&a…

📰

CPU、GPU、NPU、TPU深度解析:AI芯片选型底层逻辑

这几年总有人问我:“你到底是做AI的还是做芯片的?为什么又是CPU又是GPU,还冒出来NPU、TPU,名字都长得差不多,到底有啥区别?”说实话,这问题放在五年前还算冷门,放在今天已经是每个搞…

📰

nhost 仓库中的 safeexec 模块:规避 Windows 下 exec.LookPath 当前目录查找漏洞的实现解析

nhost 仓库中的 safeexec 模块:规避 Windows 下 exec.LookPath 当前目录查找漏洞的实现解析 【免费下载链接】nhost The Open Source Firebase Alternative with GraphQL. 项目地址: https://gitcode.com/GitHub_Trending/nh/nhost 本篇技术指南围绕 nhost 仓…

📰

ESP-IDF SPI Flash 可选特性指南:Auto Suspend、HPM、DPD、32-bit 地址与 OPI Flash 支持解析

ESP-IDF SPI Flash 可选特性指南:Auto Suspend、HPM、DPD、32-bit 地址与 OPI Flash 支持解析 【免费下载链接】esp-idf Espressif IoT Development Framework. Official development framework for Espressif SoCs. 项目地址: https://gitcode.com/GitHub_Trendi…

📰

Python爬虫气象数据实时发布系统:从采集到可视化全流程

简介:基于Python网络爬虫的陕西省气象数据实时发布系统毕业设计资料包,面向计算机及相关专业完成毕设、课程设计的学生,提供完整项目源码与配套毕业论文。资源聚焦气象数据采集、处理与实时发布流程,涵盖爬虫脚本、后端逻辑、前端…

📰

gog YouTube 实战指南:在终端中用 gog 完成 YouTube 数据查询、订阅与播放列表管理

gog YouTube 实战指南:在终端中用 gog 完成 YouTube 数据查询、订阅与播放列表管理 【免费下载链接】gogcli Google Workspace in your terminal. 项目地址: https://gitcode.com/GitHub_Trending/gogcl/gogcli 本文基于 gog 项目中面向 Agent 的 gog-youtub…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬