Comment by KronisLV
7 days ago
> First, the “hybrid” approach reduces tooling fragmentation—why have two ecosystems when the overlap is so large? The difference is just when the code runs.
Because you end up with two subsets of supported features in the same technology, even in the linked page: https://nextjs.org/docs/pages/guides/static-exports
Supported Features
The majority of core Next.js features needed to build a static site are supported, including:
Dynamic Routes when using getStaticPaths
Prefetching with next/link
Preloading JavaScript
Dynamic Imports
Any styling options (e.g. CSS Modules, styled-jsx)
Client-side data fetching
getStaticProps
getStaticPaths
Unsupported Features
Features that require a Node.js server, or dynamic logic that cannot be computed during the build process, are not supported:
Internationalized Routing
API Routes
Rewrites
Redirects
Headers
Middleware
Incremental Static Regeneration
Image Optimization with the default loader
Draft Mode
getStaticPaths with fallback: true
getStaticPaths with fallback: 'blocking'
getServerSideProps
To me, this feels about as awkward as React moving from class based components to function and hook based ones, dragging a lot of the large libraries alongside with it, meaning that if you tried using class based ones for a while you'd run into cases where some of your dependencies would only offer documentation for the functional approach.
Mixing approaches that differ so much inevitably leads to awkwardness. I'd prefer a SPA library/framework without awkward sharp edges and a separate SSR solution, each specialized at what they do, neither trying to do everything. That way the toolchains remain simpler, there's fewer abstractions at play and fewer things to keep in mind. But if one tool to rule them all works for you, then great!
I consider Next.js as a solution that not only embraces the JAMstack approach, with all its benefits and drawbacks, but also facilitates the implementation of business requirements that demand a more dynamic content update mechanism, such as Incremental Static Regeneration (ISR). Additionally, it supports functionalities like handling headers, redirects, and rewrites. Essentially, Next.js addresses the limitations of JAMstack while retaining its advantages.
(God why is this 8 paragraphs. This is what you get for being my first HN post of the day with a cuppa fresh coffee in hand. Shame on you for being the first post I saw while firmly rocking on my hobby horse.)
Dunno, the Next.js hybrid approach seems both trivial to understand the trade-offs of, but also optimal:
You get to use the same tooling, but if you don't use any of the dynamic stuff like the router (stuff you'd obviously need to use a server for), then you get to output static html files.
Or, you can start with an SSG site and then decide that you want server-side logic, and all you do is opt-in to some server-side logic.
This works well because instead of traditional SSGs like Jekyll, Next.js has the nice UX/DX of writing a dynamic server where it has a build step that crawls all your routes to generate static files (the right way to do SSG imo). So when you decide you want to run on a server, you just deploy it on the server instead of using the crawl step.
Framing this into a confusing subset vs superset distinction kinda obscures what's really going on. It's like writing an Express app but opting in to SSG by using a build tool that wget-crawls your local server.
The downside of Next.js is that client-side "rehydration" is inherently complex, not that it can enumerate your routes to generate static files. It's just that when you build a system that can render server html templates to strings and then rehydrate them in the browser, it's trivial to build the tool that saves those server templates into static html files.
And I think you're imagining that you could only do such a thing if you designed for it from the beginning, essentially bending over your abstraction to force that feature, when it's actually a trivial entailment of the system in the first place.