Milten.ioMilten
Using HTTP/2 and brotli in NextJS
Performance

Using HTTP/2 and brotli in NextJS

Next.js, as a popular framework, provides built-in mechanisms for optimization, but their effective use requires an understanding of the technologies. In this article, we will explore practical solutions for implementing HTTP/2 and compression in Next.js projects based on real cases.

Web application performance has a direct impact on user experience and SEO. According to Google research, 53% of users abandon pages that take longer than 3 seconds to load. Modern protocols like HTTP/2 and efficient data compression techniques are becoming key tools to improve metrics like LCP (Largest Contentful Paint) and CLS (Cumulative Layout Shift).

HTTP/2 solves the “head-of-line blocking ” problem of HTTP/1.1 by allowing multiple requests to be sent over a single TCP connection. This is critical for pages with multiple resources.

Requirements:

  • HTTPS: HTTP/2 requires TLS encryption. A self-signed certificate can be generated for local development:
openssl req -x509 -newkey rsa:4096 -nodes -keyout key.pem -out cert.pem -days 365

Customization in Next.js:

  • Vercel (default): HTTP/2 is automatically enabled when deploying to Vercel.

  • Self-hosting: Use a Node.js server with the https module:

import next from 'next';
import fs from 'node:fs';
import https from 'node:https';
 
const app = next({ dev: process.env.NODE_ENV !== 'production', port });
const handle = app.getRequestHandler();
 
async function startServer() {
    await app.prepare();
 
    https
        .createServer(
            {
                cert: fs.readFileSync('./cert.pem'),
                key: fs.readFileSync('./key.pem'),
            },
            async (request, response) => {
                await handle(request, response);
            }
        )
        .listen(3000);
 
    console.info(`Ready on https://localhost:3000`);
}
 
startServer();

Verification:

Use Chrome DevTools (Network tab) or command:

curl -I --http2 https://your-site.com

Compression settings: Brotli vs Gzip

Brotli provides 20-25% better compression than Gzip. Next.js supports both formats, but it is recommended to use Brotli for text resources (HTML, JS, CSS).

Brotli activation in Next.js:

  • Vercel: Enabled by default.

  • Self-hosting: Add middleware compression with Brotli:

import compression from 'compression';
import next from 'next';
import fs from 'node:fs';
import https from 'node:https';
 
const app = next({ dev: process.env.NODE_ENV !== 'production', port });
const handle = app.getRequestHandler();
 
async function startServer() {
    await app.prepare();
 
    https
        .createServer(
            {
                cert: fs.readFileSync('./cert.pem'),
                key: fs.readFileSync('./key.pem'),
            },
            async (request, response) => {
                compression({
                    brotli: {
                        enabled: true,
                        // params: { [zlib.constants.BROTLI_PARAM_QUALITY]: 11 }
                    },
                });
 
                await handle(request, response);
            }
        )
        .listen(3000);
 
    console.info(`Ready on https://localhost:3000`);
}

Example headers:

Content-Encoding: br

Compression efficiency by JS example

FormatSource File SizeCompressed Size (JS)
Gzip100 KB30 KB
Brotli100 KB22 KB

Using Server Push

HTTP/2 Server Push allows you to send resources to the client before the client requests them. In Next.js this is implemented through the Link component:

import Link from 'next/link';
 
<Link href="/about" prefetch>
    <a>About project</a>
</Link>;

Manual Push Control:

For critical resources (such as fonts), you can use http2.pushStream:

server.get('/critical-page', (req, res) => {
    res.push('/_next/static/chunks/webpack.js', {}).end();
});

Cons:

  • Network overload: Don't fluff more than 5-6 resources.

  • Support: Some older proxies may not be able to handle Push.

Image Optimization

Next.js provides an Image component with automatic conversion to WebP:

import Image from 'next/image';
 
<Image src="/example.jpg" alt="Example" width={800} height={600} quality={75} />;

Format Comparison:

FormatSize (1920×1080)Support
JPEG200 KBВсе
WebP120 KB95%+
AVIF80 KB70%

Frequent errors

ErrorSolution
Lack of TLS certificateUse Let's Encrypt for production.
Incorrect setting of BrotliCheck the response headers via curl.
Push resource overloadLimit the number of pooches.

Conclusion

HTTP/2 and compression remain the foundation of optimization until the arrival of HTTP/3. For Next.js projects, it is important to combine built-in mechanisms with manual server configuration. Testing via Lighthouse and WebPageTest will allow you to accurately assess the effect.

Experiment with settings, keep an eye on updates (e.g. experiments with HTTP/3 in Vercel), and remember: optimization is a process, not a one-time task.

Resources:

INP Debugger
Realtime check for interaction to next paintGetting Started
We use Cookies

We use cookies to ensure you get the best experience on our website. For more information on how we use cookies, please see our cookie policy.

Using HTTP/2 and brotli in NextJS