[RFC] server(less) middleware
See original GitHub issueFeature request
Currently there are a lot of users that create a custom server to do middleware behavior, for example server-side parsing of request bodies, cookies etc. Currently Next.js provides no way of handling this without a custom server. Meaning it can’t be done in serverless / other environments.
Describe the solution you’d like
Ideally users would define middleware as a top level export. Meaning that pages can define middleware requirements:
// PageContext being the same values as `getInitialProps`'s context
export async function middleware({req, res}: PageContext) {
// do something with `req` / `res`
}
function IndexPage() {
return <h1>Hello world</h1>
}
export default IndexPage
However this also introduces the complexity of having to code-split / tree shake away user imports that are server-only.
So for the initial implementation (and incrementally working towards the implementation above) I’d start with supporting middleware in pages_document.js which is always server-side rendered so it makes sense to have it there.
One thing that was brought up is “why can’t this just be done in getInitialProps of _document”.
The reason that we need a new method is that the lifecycle of calling getInitialProps looks like this:
- pages/_app.js getInitialProps is called,
- pages/_app.js getInitialProps calls the page’s getInitialProps
- pages/_document.js getInitialProps is called
- pages/_document.js getInitialProps calls
renderPage renderPagecalls React’srenderToStringand returns the html, head tags and styles.renderToStaticMarkupis called to render the _document shell- request is ended using send-html.ts, which adds etag etc.
Generally when using middleware it has to be called before getInitialProps because you could be parsing something needed in getInitialProps
So the middleware has to be called earlier.
Meaning the lifecycle would look like:
- pages/_document.js middleware is called
- pages/_app.js getInitialProps is called,
- pages/_app.js getInitialProps calls the page’s getInitialProps
- pages/_document.js getInitialProps is called
- pages/_document.js getInitialProps calls
renderPage renderPagecalls React’srenderToStringand returns the html, head tags and styles.renderToStaticMarkupis called to render the _document shell- request is ended using send-html.ts, which adds etag etc.
So for the initial implementation we’d want something like:
// pages/_document.js
// PageContext being the same values as `getInitialProps`'s context
export async function middleware({req, res}: PageContext) {
// do something with `req` / `res`
}
// rest of _document.js
Issue Analytics
- State:
- Created 4 years ago
- Reactions:126
- Comments:55 (34 by maintainers)

Top Related StackOverflow Question
Hey @timneutkens and @Timer - great to see v9 has landed. I do believe that first-class support for API routes is a monumental and vital step for NextJs.
I’ve looked through #7297 and the new documentation, and it seems middleware support is not there yet, right? Would love to be able to rewrite
next-i18nextand remove the custom server requirement (https://github.com/isaachinman/next-i18next/issues/274).Current plan is to have the notion of languages / language detection built into Next.js, that way we can make it work with both SSG and SSR and have it work on the edge for the majority of cases. This will be similar to eg preview mode.