How to get generated HTML as string in Next.js custom server?

Viewed 659

I have an SSR API that renders React components. I need to get the rendered HTML as a string so that I can manipulate it and send it back in a JSON object with other info.

In Next.js, I am using a custom server. How can I get the HTML as a string in a variable ?

// server.js
const { createServer } = require('http')
const { parse } = require('url')
const next = require('next')

const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()

app.prepare().then(() => {
  createServer((req, res) => {
    const parsedUrl = parse(req.url, true)
    const { pathname, query } = parsedUrl

    if (pathname === '/a') {
      // GET THE RENDERED HTML IN A VARIABLE HERE
      app.render(req, res, '/a', query)
    } else if (pathname === '/b') {
      app.render(req, res, '/b', query)
    } else {
      handle(req, res, parsedUrl)
    }
  }).listen(3000, (err) => {
    if (err) throw err
    console.log('> Ready on http://localhost:3000')
  })
})

I tried using the render function and also the renderToHTML function, but could not get the rendered string. I don't really understand what the render function is doing under the hood.

Any clue on how to achieve this ?

1 Answers

You can overwrite res.end and capture the generated HTML that Next.js passes to it. Note that res.end is called after app.render.

if (pathname === '/a') {
    const resEnd = res.end.bind(res) // Save original `res.end` into a variable to be called later
    res.end = (html) => {
        console.log(html) // Manipulate the HTML as you like
        resEnd(html)
        return
    }
    app.render(req, res, '/a', query)
} 
Related