Next.js: Remove usage of `renderToHTML` from all examples

Created on 30 Jun 2020  路  6Comments  路  Source: vercel/next.js

The renderToHTML is a private API that seems to have accidentally leaked into our examples. We should remove the usage of this function from all examples that have it.

Specifically:

  • custom-server-hapi
  • ssr-caching
  • examples/with-flow/flow-typed/next.js.flow
good first issue story example

Most helpful comment

@Timer
As already stated by @sagar-gavhane there should be an option to manually render a page to HTML. I've already commented on @madiknox's commit that the changes are breaking e. g. the ssr-caching example. The removal of renderToHTML is a critical break and will also break many production apps (like ours) if it won't be accessible at all anymore. I suggest to add an intended public low-level API (with documentation) for rendering manually. renderToHTML() should not call res.end() as well because it leads to a need of "crazy" workarounds like the following to actually cache HTML responses:

const _resEnd = res.end.bind(res)
    res.end = function (payload) {
    if (res.statusCode === 200) {
        ssrCache.set(key, payload)
    }
    return _resEnd(payload)
}
await app.renderToHTML(req, res, pagePath, queryParams)

All 6 comments

which alternative public method we're going to use?

@Timer
As already stated by @sagar-gavhane there should be an option to manually render a page to HTML. I've already commented on @madiknox's commit that the changes are breaking e. g. the ssr-caching example. The removal of renderToHTML is a critical break and will also break many production apps (like ours) if it won't be accessible at all anymore. I suggest to add an intended public low-level API (with documentation) for rendering manually. renderToHTML() should not call res.end() as well because it leads to a need of "crazy" workarounds like the following to actually cache HTML responses:

const _resEnd = res.end.bind(res)
    res.end = function (payload) {
    if (res.statusCode === 200) {
        ssrCache.set(key, payload)
    }
    return _resEnd(payload)
}
await app.renderToHTML(req, res, pagePath, queryParams)

According to @Charioteer's code, I currently write the following cache middleware, irrespective of next.js.

let pageCacheMiddleWare = async (req, res, next) => {
  let getCacheKey = req =>{
    return req.url
  }
  const key = getCacheKey(req)

  // End the request with page cache and bypass the rest code by omitting the next() and return
  if (ssrCache.has(key)) {
    res.setHeader('x-cache', 'HIT')
    res.end(ssrCache.get(key))
    return
  }

  // cache miss, then pass the control to the rest code to render by next() and cache rendered page by hooking the res.end method
  res.setHeader('x-cache', 'MISS');
  const _resEnd = res.end.bind(res)
  res.end =  payload => {
    if (res.statusCode === 200) {
      ssrCache.set(key, payload)
    }
    return _resEnd(payload)
  }
  next()
}

@BigSully I'm currently trying to make this work, but payload turns out to be undefined all the time. How are you dealing with the request? Are you using getRequestHandler? or plain app.render?

@juanstiza I've used a custom express server + app.render.

server.get('/:name?/item/:id', pageCacheMiddleWare, (req, res) => {
  const actualPage = '/item';
  app.render(req, res, actualPage, {
    ...req.query,
    ...req.params,
  })
})

@BigSully Yup, figured out yesterday, I was calling end prematurely. Thanks!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

sospedra picture sospedra  路  3Comments

lixiaoyan picture lixiaoyan  路  3Comments

flybayer picture flybayer  路  3Comments

havefive picture havefive  路  3Comments

formula349 picture formula349  路  3Comments