Next.js is a popular framework for creating React.js frontend applications. It is especially useful for improving SEO for website while keeping SPA like application architecture.
Next.js offers a custom server implementation. This is often required for custom handling of incoming requests. This could be redirecting based on the user session or CSRF implementation. Sometimes you may want to modify the HTML responses for a Next.js rendered page. This could be especially useful for injecting scripts or meta tags based on headers. Something like this is requested in issue.
First, you need to disable compression
in your Next.js project config. Compression is often already performed by cloud computing frontend servers or an external service like Cloudflare.
In this example, we are using an Express.js based custom server. Here we are modifying all HTML output(s) and injecting a custom meta tag, when suitable.
1import next from 'next';
2import Express from 'express';
3
4const server = express();
5const app = next({ dev: true });
6const handle = app.getRequestHandler();
7
8server.all('*', async (req, res) => {
9 const isHTMLRequest =
10 req.method === 'GET' &&
11 req.accepts(['json', 'html']) === 'html' &&
12 !req.path.includes('/_next/');
13
14 if (isHTMLRequest) {
15 // get tag value
16 const value = await getMetaTagValue();
17
18 const _resEnd = res.end.bind(res);
19 res.end = function (payload) {
20 if (!payload) return _resEnd(payload);
21
22 const modifiedPayload = payload.replace(
23 '</head>',
24 `<meta name="custom-data" content="${value}" /></head>`,
25 );
26
27 // ensure that correct content length
28 // is set, so content is not trimmed
29 res.setHeader('Content-Length', Buffer.byteLength(modifiedPayload));
30
31 return _resEnd(modifiedPayload);
32 };
33 }
34
35 return handle(req, res);
36});
37
38app
39 .prepare()
40 .then(() => {
41 server.listen(3000);
42 })
43 .catch((error: Error) => {
44 console.error(error);
45 });
Also notice that we are resetting content length, so modified HTML content is not trimmed.