Next.js 13 is not ready for production

Sanket Berde
4 min readApr 3, 2023

--

Photo by Mark König on Unsplash

This is my opinionated take on why Next.js 13 feels incomplete and lacking in many fundamental ways to be used in a serious production application. Don’t get me wrong, I'm not a hater, next-13 does bring some really powerful new features to the table and I’m sure future releases will cover these aspects.

1. Lack of a concrete middleware solution

Although next 13 introduced middleware.js file, remember it’s non-chaining like express middlewares which can be chained on top of each other. Putting all your middleware needs in a single file seems too clunky to me.

Workarounds and Alternatives:

These third-party libs can provide some express-like routing capabilities in middleware per route. But in a serious application using JWT auth, and role-based auth, I would need every route handler to import and use a stack of middlewares which is too much nuisance. Also, something as basic as this could have been chained like layout.js files are chained. Each level of directory nesting could have had its own middleware that passes state via request property like express.

I’m not comfortable relying on third-party libraries for something as basic as this, this should definitely have been a part of the framework.

Alternative #2

Using a custom server like express and using the next module to only serve web traffic except APIs is an alternative.

https://nextjs.org/docs/advanced-features/custom-server

But the problem with that is say you defined a getUsers API in the express and also need the list of users for SSR, you can either use the prebuilt API in which case you’re not duplicating code but bouncing traffic off localhost for no good reason or directly fetch user records from SSR component in which case you’re duplicating code.

2. page.ts file does not have raw request context and middleware support.

Next13 introduces server-side components which can fetch data directly from the database. This is a really powerful feature but in a serious production app, most routes will be behind authentication and routing would be strictly guarded. What data can be shown on a page would be dependent on the logged-in user's state.

While we can use headers and cookies in server-side components via
https://beta.nextjs.org/docs/api-reference/cookies
https://beta.nextjs.org/docs/api-reference/headers

I personally feel this is highly limiting. I would expect the framework to provide a common place where I can decode logged-in state and pass the user context downstream to server-side rendering.

The current approach would require me to decode tokens on every component or rely on props passed from client-side components. The problem with that is client-side props can’t be relied upon when considering the security of your application. The client-side state can always be edited by local js and plugins.

Workarounds and Alternatives:

You can keep most of the app as client-side components and use any state management lib to fire APIs with secure tokens every time.

But this just kills the whole idea of speedup using SSR. Next really wants you to keep most of the app as SSR and only have leaf nodes on the client side. Wrapping large parts of your app in context providers makes that entire tree to be client-side rendered. Although you can argue that client-side components can have SSR components as children, then managing logged-in users' state is again a problem because as I mentioned earlier, SSR components only get raw headers and cookies and can’t rely on client-side props for security.

3. Context sharing between server and client components seems off

As the docs say, Server-components can have client-components but client-components can only have server-components as children or props. While this makes perfect sense, complex user interactivity is most likely to happen on client components only. Now this interactivity would then need to trigger server-side renders for SSR components. In a non-user logged-in state, this is easy to achieve but when we add authentication to the mix, it gets needlessly hard. You will most likely consider using client-side components only because managing user state in SSR componets is so hard. Which also means you’ll loose all the advantages of starting with next in the first place.

4. Edge is not for everyone

Next is made by Versel and versel wants you to buy their offering which is blazing fast edge functions. While edge is fast, but it’s a no-go for any application using a traditional database like MySql, Postgres or MongoDB. It may work in serverless DB stacks but these databases are here to stay and not everything needs to be modeled serverless.

If you’re using any one of these features, edge is likely not for you:

  • Databases and connection pooling via popular ORMs like Sequelize
  • Native binaries like puppeteer for generating PDFs
  • Socket connections with your backend that connects to redis cluster for synchronization across load-balanced servers.

Where Next Shines:

All the good features of next are highly focussed on frontend developer experience. The <Link> <Image> tag optimizations are commendable.
Where I would actively recommend next:

  • Site you’re building is relatively small
  • Site does not have a lot of complex user interaction
  • Site does not have a dependency on native binaries on the backend
  • Site does not need sockets
  • Site does not have a lot of state management or complex user management
  • SEO is important for the site you’re building

--

--

Sanket Berde
Sanket Berde

Written by Sanket Berde

Co Founder & CTO at Blackcurrant Labs Pvt. Ltd.

Responses (10)