如何在Next.js的getStaticProps中获取User Agent实现SSG页面设备检测
问题根因
getStaticProps 是 NextJS 的构建阶段执行方法,仅在项目打包时运行一次,生成的静态页面会被所有访问用户复用。此时 react-device-detect 读取的是构建服务器的 User Agent,而非访问用户的浏览器 UA,因此会一直返回固定的桌面端判断结果。
且 getStaticProps 的设计定位就是无请求上下文的静态生成,本身不会提供用户请求的 req 参数,因此不可能在纯 SSG 的 getStaticProps 中获取单个用户的 UA。
方案1:客户端侧判断(保留纯 SSG,最轻量)
如果不需要首屏渲染时就返回对应设备的内容,直接在客户端侧做判断即可,为避免 hydration 不匹配问题,建议在组件挂载后再赋值设备判断结果:
import { useState, useEffect } from 'react'; import { isMobile } from 'react-device-detect'; function AwesomePage() { const [deviceType, setDeviceType] = useState(''); // 仅在客户端挂载后执行判断,避免服务端预渲染与客户端内容不一致 useEffect(() => { setDeviceType(isMobile ? 'Yes, I am a mobile' : 'Nope, Desktop!'); }, []); return <h1>{deviceType}</h1> } export default AwesomePage;
方案2:改用 SSR 渲染(首屏直接返回正确设备内容)
如果需要首屏就返回适配设备的内容,可将渲染模式换成 SSR,使用 getServerSideProps 可以拿到请求上下文的 req 对象,手动传入 UA 给 react-device-detect 做判断:
import { getSelectorsByUserAgent } from 'react-device-detect'; export async function getServerSideProps(context) { // 从请求头获取用户真实UA const userAgent = context.req.headers['user-agent'] || ''; // 手动传入UA生成设备判断结果 const { isMobile } = getSelectorsByUserAgent(userAgent); const deviceType = isMobile ? 'Yes, I am a mobile' : 'Nope, Desktop!'; return { props: { mobileDevice: deviceType } } } function AwesomePage({ mobileDevice }) { return <h1>{mobileDevice}</h1> } export default AwesomePage;
方案3:Middleware + 多版本 SSG 预渲染(兼顾静态页速度与设备适配)
如果既想保留 SSG 的静态响应速度,又需要首屏返回对应设备的内容,可以配合 NextJS 的 Middleware 实现:
- 构建时预渲染移动端、桌面端两个版本的静态页
- 中间件拦截用户请求,根据 UA 自动分发对应版本的静态页
首先在项目根目录新增 middleware.js:
import { NextResponse } from 'next/server'; import { getSelectorsByUserAgent } from 'react-device-detect'; export function middleware(request) { const userAgent = request.headers.get('user-agent') || ''; const { isMobile } = getSelectorsByUserAgent(userAgent); const response = NextResponse.next(); // 也可以根据UA直接重写到对应路径,实现多版本静态页分发 response.headers.set('X-Device-Type', isMobile ? 'mobile' : 'desktop'); return response; } // 配置中间件生效的页面路径 export const config = { matcher: '/awesome-page', }
之后可以通过 generateStaticParams(NextJS 13+ App Router)或 getStaticPaths(Pages Router)预生成两个设备版本的静态页即可。
内容的提问来源于stack exchange,提问作者Deepak Kamat
相关产品推荐
相关产品推荐

