The major difference with Fresh is that it runs everything just-in-time when it is needed, hence doesn't require building no shipping anything by default to the client(but you can still ship some JS for client side interactivity).
The key here is no building (packing, bundling, transpiling). This don't just save time but actually removes the complexity as what you see is what you get. The only things that ships to users visiting your site is around 0-3kb (plus client side JS you decided to ship), not prebundled transpiled polyfilled prebuild 10mb JavaScript.
Since it is Server Side Rendering, the performance is based on design decision.
This 0-3kb includes HTML or some JavaScript runtime ?
How is that possible? In the documentation (https://fresh.deno.dev/docs/getting-started/create-a-route) I see .tsx files... so I imagine that at least one needs to compile TS to JS and then JSX to JS. Perhaps I got that wrong, though and browsers nowadays support TSX out of the box.
I think they all try to solve the same problem: how to get a modern interactive app to run on (and be performant) what is essentially a hacked-together ecosystem, HTML + Javascript, with decades of backward compatibility baggage. The essential problem is that browsers work on the ancient and really poorly designed DOM, but developing against the raw DOM sucks. It's fine if you have a simple webpage with headers and some text, but once you get into stateful UIs, it gets hard to maintain pretty quickly. So there's a mismatch between user experience (in HTML) and developer experience (terrible in HTML, better in other frameworks). So developers of complex apps end up abstracting it away with something like a JAMstack.
So you have things like React, which is essentially a UI library (vs a more fully-featured framework like Angular or even the older Rails stuff, or something like Laravel/Symfony for PHP or whatever the .NET equivalent is). React lets you compose apps not out of DOM primitives but components you define yourself, which in turn are reusable and composable.
But there's a lot of things that React don't handle out of the box: page routing, state persistence, static builds, image optimization, hot reloads, CDN caching and invalidation, etc. A lot of teams end up reinventing all those wheels, or else clobbering together 80 different open-source solutions and 10 vendors. It gets hard to maintain very quickly.
Enter Next.js, one of the earlier successful React-based frameworks. It turns a React app from a quirky UI library into something almost beautiful, because you can now make an entire app, not just a UI, using React and some easy to learn JS config objects.
For example, to make a blog with React, you'd first need a CMS (let's assume you have that part figured out) and an API (also figured out). You can write it as a single-page app, using fetch() or whatever to query the API every time. But then the client has to download that and then render the page. If the CMS is on a different host than your webpages are, it can take quite a while. That whole time your user is waiting, seeing a blank page. And if your CMS goes down, your website goes down, even if the content's been the same for days.
Anyway, you could try to statically bake all that into HTML, but then every time you add a new blog entry or update an existing one, you have to rebuild your project. And then if you want it to be fast, you have to invalidate all your CDN caches.
Next.js essentially takes care of all of that for you, in one easy to use and well documented package. Combined with Vercel (the company behind Next.js, who provides hosting) it also abstracts away all the complexities of the buildchain, CDNs, invalidations, etc.
As a duo, their most powerful feature is rehydration. You can code your app as though it were a single-page app, using React to compose components and pages, combined with file-system routing, to create a whole site. But then you push your changes and that's where the magic starts: Your Next.js server (like Vercel) picks it up, builds it with data fetched server-to-server from the CMS, bakes everything into flat HTML + CSS, and invalidates it across the CDN within seconds. At this point, any user who visits your site will be able to download the HTML + CSS, even with Javascript disabled -- the client does not ever speak to your backend directly. To them, your page is just a static HTML page, served straight from the CDN edge. This means the client doesn't need to load React to see your page. They can have JS disabled and it still shows up normally, it just won't be interactive.
Seconds later after the HTML has loaded, some "bootloader" JS then downloads all the other JS that enables interactivity and dynamic data fetches (comments, etc.)... all invisibly to the user. That is the "rehydration", taking a React app that you wrote and the server buildchain "dehydrated" (baked into HTML + CSS), but then rehydrating it to add interactivity back. Yes, you could do all that manually, but Next.js makes it magically trivial... you never have to think about it, it just works. And it's lightning fast.
So take that rehydration stuff and add on a bunch of other quality-of-life developer experience improvements. For example, images are traditionally another headache, needing something like Imgix or Cloudinary to be able to dynamically resize them on the server (so the el cheapo 320p Android doesn't get served the same 4k retina image). Same with script updates... if you change your SPA, you have to figure out how to invalidate current caches, how to sure visitors who've cached the old version still works with your backend API, etc. Or hot refreshes, or page-by-page invalidations, or whatever. It does all of this in one framework, so you can get rid of ReactRouter, Redux (useContext can handle many uses cases), image processors, Preact, Express, etc. Really the only thing you need to provide is a CMS of some sort, typically a headless one.
That's Next.js (the open-source framework). Behind them is Vercel (the hosting/PaaS company which maintains Next.js). Next is the one I'm most familiar with, but I believe the others are similar (but someone correct me if I'm wrong):
Nuxt.js is to Vue what Next is to React. I believe it's a little less featureful than Next, and it's maintained by a different company.
Remix takes some of the Next.js principles but implements them differently; instead of having a server rebuild and bake your project at push, you can do a similar thing on edge compute/serverless (like Cloudflare Workers directly). It has a really neat feature: nested routes (really more like UI layouts), which are composable UI units that are hydrated serverside, similar to Next.js, and then sent to the client as HTML wholesale. So like your <Dashboard> can include <Widget> and <Chart> and <Comments>, but each one can be individually hydrated, composed, and reused -- all invisibly to the client. My understanding (again, not familiar with Remix) is that this was such an amazing feature that Next.js straight up copied it last month with their Layouts RFC (https://nextjs.org/blog/layouts-rfc?utm_source=next-site&utm...).
Fresh looks like Deno's attempt to produce something similar, but it's still early and not quite as powerful.
If you're a web dev and you've never tried this stuff, I strongly recommend taking a look. I've been coding webpages since Netscape, before CSS was invented. Next.js was the single biggest improvement to my professional life in decades, especially coming from the hell that was Drupal + jQuery. I coupled Next/Vercel with a vendor-supported headless CMS, and the overall developer experience made me fall in love with my job for the first time ever. So much so, I actually switched careers from being full-stack to solely frontend/React focused, because Next.js just made it so enjoyable. No more infra and DevOps hell, it all just works, it's all in JS/Typescript, and I can just focus on coding for UX. What used to take weeks to do in the old PHP + jQuery framework would only take minutes to prototype, a day or two to finish in Next. I hope the other frameworks bring you as much joy!
1. Pure front-end solution (React) they wait on the front-end to handle it all. 2. Remix or Fresh, they are still waiting, it just happens on the server.
It seems like there isn't a significant difference either way - ultimately, you are still waiting, as a user. If the payload is huge, maybe the server model is faster - unless the server is getting smashed with requests, then it'll actually be slower?
[0] https://remix.run/docs/en/v1/pages/philosophy#serverclient-m...
But many sites are more heavily read than interacted with: blogs, news, documentation, even to some extent HackerNews and comments. These are all "write rarely, read often" sites. In those cases, prerendering can be way faster both for the end-user (it's just HTML being downloaded from one single source) and also for the origin server (you build once, CDN caches it everywhere and takes over from there). Typically, the tradeoff is that it's also a PITA to manage these buildchains, especially once you get into obscure webpack or babel configs. Next.js handles it really elegantly.
Next.js has other benefits too, especially when coupled with Vercel. It is more than CRA + static builds, and even if you never end up using the rehydration system, the routing/image optimization/per-commit preview sandboxes may still be helpful, though not life-changing. For me the killer feature was being able to detach the data layer from the (write-rarely, read-often) frontend, such that the frontend could always just assume it would have access to the latest data from the API (because Next.js takes care of that).
To give you a before-and-after comparison... I worked on this page previously: https://www.fieldmuseum.org/exhibitions
That version is running on Drupal. Some of it was in a Drupal template, some of it was in-house PHP. To fetch data, we had to use a mix of Drupal built-ins and some raw SQL, mixed into some ugly templating language. Then through custom modules we had to add jQuery and React, sprinkled on top. Drupal had to "build" the page into HTML whenever we save, and then a separate buildchain would add back the Javascript on top of that and try to bundle it all. The developer experience was ugly and required needed at least four languages (Drupal, PHP, jQuery, React). Filtering is done serverside, so filtering by e.g. Type = 3D movie requires an API call and takes several seconds. If you turn off Javascript the whole page breaks and you can't access any of the links anymore. This version is pretty fast thanks to in-house optimizations and extensive caching by Pantheon (a specialist PHP host), otherwise it would be really, really slow. Our dev and staging machines were hell to use because every page took like 10-20 seconds to load.
The new version (WIP, and I don't work there anymore): https://nextfield.vercel.app/exhibitions
That is 100% Next.js/React and only that, no more PHP or jQuery needed and no other frameworks. Data was moved to a headless CMS (DatoCMS in our case, which returned convenient GraphQL responses). It is slightly smaller over the network. All filtering is clientside and instant. If you go to a different exhibition page, it just has to load the JSON data for the new exhibition (text and image URLs + thumbnails), in like a 25kB JSON instead of the whole HTML page (headers and footers and all) all over again. The images are resized on the server for your viewport needs before they're sent to you (though TBH I am not a big fan of that feature because it's not preloading images right now). Even if you had JS disabled, the page would still load and the images and links would still work, you'd just lose the interactive filters.
So for users, the new version is hopefully a bit faster. The real improvement was in the developer experience, being able to code everything in React and not have to think about how it's going to get rendered into HTML or how we're going to balance our caching strategy (invalidations vs not overloading origin). And devs didn't need to use PHP at all anymore.
CRA wouldn't handle much of that, it'd just serve up a SPA run by a single server.
The Drupal version is seeing production traffic, while the Next version only sees a few devs now and then.
Anyway, with a bit of discipline and some frontend tricks (preconnect, preload, async) you can create a Drupal page that's super fast. And it would actually serve less code to the end user than a page based on JS frameworks (as all things happen on the server).
Example: https://www.magneticpoint.com/
You still need a place to store actual content/data, of course. But that could be any store or service that gives you an API endpoint to fetch from.
The HTML it returns is really big! 374kb before compression. I turned off Javascript to see how the page loaded without it, and it still downloaded the whole 374kb HTML (I guess that's to be expected).
I dug into the HTML and realised that the reason for the size is that Next.js includes a <script id="__NEXT_DATA__"> element that contains the entire data of the page's components as JSON for React to hydrate. This JSON takes up 60% of the whole HTML file! I suppose it's prioritising smooth rendering over reducing data use, but it doesn't seem very optimal, tbh. And it's really inefficient for browsers operating without JS, since every navigation click requires downloading a bloated HTML file.
I found Github issues, SO questions, and blogposts about this drawback, and it seems like this is a common practice for even the largest websites. This massive duplication seems to be a problem that newer frameworks are trying to solve. I wonder if non-dynamic sites like this aren't better off just being static HTML served from CDNs, since they aren't interactive.
Also, the main stylesheet is 1.12mb uncompressed! Bootstrap is part of it, but it seems like there's a lot of other CSS?
(Now I understand more about why my web browsing on mobile consumes so much data even on low-media sites, ouch.)
1) That 374kB file is only like 50kB gzipped. We had bigger fish to fry/optimize, like that massive CSS. (Which is a holdover from the PHP days. Phase 2 of the project would eventually have refactored that and tree-shaken it, but it was out of scope for the prototype.) A lot of the bloat you see is because that's still a work in progress and they haven't had a chance to do any optimizations yet. A future version would probably get rid of much of that CSS and maybe even Bootstrap, then think about webfonts, oversized images, etc. There's a lot of work on that front.
2) Our target audience wasn't expected to have Javascript disabled, and with it enabled, Next's hybrid rendering model actually makes it really fast to navigate between pages after an initial page load. In an earlier test, we had the individual exhibition pages side-by-side, the Drupal version next to the Next one in iframes, plus back/forward buttons to navigate through each exhibition in sequence. Originally that was meant just as an easy way to catch visual differences, but we realized that the Next version was loading almost instantly (couldn't even see it load), whereas the Drupal version took 4-5 seconds per navigation. It turned out that Next was able to just download the tiny JSON (~20kB) for each exhibition and injected that into the React shadow DOM for updates; it didn't have to download anything else while navigating between navigations. That was an unexpected, and really powerful, feature that would normally only be available in SPAs.
Realistically, this means that if users had JS on, the initial page load might be a bit bloated, but subsequent navigations between pages should be MUCH faster.
3) The JSON shape was also an artifact of our CMS API (in GraphQL). If we wanted to, we could've optimized it before sending it over the wire.
4) Most importantly... I want to reiterate this... the main benefit of Next.js is NOT page performance, but developer experience. To the extent that there are any improvements at all to page load speed, that is a nice side effect. But even if there weren't, it would still be worth it for us. The big difference is in being able to quickly create new pages/templates, in a single language (JS), with a zero-stack configuration. Especially once we also decided to move the content to a hosted headless CMS. That meant no more LAMP stack to maintain, no more DBs to prune, no more fiddling with CDN caching, Drupal modules, Docker, CI/CD etc. Previously we were spending 80% of our dev time fighting our own stack and framework (Drupal is really really hard to work with, even compared to the messy Node/React ecosystem). Next got us out of the DevOps and infrastructure game completely so we could focus solely on the frontend, and Next + Vercel takes care of everything else. It's not just "serverless" but almost stack-less in a way (managed). All we had to do is write React, push a commit, and done. For a small team, that was HUGE... being able to push out a new template in a matter of hours instead of days/weeks, and being able to deploy to production in seconds (and roll back in seconds) too. In the Drupal world, there are companies like Pantheon and WPEngine and Acquia that try to do the same thing for the PHP landscape (and they do it well), but Next + Vercel is waaaaaay easier and faster. Other competitors in that scape (for JS) are Netlify, Gatsby, etc. These Jamstack hosts are gaining popularity because they are so much easier to work with than the traditional backend + pipeline + frontend model. But of course they have their own tradeoffs and aren't right for every use case -- for example, if we anticipated heavy user interactions (logins, profiles, personalizations, etc.) we would've had to consider a lot more factors. But for write-rarely, read-often informative website, it was the perfect fit for us. YMMV of course!
So until that happens the UI looks functional but isn't. The user is left to tap/click furiously on that button but nothing happens?
It sounds to me like this is only suitable for pages where interaction is an exceptional thing that users will only attempt to do after reading some content.
There might be cases where the issue you describe occurs, but I haven't actually seen it in testing. If it's a concern, you could of course add throbbers or the such. But generally, in our limited tests, it hasn't been an issue.
Still, it is an issue they (and the React ecosystem) are actively working on improving, with React Suspense (https://17.reactjs.org/docs/concurrent-mode-suspense.html) and Next.js Layouts (which I understand is copied from Remix(?) and can fetch component groups in a hierarchy https://nextjs.org/blog/layouts-rfc). There is also server components and streaming, which can render HTTP snippets/components (instead of pages) and send those back over the wire, similar to the PHP days: https://nextjs.org/docs/advanced-features/react-18/streaming
But again, the benefit is mostly to the developer experience. It's a lot easier to write everything in React than to have to switch between PHP and Drupal (as in the admin UI) and JS. There are some benefits to the user experience if done well, but the same could be said of a statically cached Drupal output.
Actually I think the big trend in JS front-end development is realizing that you do have to think about it! React rehydration is often a very slow step (whether it's Next.js or anything else, I don't think it makes a difference), definitely not "lightning fast" on non-trivial apps with lots of data. Islands architecture goes a long way towards solving that but it's still a bit limited today.
[0] https://twitter.com/dan_abramov/status/1200118229697486849
There are some ways to work around that, if it actually turns out to be an issue (which it wasn't for us)... discussed it a bit more in my other response: https://news.ycombinator.com/item?id=31727249
Where does Next fit here?
That would be Blazor for anyone interested in checking it out.
Deno has other advantages in paper, like official ts support, all the tooling was written in rust (so it's more performant that the default ones that the others use).
The only downside right now with deno is popularity and maturity of the ecosystem, it is just too new, so you will have hard time finding what you are looking for that works out of the box, while a lot of companies invested in node official packages.