首页 > 解决方案 > 如何通过自定义服务器访问 next.js 呈现的 HTML

问题描述

我希望将 next.js 中的服务器端生成页面作为文件提供。所以我想在自定义 server.js 文件中获取呈现的内容:

const express = require('express');
const next = require('next');

const port = parseInt(process.env.PORT, 10) || 3000;
const dev = process.env.NODE_ENV !== 'production';
const app = next({dev});
const handle = app.getRequestHandler();

app.prepare().then(() => {
  const server = express();

  server.get('/', async (req, res) => {
    const nextResponse = await app.renderToHTML(req, res, '/', req.query);

    console.log('nextResponse', nextResponse);
    console.log('res.body', res.body);
  });

  server.get('*', (req, res) => {
    return handle(req, res);
  });

  server.listen(port, (err) => {
    if (err) throw err;
    console.log(`> Ready on http://localhost:${port}`);
  });
});

奇怪的是,每个 console.log 都返回 null 或 undefined。我认为这renderToHTML只会返回呈现的 HTML 字符串。有没有办法做到这一点?

标签: javascriptnext.jsserver-side-rendering

解决方案


这有点棘手,但可以实现。

这个想法是覆盖res.end函数以便在那里捕获呈现的 HTML。棘手的部分是 Next.js gzips 和流响应使用覆盖函数中间某处的压缩库。res.endhandle

压缩库是使用handleCompressionNext.js 的 Server 对象(可使用 访问app.getServer())的函数初始化的,因此该函数也需要被覆盖。

所以它应该看起来像这样:

const { parse } = require('url');
const next = require('next');
const express = require('express');
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });

const port = process.env.PORT || 3000;

const handle = app.getRequestHandler();

app.prepare()
.then(() => {
    const server = express();

    server.get('*', async (req, res) => {
        const parsedUrl = parse(req.url, true);

        const nextServer = await app.getServer();
        const _handleCompression = nodeServer.handleCompression.bind(nodeServer);

        nextServer.handleCompression = (req, res) => {
            _handleCompression(req, res);

            const _resEnd = res.end.bind(res)
            res.end = function (payload) {
                console.log('Rendered HTML: ', payload);

                return _resEnd(payload);
            }
        }

        return handle(req, res, parsedUrl);
    });

    server.listen(port, err => {
        if (err) throw err;
        console.log('> Ready on http://localhost:' + port);
    });
});

获得呈现的 HTML 后,您不必使用已保存的_resEnd功能。随意操作,作为文件,或任何你想要的。


推荐阅读