We create the next request handler function via app.getRequestHandler()
. This returns a standard express handler, so we use it like expressApp.get('*', middlewareA(), middlewareB(), nextApp.getRequestHandler())
.
When the handler is invoked:
- Server#handleRequest (next-server/server/lib/next-server.js)
- Parses URL + query string if not already done
- Server#run
- Searches for matching route
- Runs it
- The routes were generated in
#generateRoutes
- The routes were generated in
- Or 404
- Runs it
- Some crazy stuff - lots of router layers, eventually gets to #render
- Searches for matching route
- Server#render
- Checks if it’s an internal page, or blocked, and returns
- Server#renderToHTML
- In dev, will trigger a rebuild
- This fires complete callbacks per page, so we respond as soon as our page is ready, not all pages
- Will output manifest too which lists what we’re outputting
- In production we have prebuilt everything
- App/document code is loaded via standard cjs require()
- So it’s just running in Node, nice n simple
- And cached in production etc
- Loading page is via require, path generated by next-server/server/require.js
- Again pointing to a output file in .next build, .next/server/static/development/pages/some-page.js
- Webpack has output it as CJS
- e.g .next/server/static/development/pages/_document.js
- So it’s just running in Node, nice n simple
- Then we generates the HTML required to load the page
- Passed lists of all scripts required, take from the manifest file
- Calls
Document.getInitialProps
to get initial data used in our SSR - Then creates our
{ type: Document, … }
vdom value - Our vdom tree is passed to renderToStaticMarkup, which will instantiate our components, call render, and output a string HTML
- In dev, will trigger a rebuild