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-hapissr-cachingexamples/with-flow/flow-typed/next.js.flowwhich 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!
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: