GitHub Docs路由系统:Next.js路由配置与优化
概述
GitHub Docs作为GitHub官方文档平台,采用了Next.js作为其核心框架,构建了一套高效、灵活的路由系统。本文将深入分析GitHub Docs的路由架构设计、配置策略以及性能优化实践,为开发者提供可借鉴的路由系统实现方案。
路由架构设计
1. 双路由系统架构
GitHub Docs采用App Router与Pages Router并存的双路由架构,通过智能路由网关实现动态路由分发:
2. 路由决策逻辑
// 路由决策核心逻辑
export function shouldUseAppRouter(path: string, pageFound: boolean = true): boolean {
const strippedPath = stripLocalePrefix(path)
// App Router专用路由
const APP_ROUTER_ROUTES = new Set([
'/_not-found',
'/404',
// 其他迁移路由
])
if (APP_ROUTER_ROUTES.has(strippedPath)) {
return true
}
// 特殊404处理
if (strippedPath.endsWith('/empty-categories')) {
return true
}
// 页面未找到时使用App Router处理404
if (!pageFound) {
return true
}
return false
}
路由配置详解
1. Next.js配置优化
// next.config.js 关键配置
export default {
transpilePackages: ['@primer/react'],
typescript: { ignoreBuildErrors: true },
eslint: { ignoreDuringBuilds: true },
i18n: {
locales: ['en', 'es', 'ja', 'pt', 'zh', 'ru', 'fr', 'ko', 'de'],
defaultLocale: 'en',
},
async rewrites() {
const DEFAULT_VERSION = 'free-pro-team@latest'
return productIds.map((productId) => {
return {
source: `/${productId}/:path*`,
destination: `/${DEFAULT_VERSION}/${productId}/:path*`,
}
})
},
experimental: {
largePageDataBytes: 1024 * 1024, // 1MB页面数据限制
scrollRestoration: true, // 滚动位置恢复
},
}
2. 路由模式识别
// 路由模式识别函数
export function isVersionedPath(path: string): boolean {
const strippedPath = stripLocalePrefix(path)
const versionPattern =
/(enterprise-server@[\d.]+|enterprise-server@latest|enterprise-cloud@latest|free-pro-team@latest)/
return versionPattern.test(strippedPath)
}
export function isJunkPath(path: string): boolean {
const junkPatterns = [
/^\/wp-/, /^\/[^/]*\.php$/, /^\/~\w+/, /\/\.env/,
/\/package(-lock)?\.json$/, /^\/_{2,}/, /^\/\\+/
]
return junkPatterns.some((pattern) => pattern.test(path))
}
性能优化策略
1. 缓存策略配置
| 缓存类型 | 配置 | 说明 |
|---|---|---|
| CDN缓存 | generateEtags: false | 禁用ETag避免CDN重验证 |
| 静态资源 | 默认缓存头 | 静态资源长期缓存 |
| 页面数据 | 自定义缓存控制 | 根据内容类型设置缓存 |
2. 路由预处理优化
// 路由网关中间件
export default function appRouterGateway(req: ExtendedRequest, res: Response, next: NextFunction) {
const path = req.path || req.url
// 只拦截GET和HEAD请求
if (req.method !== 'GET' && req.method !== 'HEAD') {
return next()
}
// 排除静态资源、API路由等
if (
path.startsWith('/_next/') ||
path.startsWith('/assets/') ||
path.startsWith('/api/') ||
isJunkPath(path) ||
(isVersionedPath(path) && !isInvalidVersionedPath(path))
) {
return next()
}
// 智能路由决策
const pageFound = !!(req.context && req.context.page)
if (shouldUseAppRouter(path, pageFound)) {
// App Router处理逻辑
res.locals.handledByAppRouter = true
return nextApp.getRequestHandler()(req, res)
}
return next()
}
多语言路由处理
1. 语言前缀处理
export function stripLocalePrefix(path: string): string {
const decodedPath = decodePathSafely(path)
const localeMatch = decodedPath.match(/^\/([a-z]{2})(\/.*)?$/)
if (localeMatch) {
return localeMatch[2] || '/'
}
return decodedPath
}
export function decodePathSafely(path: string): string {
try {
return decodeURIComponent(path)
} catch {
return path
}
}
2. 多语言路由映射表
| 路径模式 | 处理方式 | 示例 |
|---|---|---|
/en/path | 去除语言前缀 | /path |
/zh/path | 去除语言前缀 | /path |
| 无语言前缀 | 保持原样 | /path |
错误处理与404路由
1. 自定义404处理
// 404路由处理逻辑
if (strippedPath === '/404' || strippedPath === '/_not-found' || !pageFound) {
req.url = '/404'
res.status(404)
defaultCacheControl(res)
// 传递原始路径信息
res.setHeader('x-pathname', req.path)
res.locals.handledByAppRouter = true
return nextApp.getRequestHandler()(req, res)
}
2. 错误边界处理
// 错误处理中间件
async function buildRenderedPage(req: ExtendedRequest): Promise<string> {
const { context } = req
if (!context) throw new Error('request not contextualized')
const { page } = context
if (!page) throw new Error('page not set in context')
const pageRenderTimed = statsd.asyncTimer(page.render, 'middleware.render_page', [
`path:${req.path}`
])
return (await pageRenderTimed(context)) as string
}
路由监控与统计
1. 性能监控配置
// 路由性能统计
const STATSD_KEY_RENDER = 'middleware.render_page'
async function buildRenderedPage(req: ExtendedRequest): Promise<string> {
const pageRenderTimed = statsd.asyncTimer(
page.render,
STATSD_KEY_RENDER,
[`path:${req.path}`]
)
return (await pageRenderTimed(context)) as string
}
2. 路由决策日志
// 路由决策日志记录
if (shouldUseAppRouter(path, pageFound)) {
console.log(`[INFO] Using App Router for path: ${path} (pageFound: ${!!pageFound})`)
// App Router处理逻辑
} else {
console.log(`[INFO] Using Pages Router for path: ${path}`)
return next()
}
最佳实践总结
1. 路由设计原则
- 渐进式迁移: 支持App Router和Pages Router并存,逐步迁移
- 智能路由: 基于路径模式和内容类型自动选择路由处理器
- 性能优先: 通过缓存策略和预处理优化路由性能
2. 配置优化建议
// 推荐配置
module.exports = {
compress: false, // 禁用压缩,由CDN处理
generateEtags: false, // 禁用ETag避免CDN问题
experimental: {
largePageDataBytes: 1024 * 1024, // 调整大页面数据阈值
scrollRestoration: true // 启用滚动恢复
}
}
3. 监控与维护
- 实施路由性能监控
- 定期审查路由决策逻辑
- 监控404路由处理效果
- 优化多语言路由性能
GitHub Docs的路由系统通过精心设计的架构和优化策略,实现了高性能、高可用的文档服务。其双路由架构、智能路由决策和全面的性能优化为大型文档站点提供了优秀的参考实现。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



