← Back to context

Comment by Rauchg

1 month ago

Heard and appreciate the feedback. We’re well aware of the DX papercuts in Middleware. With 15.5 we made a big step in supporting Node runtime[1] which addresses a slew of issues people have reported over time.

If I went back in time, I would have called it Routing Middleware or Routing Handler. A specific hook to intercept during the routing phase, which can be delivered to the CDN edge for specialized providers. It’s also a somewhat advanced escape hatch.

Since OP mentions logging, it’s worth noting that for instrumentation and observability we’ve embraced OpenTelemetry and have an instrumentation.ts convention[2]

[1] https://nextjs.org/blog/next-15-5#nodejs-middleware-stable

[2] https://nextjs.org/docs/app/api-reference/file-conventions/i...

Appreciate the response. But ...

> Since OP mentions logging, it’s worth noting that for instrumentation and observability we’ve embraced OpenTelemetry and have an instrumentation.ts convention

That makes it sound as though the answer to a clumsy logging facility is simply to add another heavy layer of complexity. Surely not every application needs OpenTelemetry. Why can’t logger().info() just work in a sensible way? This can't be such a hard problem, can it? Every other language and framework does it!

  • > Why can’t logger().info() just work in a sensible way?

    I think OTEL is pretty sensible for a vendor-free and if you want to have a console logger you can use the console exporter[0] for debug mode during local development. Also if Next is designed as a framework to make it easy to build production-grade apps, having a standardized way to implement o11y with OTEL is a worthwhile tradeoff?

    If you view that as being overkill, perhaps you're not the target audience of the framework

    [0] https://opentelemetry.io/docs/languages/js/exporters/#consol...

    • Because making it easy to run and monitor NextJS is never in their interest. The difficulty of that is what pushes people that make it to production with Next onto their platform. The goal is to provide more impressive preoptimizations that complicate the stack more and make it more difficult to run NextJS yourself and actually use any of them.

      3 replies →

First off, since the sentiment here is really negative, I'd like to say that next.js is actually really good for what it does. You've done a great job at building the software that powers millions of websites at this point.

I think a big part of the negative sentiment derives from the fact that detailed documentation and reference documentation almost non-existant. The documentation mostly tells you what exists, but not how to use them, how they get executed, common pitfalls and gotchas etc etc.

The documentation is written to be easy and friendly to newcomers, but is really missing the details and nuances of whatever execution context a given api is in and does not touch on derived complexities of using react in a server environment etc.

This is a trend across a lot of projects these days - often missing all the nuances and details - writing good documentation is really hard. Finding the balance between making things user friendly and detailed is hard.

Keep it up

  • > Finding the balance between making things user friendly and detailed is hard.

    Thanks for the note! Indeed, it is also challenging when experience hides what things are not obvious or necessary to make further connections when reading the docs. It is an area of continuous improvement.

    > The documentation is written to be easy and friendly to newcomers, but is really missing the details and nuances of whatever execution context a given api is in and does not touch on derived complexities of using react in a server environment etc.

    I think on this particular topic, there had been an assumption made on the docs side, that, listing Edge runtime (when middleware was introduced), as its own thing, that might as well run in another computer, would also communicate that it does not share the same global environment as the underlying rendering server.

    I'll do some updates to narrow this down again.

    > The documentation mostly tells you what exists, but not how to use them, how they get executed, common pitfalls and gotchas etc etc.

    Do you have anymore examples on this. I have been improving the revalidateTags/ Paths, layouts, fetch, hooks like useSearchParams, gotchas with Response.next, etc..

    I know the OP post does talk about issues not being responded to, but that trend has been changing. If you do find/remember something as you describe, please do open a documentation issue, pointing to the docs page and the confusion/gotcha - we have been addressing these over the past months.

  • Don't you find it problematic, as a framework that's 8 years old to already have reached version 15.x? Assuming they follow semantic versioning and those are 15 different backwards incompatible upgrades?

    • Most of our upgrades have been fairly painless. Yes, they're not CI-succeeds Dependabot merges, but usually it's basically running the auto codemod and you're done, though I do always scan through the release notes and migration guide. That seems justified for the backbone of our application.

Since you're here — I'll just pipe in.

Here in this article, the author, failing to comprehend the domain differences, is applying the same approach to call a function everywhere. Of course it won't work.

The fallacy of nextjs is attempting to blend function domains that are inherently different. Stop doing that and you will be fine. Documentation won't work, it will be just more confusing. Blending edge and ssr and node and client-side into one is a mess, and the attempt to achieve that only results in layers upon layers of redundant framework complexity.

  • Sounds like you wouldn’t be a fan of React Server Components in general then since blending domains is its whole point.

    • Blending domains is great. Blending domains where you don't get logging at some levels because your framework is incompetent is not.

Yeah, I was actually recommended the instrumentation route by a commenter on Reddit.

I spent a similar amount of time setting up opentelemetry with Next and while it would have been titled differently, I would have likely still written a blog post after this experience too.

This isn't your fault, but basically every opentelemetry package I had to setup is marked as experimental. This does not build confidence when pushing stuff to production.

Then, for the longest time I couldn't get the pino instrumentation working. I managed to figure it out eventually, but it was a pain.

First, pino has to be added to serverExternalPackages. If it's not, the OTel instrumentation does not work.

Second, the automatic instrumentation is extremely allergic to import order. And also for whatever reason, only the pino default export is instrumented. Again, this took a while to figure out.

Module local variables don't work how I would expect. I had to use globalThis instead.

And after all that I was still hit by this: https://github.com/vercel/next.js/issues/80445

It does work, but it was not great to set up. Granted, I went with the manual router (eg. not using vercel/otel).

If you finally decided to support proper server-side middleware, why is there still a limitation for only one middleware function and not a chain of middleewares as every other sane server implementation offers?

  • Consider middleware.ts as a root middleware. Nothing is stopping you from creating your own chain (which is trivial) in there. I mean, that would eventually work the same if nextjs implemented that feature — there would be a root somewhere.

Will vercel/next come up with an official policy on pages roter/API routes, will they be supported long term? If I start a next project I still use pages/API routes, because of several really really bad experiences with the app router.

> Since OP mentions logging [...] we’ve embraced OpenTelemetry

I really hate this stuff. Users raise feedback for something they need, the dev team considers the feedback, they spend a really long time thinking about the most perfect abstraction, scope the problem way out to some big fundamental system, and come up with an extremely complicated solution that is "best". The purist committee-approved solution could technically be used to address what the user asked for, with a lot of work, but that's no longer the focus. Pragmatism goes out the window; it's all about inventing fun abstract puzzles.

All the while, the user just wanted to log things.

Not saying that's the exact situation here, but the phrasing in the comment was all too real to me.