Readit News logoReadit News
turtlebits · 4 months ago
I dont get it. Yes it's a static site, but it's only text and you're sending 100kb+ of JS over the wire. Is there any reason why you need React?
igorbark · 4 months ago
you don't need to send 100kb+ of JS over the wire to build a static site in react: for example https://vike.dev supports static HTML-only output for a site built with React.

as for "why React", speaking just for myself it's really nice to just have one tool that can do everything (static HTML-only, static with JS, SPA, SSR) and not have to context switch or potentially even have to split my site into two projects just because I want to hop between one or the other approach. and React has the biggest mindshare and ecosystem.

turtlebits · 4 months ago
I think you just proved the point by introducing yet another frontend framework to learn.

And you absolutely don't want one tool to do everything. HTML/CSS is native and understanding it is a requirement for React. It also doesn't require Node and a build step.

owebmaster · 4 months ago
> you don't need to send 100kb+ of JS over the wire to build a static site in react

It is telling that the blog of the fw creator ships 500kb of JS/CSS/HTML to display text on a screen.

> it's really nice to just have one tool that can do everything (static HTML-only, static with JS, SPA, SSR)

WebComponents (+lit-html)

danabramov · 3 months ago
First of all, this is not an argument against the model. I could easily remove all JS and it would still work. I’m keeping it as a choice, not as a consequence of the model.

I have interactive examples on some pages. I’m planning to have more of them and more complex ones. Very little of the infra for this is actually render-blocking — try disabling JS and see that my site loads just fine.

All data and interactive stuff is loaded after the text and doesn’t block the first paint.

If anything, running a webpage test shows that the CSS requests are blocking the first render a bit. Maybe I should inline them or something.

crummy · 4 months ago
If you load external content on build (e.g. external blog pages, prices from an external store, etc), then you'll need some way to template that into your HTML. I'm not a huge React fan but I do like JSX compared to other templating languages.
notpushkin · 4 months ago
Then use JSX without React?
_benton · 4 months ago
Basically at any time they could turn it into an SPA, but tbf you don't need RSC for that.
exiguus · 4 months ago
Think a about the case, that you have a shop, and you need the stock to disable the add to cart button. You can do a API request for every page visit. Or, use something like ISR to revalidate stock on the server and rerender the page every 10min.
girvo · 4 months ago
> This builds on an insight that seems obvious in retrospect: you can take any “server” framework and get a “static” site out of it by running its “server” during the build and hitting it with a request for every page you want to generate, and then storing the responses on disk

I'm showing my age, but we used to do this using Wordpress ages ago. Like 15 years ago or more haha.

Loic · 4 months ago
With Moveable Type we even generated .php files with prerendered content in it from the database and using the PHP part of it to add server side dynamic functionalities. This was a very nice balance between a static and a fully dynamic website.
sally_glance · 4 months ago
We did, but we were not able to run our PHP in the browser or prerender our jQuery on the server.
girvo · 4 months ago
> pretender our jQuery on the server.

That came later, but yes we could (we did some wild stuff with v8js in PHP). And I'm convinced that anything in the blog requires either feature, though I get that more complex systems might.

danabramov · 3 months ago
I didn’t mean to imply this is something new per se. But many people today are unaware of this technique. It is seeing some resurgence but not as much as I would have liked. Hence the article.
KronisLV · 4 months 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!

