How to Detect Mobile Devices Server-Side in Next.js for Optimized Rendering
When building responsive web applications, you often need to make layout adjustments based on whether the user is on a mobile or desktop device. While CSS media queries handle most styling needs, sometimes you need server-side device detection to:
- Load different quantities of data
- Optimize first-fold loading, achieving better LCP (Largest Contentful Paint) scores as part of Core Web Vitals
- Implement device-specific features or interfaces
- Improve performance by sending only what's needed, boosting page speed
- Initial load for Server-Side Device Detection
Here's the code that I am using for my server components:
import { headers } from "next/headers";
import UAParser from "ua-parser-js";
type IDevice = "mobile" | "desktop";
export default async function getDevice( // prefix with `get` since you can onle use in server component
device: IDevice = "mobile" /*default mobile*/
): Promise<boolean> {
const headersList = await headers(); // await mandatory for nextjs 15
const userAgent = headersList.get("user-agent") || ""; //Get request headers
const deviceType = new UAParser(userAgent).getDevice().type || "desktop"; // Parse to string
return deviceType === device; // return true or false
}
Example of use
/page.tsx
export default async function SomeNextPage() {
const isMobile = await getDevice(); // Don't forget the "async await" or will launch error
const quantity = isMobile ? 4 : 12; // Will load different quantities according to device
const response = await fetch("https://jsonplaceholder.typicode.com/posts?_limit=" + limitItems);
const posts = await response.json();
return (
<div>
{posts.map((post) => (
<article key={post.id} className="post">
<h2>{post.title}</h2>
<p>{post.body}</p>
{isMobile ? (
<div className="mobile-only">
<button>Read More</button>
<small>Tap for full content</small>
</div>
) : (
<div className="desktop-only">
<button>View Details</button>
<button>Save for Later</button>
<button>Share</button>
</div>
)}
</article>
))}
</div>
);
}
Last updated on