迁移场景下:如何用Express将Next.js输出转为指定JSON格式
在Express.js中包装Next.js生成的内容为指定JSON格式
方案一:拦截响应流收集HTML内容
通过重写Express响应对象的write和end方法,收集Next.js输出的所有内容块,最后将拼接后的HTML包装成JSON返回。
实现代码
const express = require('express'); const next = require('next'); const port = 8080; const dev = process.env.NODE_ENV !== 'production'; const nextApp = next({dev}); const handle = nextApp.getRequestHandler(); // 响应拦截中间件:收集HTML内容并包装为JSON function captureHtmlResponse(req, res, next) { // 过滤静态资源请求(如Next.js的/_next/资源、图片、JS/CSS文件),只处理页面请求 if (req.path.startsWith('/_next/') || req.path.match(/\.(js|css|png|jpg|svg|ico)$/)) { return next(); } const originalEnd = res.end; const contentChunks = []; // 重写write方法,收集所有输出的内容块 res.write = function(chunk) { contentChunks.push(Buffer.from(chunk)); return true; // 返回true表示写入成功 }; // 重写end方法,将收集到的HTML包装为JSON返回 res.end = function(chunk) { if (chunk) { contentChunks.push(Buffer.from(chunk)); } const fullHtml = Buffer.concat(contentChunks).toString('utf8'); // 设置正确的响应头 res.setHeader('Content-Type', 'application/json'); // 发送包装后的JSON originalEnd.call(this, JSON.stringify({ content: fullHtml })); }; next(); } nextApp.prepare().then(() => { const server = express(); // 先挂载拦截中间件,再处理Next.js请求 server.use(captureHtmlResponse); server.all('*', async (req, res) => { return handle(req, res); }); server.listen(port, () => { console.log(`[server]: Server is running at http://localhost:${port}`); }); });
方案二:直接调用Next.js的renderToHTMLAPI
通过Next.js提供的renderToHTML方法主动获取页面渲染后的HTML字符串,再包装成JSON返回,无需拦截响应流,逻辑更直接可控。
实现代码
const express = require('express'); const next = require('next'); const port = 8080; const dev = process.env.NODE_ENV !== 'production'; const nextApp = next({dev}); const handle = nextApp.getRequestHandler(); nextApp.prepare().then(() => { const server = express(); server.all('*', async (req, res) => { try { // 解析当前请求的路径和查询参数 const { pathname, query } = nextApp.getRequestHandler().parse(req); // 调用renderToHTML获取页面渲染后的HTML const pageHtml = await nextApp.renderToHTML(req, res, pathname, query); // 返回包装后的JSON res.json({ content: pageHtml }); } catch (error) { // 处理渲染错误(如页面不存在),交给Next.js默认处理逻辑 handle(req, res); } }); server.listen(port, () => { console.log(`[server]: Server is running at http://localhost:${port}`); }); });
注意事项
- 方案二的
renderToHTML会自动处理页面的服务器端数据获取逻辑(如getServerSideProps),和原Next.js请求行为一致 - 若需过滤静态资源,可在路由处理中添加路径判断,跳过静态资源的JSON包装
内容的提问来源于stack exchange,提问作者chrgue
相关产品推荐
相关产品推荐

