Built-in Components That Save You Time
Next.js ships three components you'll use constantly: Link, Image, and Script. They're not just wrappers, they provide real performance optimizations under the hood.
Link: Client-Side Navigation
src/components/Navbar.tsx
tsx
1import Link from "next/link";23export default function Navbar() {4return (5 <nav>6 {/* Basic link */}7 <Link href="/about">About</Link>89 {/* Link with dynamic route */}10 <Link href={`/blog/${postSlug}`}>Read Post</Link>1112 {/* Disable prefetching for rarely visited pages */}13 <Link href="/admin" prefetch={false}>Admin</Link>1415 {/* Replace history instead of push */}16 <Link href="/login" replace>Login</Link>17 </nav>18);19}š”
Why Link over <a>?
Link does client-side navigation (instant, no full page reload).
⢠Prefetches linked pages in the viewport
⢠Preserves client state across navigations
⢠Using causes a full server round-trip, which is slow and destroys state
⢠Prefetches linked pages in the viewport
⢠Preserves client state across navigations
⢠Using causes a full server round-trip, which is slow and destroys state
Image: Optimized Images
The Image component automatically optimizes your images: WebP conversion, lazy loading, responsive sizes, blur placeholder.
src/components/Hero.tsx
tsx
1import Image from "next/image";23// Local image (automatic width/height detection)4import heroImage from "@/public/hero.jpg";56export default function Hero() {7return (8 <div>9 {/* Local image (dimensions auto-detected) */}10 <Image11 src={heroImage}12 alt="Hero banner"13 placeholder="blur"14 priority15 />1617 {/* Remote image (must specify dimensions) */}18 <Image19 src="https://example.com/photo.jpg"20 alt="Profile photo"21 width={400}22 height={400}23 className="rounded-full"24 />2526 {/* Fill container (like background-size: cover) */}27 <div className="relative h-96 w-full">28 <Image29 src="/banner.jpg"30 alt="Banner"31 fill32 className="object-cover"33 />34 </div>35 </div>36);37}ā ļø
Remote images need config
If you're loading images from external URLs, you need to whitelist the domains in next.config.ts under images.remotePatterns. Otherwise Next.js blocks them for security.
next.config.ts
typescript
1// next.config.ts2import type { NextConfig } from "next";34const nextConfig: NextConfig = {5images: {6 remotePatterns: [7 {8 protocol: "https",9 hostname: "example.com",10 pathname: "/images/**",11 },12 ],13},14};1516export default nextConfig;Script: Third-Party Scripts
Loading analytics, chat widgets, or other third-party scripts? Use the Script component to control loading strategy:
src/app/layout.tsx
tsx
1import Script from "next/script";23export default function Layout({ children }) {4return (5 <>6 {/* Load after page is interactive */}7 <Script8 src="https://analytics.example.com/script.js"9 strategy="afterInteractive"10 />1112 {/* Load when browser is idle */}13 <Script14 src="https://chat-widget.example.com/widget.js"15 strategy="lazyOnload"16 />1718 {/* Inline script */}19 <Script id="schema-org" type="application/ld+json">20 {`{ "@context": "https://schema.org", "@type": "WebSite" }`}21 </Script>2223 {children}24 </>25);26}