基于 User-Agent 的分设备渲染:Next.js Edge Middleware 示例深度解析

基于 User-Agent 的分设备渲染:Next.js Edge Middleware 示例深度解析 基于 User-Agent 的分设备渲染Next.js Edge Middleware 示例深度解析【免费下载链接】examplesEnjoy our curated collection of examples and solutions. Use these patterns to build your own robust and scalable applications.项目地址: https://gitcode.com/GitHub_Trending/examples1/examples本指南围绕仓库中的 edge-middleware/user-agent-based-rendering 示例讲解如何利用 Next.js Edge Middleware 读取 HTTPUser-Agent请求头在边缘节点判断访客设备类型并将请求重写到对应的桌面版或移动版页面。读完本文你将掌握userAgent()解析、NextResponse.rewrite重写分流、_viewport视图组织等一整套可直接复用的设备感知渲染方案并能结合仓库源码理解其完整调用链。为什么需要基于 User-Agent 渲染桌面版与移动版应用常常在 UI 布局、交互方式上有显著差异有时还会加载完全不同的脚本、样式表与第三方资源。如果让所有设备加载同一份页面再靠客户端 CSS 媒体查询隐藏元素移动端用户依然会白白下载大量不必要的资源影响加载速度与体验。该示例的思路是在请求到达页面渲染之前于边缘中间件中读取User-Agent头判断当前是手机还是桌面设备然后直接把请求重写到对应的视图页面。这样服务端按设备返回不同的 HTML未使用的脚本与样式根本不会被下发实现了按需渲染。示例整体结构与请求流程从仓库目录结构看示例由以下几个关键部分构成edge-middleware/user-agent-based-rendering/ ├── middleware.ts # 边缘中间件负责解析 UA 并重写请求 ├── pages/ │ ├── _app.tsx # 应用外壳套用 vercel/examples-ui 布局 │ └── _viewport/ # 按设备区分的视图目录 │ ├── desktop.tsx # 桌面视图 │ └── mobile.tsx # 移动视图 ├── components/ │ └── Home.tsx # 两个视图共用的页面组件 ├── public/ │ └── board.jpg # 请求分流流程示意图 └── package.json / vercel.json # 依赖与构建配置一次完整请求的处理链路如下客户端发起对/的请求携带User-Agent头middleware.ts 在边缘层拦截请求matcher: /中间件调用userAgent(req)解析设备类型得到mobile或desktop通过NextResponse.rewrite将请求内部重写到/_viewport/{mobile|desktop}对应视图页面pages/_viewport/mobile.tsx 或 pages/_viewport/desktop.tsx被渲染返回。注意rewrite是内部重写浏览器地址栏仍显示/只有服务端路由被替换用户感知不到跳转。核心实现middleware.ts 源码级解析示例的核心逻辑全部集中在 middleware.ts共 20 行逐段拆解如下import { NextRequest, NextResponse, userAgent } from next/server // Set pathname were middleware will be executed export const config { matcher: /, } export default function middleware(req: NextRequest) { // Parse user agent const { device } userAgent(req) // Check the viewport const viewport device.type mobile ? mobile : desktop // Update the expected url req.nextUrl.pathname _viewport/${viewport} // Return rewrited response return NextResponse.rewrite(req.nextUrl) }1.config.matcher限定执行范围export const config { matcher: /, }matcher决定中间件在哪些路径上执行。这里仅匹配根路径/即只有访问首页时才触发设备分流。实际项目中可扩展为数组例如matcher: [/, /docs/:path*]或使用正则精确控制避免中间件在不必要的路由上白白执行。2.userAgent(req)解析请求头const { device } userAgent(req)userAgent()是next/server提供的内置工具函数它从req中解析User-Agent头并返回结构化对象其中device.type携带设备类型判断结果如mobile、tablet等。相比手写正则匹配 UA 字符串这一 API 将解析细节封装起来代码更简洁、更不易出错。3. 设备判定与 URL 重写const viewport device.type mobile ? mobile : desktop req.nextUrl.pathname _viewport/${viewport} return NextResponse.rewrite(req.nextUrl)逻辑非常直观device.type为mobile时选中移动视图否则回退到桌面视图随后修改req.nextUrl.pathname为目标视图路径最后用NextResponse.rewrite(req.nextUrl)返回重写后的响应。中间件全程在边缘Edge Runtime执行不占用 Node.js 服务器资源也不阻塞应用主体逻辑。下图直观展示了中间件依据 User-Agent 将请求分发给桌面与移动视图的完整流程视图组织_viewport 目录与共用组件为支持多设备渲染示例将每个设备对应的页面放在pages/_viewport目录下。从源码看两个页面文件都非常薄仅作转发// pages/_viewport/desktop.tsx export { default } from ../../components/Home // pages/_viewport/mobile.tsx export { default } from ../../components/Home即桌面与移动视图共享同一个 components/Home.tsx 组件通过路由信息区分当前视口const { route } useRouter() const viewport route.replace(/_viewport/, )useRouter().route返回当前实际路由路径重写后的路径去掉/_viewport/前缀即得到mobile或desktop。页面底部据此渲染一行设备提示This page was loaded on a b{viewport}/b device.这为如何验证分流是否生效提供了直观手段在不同设备或浏览器开发者工具切换设备模拟上访问页面即可看到提示文案随之变化。实际项目中mobile与desktop两个视图完全可以替换为两套差异更大的页面实现各自加载专属脚本与样式这正是该模式的价值所在。应用外壳 pages/_app.tsx 通过vercel/examples-ui的getLayout统一套用页面布局与全局样式并声明了本示例的标题与描述属于示例的展示层封装不影响分流核心逻辑。本地运行与部署方式一以本示例为模板创建项目可借助create-next-app以该示例目录为模板直接引导项目pnpm create next-app --example edge-middleware/user-agent-based-rendering方式二克隆仓库后本地运行获取仓库源码后进入示例目录安装依赖并启动开发服务器git clone https://gitcode.com/GitHub_Trending/examples1/examples cd examples/edge-middleware/user-agent-based-rendering pnpm install pnpm devpnpm dev启动开发模式后浏览器访问http://localhost:3000切换设备模拟即可观察桌面/移动视图的变化。项目其余脚本见 package.jsonscripts: { dev: next dev, build: next build, start: next start, lint: next lint }其中pnpm build执行生产构建pnpm start启动生产服务器。依赖方面示例基于 Next.jsnext: ^16.0.10与 React 19react: ^19.2.1UI 层使用vercel/examples-ui样式方案为 Tailwind CSS见 tailwind.config.js 与 postcss.config.js。部署到 Vercel示例根目录的 vercel.json 已预置构建配置{ buildCommand: pnpm turbo build, ignoreCommand: pnpm dlx turbo-ignore }在 Vercel 控制台导入该仓库或通过一键部署入口后平台会依据上述配置执行 Turbo 构建并将 Edge Middleware 自动部署到边缘网络使设备分流在离用户最近的节点完成。该策略对 Next.js 部署同样适用——只要中间件文件放在项目根目录Pages Router 约定或src/middleware.ts构建产物即可直接上线。扩展思路与注意事项扩展更多设备类型device.type不止mobile与desktop两种取值从 Next.js 的 UA 解析结果看还包含tablet等类型。可将判定逻辑改为switch或映射表为平板单独提供视图只需在pages/_viewport下新增对应页面即可。matcher 范围控制分流逻辑只应作用于确有差异化需求的路径过宽的matcher会带来不必要的边缘计算开销。UA 判定的局限性基于User-Agent的判断无法覆盖小屏桌面浏览器或伪装 UA等场景且同一用户更换设备后视图不会自动切换。若需更精细的响应式能力可结合 CSS 媒体查询、视口尺寸检测或设备特性探测相关示例可参考仓库中 edge-middleware/ab-testing-simple 对分流中间件的同类实践作为补充。缓存与性能Edge Middleware 在边缘执行、响应可被 CDN 缓存但需注意为不同设备产物配置合适的Vary: User-Agent等缓存策略避免设备 A 的 HTML 被错误复用于设备 B。总而言之该示例用 20 行中间件代码完成了按设备渲染不同页面的完整闭环边缘解析 UA → 路由重写 → 视图分发 → 设备感知 UI。它既是理解 Next.js Edge Middleware 工作原理的最小可运行样例也是一个可平滑扩展为多设备、多版本页面体系的生产级参考模式。【免费下载链接】examplesEnjoy our curated collection of examples and solutions. Use these patterns to build your own robust and scalable applications.项目地址: https://gitcode.com/GitHub_Trending/examples1/examples创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考