npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

next-perfect-score-config

v1.1.0

Published

Next.js 16 configuration for 100/100 Lighthouse scores. Used in production at knaru.com.

Downloads

170

Readme

Next.js Perfect Score Configuration

Lighthouse Perfect Score

Production-tested Next.js configuration that achieves 100/100 Lighthouse scores across Performance, Accessibility, Best Practices, and SEO. These settings are actively used on knaru.com.


Table of Contents


Tech Stack

| Technology | Version | Purpose | |------------|---------|---------| | Next.js | 16.x | App Router, Server Components | | React | 19.x | React Compiler support | | Vercel | - | Edge Network, Serverless | | Bun | 1.x | Fast package management |


Configuration Breakdown

1. Inline CSS

experimental: {
  inlineCss: true,
}

What it does: Injects critical CSS directly into the HTML document instead of loading external CSS files.

Why it matters: External CSS files are render-blocking. The browser must download, parse, and apply CSS before painting anything. By inlining critical styles, we eliminate this network round-trip entirely.

Impact: First Contentful Paint (FCP) improved by ~150ms on mobile networks.


2. Aggressive Caching

async headers() {
  return [
    {
      source: '/_next/static/:path*',
      headers: [
        { key: 'Cache-Control', value: 'public, max-age=31536000, immutable' },
      ],
    },
    {
      source: '/images/:path*',
      headers: [
        { key: 'Cache-Control', value: 'public, max-age=31536000, immutable' },
      ],
    },
  ]
}

What it does: Tells browsers to cache static assets (JS, CSS, images) for 1 year (31536000 seconds). The immutable directive indicates these files will never change.

Why it matters: Next.js generates hashed filenames for static assets (e.g., page-a1b2c3.js). When content changes, the filename changes. This means we can safely cache forever—if a user already has the file, they never need to download it again.

Impact: Repeat visitors experience near-instant page loads. Network requests for static assets drop to zero.


3. Package Optimization

experimental: {
  optimizePackageImports: [
    'lucide-react',
    'date-fns',
    'react-hook-form',
    '@radix-ui/react-dialog',
    '@radix-ui/react-dropdown-menu',
  ],
}

What it does: Forces Next.js to analyze these packages and only include the code paths actually used.

Why it matters: Libraries like lucide-react contain 4000+ icons. Without optimization, importing one icon could pull in metadata for all icons. This setting ensures truly dead code is eliminated.

Impact: Initial JavaScript bundle reduced by 30-50KB depending on usage.


4. React Compiler

reactCompiler: true,

What it does: Enables the new React 19 Compiler (formerly React Forget). It automatically adds useMemo, useCallback, and React.memo where beneficial.

Why it matters: Manual memoization is error-prone and often applied incorrectly. The compiler analyzes your code and applies optimizations that humans consistently miss.

Impact: Fewer unnecessary re-renders. Lower Total Blocking Time (TBT).


5. Modular Imports

modularizeImports: {
  'lucide-react': {
    transform: 'lucide-react/dist/esm/icons/{{kebabCase member}}',
    skipDefaultConversion: false,
  },
  'date-fns': {
    transform: 'date-fns/{{member}}',
  },
},

What it does: Rewrites import statements to pull from specific file paths instead of the package root.

Why it matters: When you write import { format } from 'date-fns', bundlers must parse the entire date-fns entry point to find format. This setting rewrites it to import format from 'date-fns/format', skipping the entry point entirely.

Impact: Faster builds. Smaller bundles. Better tree-shaking.


Code Patterns

Configuration alone is not enough. These code patterns complement the settings above.

Font Loading

import { Inter } from 'next/font/google';

const inter = Inter({
  subsets: ['latin'],
  display: 'swap',
});

export default function RootLayout({ children }) {
  return <body className={inter.className}>{children}</body>;
}

Why: The display: 'swap' property shows fallback text immediately while the web font loads. This prevents invisible text (FOIT) and reduces Cumulative Layout Shift (CLS). The next/font system also self-hosts fonts, eliminating external requests to Google Fonts.


Image Optimization

<Image 
  src="/hero.jpg" 
  alt="Hero"
  width={1200}
  height={600}
  priority
  sizes="(max-width: 768px) 100vw, 50vw"
/>

Why: The priority attribute tells Next.js to preload this image, critical for Largest Contentful Paint (LCP). Explicit width and height reserve space in the layout, preventing CLS. The sizes attribute helps the browser choose the smallest appropriate image variant.


Third-Party Scripts

import Script from 'next/script';

<Script 
  src="https://www.googletagmanager.com/gtag/js?id=GA_ID" 
  strategy="lazyOnload" 
/>

Why: Third-party scripts (analytics, ads, chat widgets) are notorious for blocking the main thread. The lazyOnload strategy defers loading until after the page is fully interactive. This protects your Interaction to Next Paint (INP) score.


ISR (Incremental Static Regeneration)

// app/posts/[id]/page.tsx
export const revalidate = 60;

export default async function Post({ params }) {
  const data = await getPost(params.id);
  return <PostContent data={data} />;
}

Why: Pure SSR requires a database query on every request, adding latency. Pure SSG serves stale content. ISR gives you both: instant static responses with background revalidation every 60 seconds. Users always get fast responses, and content stays fresh.


Why These Work

The common thread across all optimizations:

  1. Eliminate network requests - Inline CSS, aggressive caching, self-hosted fonts
  2. Reduce JavaScript - Tree-shaking, modular imports, package optimization
  3. Don't block the main thread - Lazy scripts, React Compiler, ISR

Lighthouse scores are not vanity metrics. They directly correlate with user experience and SEO rankings. Google uses Core Web Vitals as a ranking factor.


Live Demo

These configurations are running in production:

https://knaru.com

Test it yourself:

  1. Open Chrome DevTools
  2. Go to Lighthouse tab
  3. Run audit on Desktop

License

MIT