exiguus · 4 months ago
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.
hombre_fatal · 4 months ago
(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.

zeropointsh · 4 months ago
My exact thoughts[1] when it comes to hosting, things should be static, although I seek joy in Astro and Markdown. [1]https://zeropoint.sh/blog/astro-as-static/
exiguus · 4 months ago
Think about product stock that change or you have a website with a cms and 100 Editors that push changes every 5min. If you have 5k pages. Then its likely, that builds take longer then 5min. And if you want to have a up-to-date website, you have to build it every 5min. This is where ISR and SSR comes into play, to update the pre-rendering on the server.
ndriscoll · 4 months ago
5k pages in 5 minutes? That's only 16/second. If your generator/server is on the JVM I'd expect it to be capable of more like 5k/second at least (and if you have a sensible `last_updated` or `version` field, you could early return with a Not Modified for even better performance). If you're batch processing, you could do a lot better than that.
perilunar · 4 months ago
Why would you rebuild the site every time an editor updates a page? Just update the page that was edited. Even better, don't pre-render anything until the first time it's requested, then render, serve, and cache it.
nicbou · 4 months ago
My website has about 700 pages. A full rebuild takes around 10 seconds.
indigodaddy · 4 months ago
Your artifact or whatever has a footer typo
exogen · 4 months ago
This is also how I build most of my static sites, usually deployed to GitHub Pages. For example, here’s the demo page for a library I recently developed: https://exogen.github.io/turbo-colormap/

Or a more complicated app: https://exogen.github.io/t2-model-skinner/

Are all of Next.js’ features overkill for such sites? Sure, but the convenience such frameworks provide is worth it. And the reason to prefer it over something like Vite is simply routing, which Vite doesn’t cover out of the box, so as soon as I want to add a second page, I now have another problem to solve.

Next.js’ best feature is simply that you’re up and running with `npm i react react-dom next` and step two is just writing the pages.

atoko · 4 months ago
I wonder if the omission of React Context in this example is intentional. Do you think Context is compatible with suspense? In the sense that posts is being passed to components as props three times over.

Is it because each component is expected to abstract over async, relying on the promise state?

danabramov · 4 months ago
Not sure what you mean — we’re just reading some files from the disk and passing that down. It doesn’t need Suspense because everything is static (so no loading indicators are needed). If this was dynamic then I’d probably still not add a loading indicator because you expect a blog index to “pop in” with the rest of the page rather than behind a spinner.
atoko · 4 months ago
Thanks!

More concisely: it’s not always the case that prop drilling is possible within a component hierarchy. In a more involved application you store this object in context.

Is what you are describing compatible with this pattern? How does this inform the design of RSCs and as a developer, how can I expect this to affect me?

nhumrich · 4 months ago
This model already has a name: pre-rendered.
exiguus · 4 months ago
No, you can not pre-render a shop site that needs product stock for UI updates. For this business requirement the classic JAMStack approach does not work. You need ISR or SSR. And you can combine pre-render with ISR for example.

Deleted Comment

raddan · 4 months ago
I understand that somebody might want to generate static pages from code that generates it dynamically, but I fail to appreciate _why_. Are people using this for a handful of pages they want to load quickly and whose contents rarely change, or are people building entire static sites using things like React? If it's the latter... uh... why? It's been awhile since I was a web developer, so maybe my pain threshold is inappropriately low. I think Jekyll is fine and use it pretty regularly.
switz · 4 months ago
It's because inevitably there comes a time where you want some pages (or even sub-pages) to be static, and other pages (or parts) of your application to be dynamic. If the question is "why" the inverse is "why not"?

Dan's blog is rendered as static, works without javascript and still lets him write complex client-side components when he calls for it. And if one day he decides to add a page that renders content dynamically, he can do so in the same patterns and framework that he's already using.

The goal is developer-choice. No need to pick static or dynamic holistically, have access to both when you need them. No need to pick between hydrating the entire website vs. rendering exclusively on the server. No need to pick between writing client-side amenable code or server-only code.

How many platforms have a "marketing" website for / and a platform website for /dashboard? No need to split them, just use a framework that accommodates both seamlessly. It's more powerful, even though it does come with a learning curve.

danabramov · 4 months ago
To give a concrete example, I’ll probably add some dynamic stuff at some point in the future, like commenting with Bluesky or such. It’s nice not to switch tools for that.
bigstrat2003 · 4 months ago
It is certainly not true that the point you describe is inevitable. Lots of sites will never reach the point where they need dynamic content. As to "why not" - because simplest is best until such time as you have a genuine need for the complexity. YAGNI is a maxim for a reason.
dakiol · 4 months ago
I think the reason to split the marketing page from the dashboard one is that you can deploy one without the other. I would actually prefer to have all the marketing stuff in its own repo away from any dashboard code.
dschuessler · 4 months ago
As someone who uses Astro a lot for (mostly) static pages, the two standout features of this approach that come to my mind are code sharing and the ease of integrating SSR/CSR where needed.

Components (be it Astro, Svelte, React, etc.) have a lovely API for sharing code across web pages. I used Hugo before and hit the limits of shortcodes pretty quickly. I can't comment on Jekyll though.

Furthermore, if the need for some dynamically rendered pages or client-side interactivity comes up, it is very easy to integrate this later on. I can build static, server-rendered and client-rendered pages (and everything in between) with the same set of tools, which means less mental load when I develop.

danabramov · 4 months ago
Nowadays it’s common for things to not be entirely static but kind of a mix. Some interactive client stuff, some dynamic server stuff. It’s nice to stay within the same programming model for these.

React might sound like a weird choice to you but its composition model including server and static stuff is quite powerful. See here for a slightly contrived but representative example: https://overreacted.io/impossible-components/#a-sortable-lis...

RadiozRadioz · 4 months ago
Mainly because they all discovered that fully dynamic client-side SPAs written in 100% JS are extremely slow, and wanted a way to speed them up whilst keeping most of the developer experience of an SPA.

That's it. It's not a clever way to arrive at the conclusion that the server is useful, but they got there in the end.

ricardobeat · 4 months ago
Because most mainstream frameworks are too bloated to handle more than a few hundred rps on a normal server, and caching has gone out of fashion (?), so it's the best way to save money.

All of this makes very little sense, but every couple years a guru will shout new commandments from his social media mountaintop and reshape the landscape. It's more of a religious ritual at this point, really.

On a more serious note, it's also because the market is saturated with developers who specialize on React, and this is what's easy and makes sense to reuse their knowledge and code (vs say, setting up a caching reverse proxy and dealing with invalidation).

danabramov · 4 months ago
I’m actually quite excited for caching to make a comeback: https://overreacted.io/functional-html/#caching
manofmanysmiles · 4 months ago
Although I don't usually use react, for me, there is a certain joy and also efficiency that comes from using some of the abstractions that you got from the larger JavaScript/web ecosystem while also having the ability render all that magic to a folder with a couple of HTML, CSS and JavaScript files.

With LLMs to help wrestle the boilerplate, I've found I can whip up a fast static site using advanced ergonomic abstractions that make the whole process a joy! In the past, wrestling the Node and NPM ecosystem was a a complete nightmare. Now it's, a dream — with the occasional storm cloud.

Deleted Comment

aclatuts · 4 months ago
This makes perfect sense for a headless CMS. An editor might upload changes or a new article a few times per day/week into a database through a headless CMS. A webserver could make a request to the headless CMS/database for every web page load, but if the content doesn't change then the webpage can be computed and served statically. The web server can compute just the changes per page or regenerate the whole site on any change on the backend.
omnimus · 4 months ago
You can also simply call it caching and put that rendered html in cache inside or even outside your system and you get the same thing.
floodle · 4 months ago
Because it's an easy and widely used framework to write JavaScript components that react to changes in state
ahuth · 4 months ago
Jekyll is fine. So is React. And Astro. Some folks like different things than others.

Dead Comment

Dead Comment