DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’»

DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’» is a community of 968,873 amazing developers

We're a place where coders share, stay up-to-date and grow their careers.

Create account Log in
Cover image for Understanding Transitional JavaScript Apps
Ryan Carniato for This is Learning

Posted on • Updated on

Understanding Transitional JavaScript Apps

Transitional JavaScript Apps? What? Well honestly I'm not sure I know completely myself. It is an umbrella term for the progress that has been happening in JavaScript frameworks the past few years to represent that things are changing. Single Pages as a technology have existed now for over 10 years and Single Page apps today are not the same as they were decade ago, or even 6 years ago. We've embraced server-side rendering and taking responsibility for the side effects of what abusing the technology looks like.

As usual this isn't a new idea, but sometimes it just takes someone to put a name on it, and who better than @richharris in his recent talk at JamStack conf:

Now as some of you know this has been an area of focus for me the last couple years both with Marko and even to some degree with Solid. In fact it's kind of been on everyone's mind:

I've written countless articles about the technologies around these topics but maybe it's time to step back and really appreciate what this means for the average web developer.


Death of Single Page Apps?

Well not exactly. Every time you touch this topic some Rails developer jumps out of the back of the crowd to tell us DHH had this all figured out in 2005. And honestly, that developer would probably wish we spent our time building time machines rather than move the web forward. But that's not why we are here.

No. Server rendering has been part of the equation for frontend JavaScript frameworks for years now. What has changed? Why are these suddenly transitional? Well very little from a technology perspective. It boils down to the fact that in many ways Single Page Apps have set poor expectations for the frontend ecosystem. We built them originally to mimic the behavior of mobile applications, but in reality not all experiences need to be that way. But like any tooling with great Developer Experience people naturally want to use it everywhere.

The problem is this directs people to pull in tons of JavaScript and often to replace functionality that might already be present natively in the browser. And it isn't just people not selecting lean enough libraries. It's architectural. The new hot library like Svelte or Solid doesn't change the equation on its own. Yes I'm author of Solid and I'm saying this without reservation. They are huge improvements and have been able to learn from the lessons of the past but their pedigree is inherent.

Server Side rendering in itself never did anything to reduce the JavaScript bloat. If anything it only adds to it as the code to hydrate tends to be larger than the code to render. We've found ways to statically generate pages, but the second we need JavaScript bam there is the whole bundle. Now for small sites and small framework like Svelte, Solid, or Preact I mean seriously who cares, but we aren't talking silver bullets.

We are more conscious now than in the past about accessibility and the importance of progressive enhancement, allowing for pages to work fine without any JavaScript present. But these are implementation considerations and not architectural. These are characteristics of being a good citizen of the web and our tools should support this.


Lost in Translation

I've publically been a bit critical of the term Transitional Apps, mostly because while SPA frameworks are finding ways they can play nicer, there has been research and development going into actually solving the problem of sending too much JavaScript. And I don't mean resurrecting Rails. I mean full JavaScript frameworks designed for this use case. No need to juggle multiple apps or not be able to leverage the latest tooling.

Dan is right on the money again. Right now on this front there are only a couple games in town. React Server Components might be a consideration once you are in the larger side of things. But React and related infrastructure is too large for what I'm driving at. Let's talk frameworks that can start from nearly 0kb of JavaScript and disappear your app:

Marko

Qwik

Astro

iles

Elder

Slinkity

These have one thing in common. They only send the JavaScript you need to the browser. They do so in different ways but if you want to live the promise of disappearing app here it is. And the reason? Because regardless of the authoring experience they don't view the application as a single top down system.

These solutions also have something else in common. They tend to be used as what is being referred to as Multi Page Apps(MPAs). Yes your next-gen static site generator(Next, Nuxt, Gatsby, SvelteKit, VuePress, VitePress, SolidStart) can generate multiple pages but it is not this. Your SPA framework still treats each page as part of the whole and still can't isolate the pieces. Before you say but what about ____? If the framework isn't in the list above and it was created before 2022, 99% chance it is not doing this.

Aren't MPAs bad? Surprisingly not really so much these days. There are a lot of technologies and the browsers themselves that make these experiences quite nice. Sure there are certain things you can only do when you can preserve the browser state through navigation but for many things they are kind of great. See @swyx' Svelte for Sites, React for Apps. This article is actually more a case for Elder than Svelte and it applies to all frameworks above.

The problem is this conversation is still being had between SPA enthusiasts and, our stranded in time, classic MPA proponents missing the fact that the world has moved on from this argument. MPAs are not old fashioned anymore. If anything JavaScript MPAs are as cutting edge as it gets. But they aren't your grandfather's MPAs.

And here's the thing. This is a distinction so technical in nature that authors of these MPA JavaScript frameworks are struggling to tell the story in a way their value can be understood by an ecosystem flooded with SPAs. The last thing they want to be associated with is SPAs. I've received criticism for misinterpreting Rich Harris' intent and for being divisive rather than inclusive. But is something inclusive when some of the many of defining parties don't want to be included?



Now there is no ill intent here. We're all fighting different battles. Rich is rallying the troops to fend off the would-be time travelers. I'm just standing up for the little guy. Maybe this is a technical distinction that doesn't mean anything. But it does to some of us.

Rich is doing a great service to the community on a whole to bring awareness. He didn't need to include or even mention these other tools yet he did because he believes in where things are going. This response is only concerned with preserving identity and allowing these frameworks to find their voice.


Long Live SPAs Transitional Apps

Didn't I just say SPAs are dead, and MPAs are the future. Not quite. Dan Abramov had it right when he said the future is hybrid. Hell, Rich had it right when he suggested in an ideal future there is no need for MPAs.

It's just that future is not something that is here yet. There are currently unreconciled downsides alongside the numerous benefits. Which is why I dislike the term Transitional Apps now because it jumps the gun a bit. When we have truly Transitional Apps it'd be cool to market them as such. But I didn't coin the term so that isn't my call.

I want to take moment to talk about Qwik again (and this is also relevant to the next version of Marko). These frameworks support automatic independent hydration without manual islands, and hydrating children before for their parent. They can deliver experiences with all the benefits of Multi-Page apps and scale to Single page experiences seamlessly.

That is a Transitional App in my view. An application that literally can transition from a minimal page to an interactive client navigated experience on demand. This is a unique challenge with a whole slew of new tradeoffs. You don't get to pick up an existing framework and just do this. Maybe this deserves a new term. Then next year we can debate the merits of Transitional Apps vs Transformative Apps. Is that the better outcome?

Now there is nothing wrong with any of this inherently so far as that any of these can't be the right solution. You have many options. This really should start from your requirements of what you are building rather than building what your favorite tool enables you to do. When did JavaScript frameworks become the Highlander?

There can be only one

I might generally be pessimistic about framework agnostic endeavors but I'm all for celebrating our differences. Each framework is different and that's a good thing.

Top comments (15)

Collapse
 
jfbrennan profile image
Jordan Brennan

Let's be honest, the real definition for transitional apps is apps that are transitioning away from React 😏

Collapse
 
lexlohr profile image
Alex Lohr

It's now over a decade in the past that I created a little script that allowed loading content from a HTML on the same server to the current one instead of navigating to the page (plus some history handling). This turned a classical multi-page-app into a transitional single-page-app, though in a very naive and not very sophisticated way.

This development is not exactly new. It's just updated, seen through the lens of modern front-end frameworks. I think it's worth waiting for the update.

Collapse
 
justinnoel profile image
Justin Noel

Do you have a sample of this somewhere? I'm not finding it.

Collapse
 
lexlohr profile image
Alex Lohr

No, I wrote it for an employer who did not believe in open source. However, it was a pretty simple script, somewhat along the lines of

document.addEventListener('click', (ev) => {
  const link = ev.target;
  if (
    link.href &&
    link.host === location.host &&
    link.hasAttribute('data-selector')
) {
    link.classList.add('loading');
    fetch(link.href)
     .then((response) => response.text())
     .then((html) => {
       const loaded = new DOMParser().parseFromString(html, 'text/html');
       document.querySelector(ev.target.getAttribute('data-selector')).innerHTML = loaded.body.innerHTML;
        link.classList.remove('loading');
     });
  }
});
Enter fullscreen mode Exit fullscreen mode

That was the main gist, I updated it with fetch, which wasn't stable at the time then; the history handling was a bit more involved, though.

Or did you mean an example of a transitional app?

Collapse
 
hobbydev profile image
Cy Walker

Where do framework agnostic web components (e.g. litElememt ) fit into this future landscape?
As simply a hobby coder I am left wondering...
Why doesn't a web component that, if not supported / JS disabled, that will default fallback to the inner HTML suitable? Whats wrong with dynamic addition to the DOM & progressive loading when it is supported? Why don't we want to use the distributed power in everyones hands / on their desks to carry out client focused workloads & lighten the demand on our back ends?

Collapse
 
ryansolid profile image
Ryan Carniato Author

Yeah in terms of progressive enhancement they have a decent story in theory. I mean you can accomplish most things with built-ins so adding on top of that makes sense. Except Apple basically veto that and is not supporting extending built-in elements in Safari ever. It was still added to the spec for future discussion but they haven't budged on this issue once in 5 years. So you can can't extend Form or Anchor but need to make your own at which point that unfortunately falls apart.

The next thing to consider is that there is no universal way to server render web components. Recently there is the addition of the Declarative Shadow Root which is cool since now it can be server rendered, but without a DOM on the server there is no unit, no component, it has to come down to whatever templating system you have. I actually was in a meeting with the guys from Lit and they were quite unapologetically like it should be expected you need to use a library to do web components. Lit knows how to server render their webcomponents. In a way its just a different framework.

So I don't really see Lit as framework agnostic. Sure in theory anyone can consume them (client side atleast) but for size reasons you don't want to have 20 components authored with 20 different libraries. In a sense framework agnostic is a fallacy unless you use hand spun ones, and well to do that efficiently requires a certain level of expertise. Not saying people won't do this and those in theory form a strong foundation but then we are stuck with how to server render them.

Lightening the load on the backends isn't really the concern here. The problem is every byte of JavaScript in the browser carries weight. Devices/networks vary and are out of our control. The technologies I'm talking about are all about mitigating the cost of JavaScript in the browser. Advances in edge computing/serverless have us covered on the backend, what we really need is less JavaScript in the browser. That isn't something we can scale to mitigate. We've already went heavy client, that doesn't work for everything, now we are looking how to scale back.

Collapse
 
hobbydev profile image
Cy Walker

Wow - thanks for the reply, best reply I've ever received & has really helped me understand the driving forces at play. Thanks.

Collapse
 
kohlerm profile image
Markus Kohler • Edited on

The problem with SDAs in large organizations is in my experience also that without a mono-repo creating large applications is kind of impossible. The reason is that one is forced to use the all libraries in the same version. Also code sharing becomes an hard to solve problem without a common build (yes there is now webpack module federation which might help).

Collapse
 
ryansolid profile image
Ryan Carniato Author

Microfrontends are one solution. All architectures face scaling problems. MPAs might take longer but we still get there with sufficient desire for re-usability and unified experience. I'm not here to crap on SPAs to be clear. I like SPAs and I think they have a plenty of utility. I'm just saying there are different ways to to attack this, each with different tradeoffs. Everything isn't the same, and that's OK.

Module Federation is an interesting idea, but it doesn't change the fundamental math. Either everything is on the same deps, which means you didn't need module federation if you can enforce it. Or things can have their own version at which point you were probably better bundling with your app to leverage tree shaking (ie.. only load the Lodash functions your app uses). The middle ground is sort of no good for anyone, and when you consider Module Federation has its own overhead (often client side orchestration with fetching waterfalls) what are you left with. I think combining this technology with server side rendering is probably the way to go, but first we need to have the right technology to deliver those woven server experiences.

Collapse
 
kohlerm profile image
Markus Kohler

I am also not convinced that webpacks federation are the full solution. With regards to bundling I wonder why we have not yet yet seen more attempts on server side dynamic bundling.

Collapse
 
jon49 profile image
Jon Nyman

I've been experimenting with going from Server side rendering all the way to offline app capability. For certain apps I think this is possible and desired and others it isn't.

But basically, I start with forms as the core so it can submit even if you have no JS. Then I wrote my own HTMX-like library (HTMF) that focuses on forms instead of having the expectation that JavaScript will be available.

Then for the next step I use a service worker to render the HTML for each page that interacts with HTMF and I save the data to indexeddb and then syncs this data to the back end.

I'm just one person with a day job and family so I don't have a whole lot of time to develop this. But it has been fun and I've tried to keep it fairly minimal on the JS side of things. I haven't gotten this completely implemented yet either. It would be nice to get to the point where it works across all the domains. But I don't see any reason why it shouldn't work.

Links:

github.com/jon49/htmf
github.com/jon49/html-template-tag...
github.com/jon49/WeightTracker/tre...

Collapse
 
andrew_march_b968a4edb028 profile image
Andrew March

Why don’t we abandon the DOM altogether? Let’s be realistic we are no longer building β€œdocuments”. Why don’t we see more frameworks that use canvas or wasm to draw pixels? I feel like if developers pushed forward this way, away from the DOM, the browsers would follow suit and speed up the canvas API, or otherwise accommodate the shift. It feels like we are building entire sky scrapers out of chewing gum and popsicle sticks. It’s fun, don’t get me wrong, and something like Qwik is incredibly impressive, but it’s getting to be a very VERY strange way to show pixels to a user. Frameworks can draw and scale text, adjust layout responsively, scroll, navigate, listen for events, and do the rest of the small handful of things we actually rely on the DOM for today. If these tasks were in the framework, we could modify how it works to taste, and not be stuck with a black box DOM to work around. Arguably less fun, but certainly more productive.

Collapse
 
andrew_march_b968a4edb028 profile image
Andrew March

here's a fun one I made over a few weeks in Deno. I just wrote a custom JSX Factory, and went from there. I was able to build text inputs, scrolling, and animations without loosing too much sleep over it. Canvas can handle it (just barely), and this completely redraws everything on every render.
github.com/marchingband/jdom/

Collapse
 
mtyson profile image
MTyson

"If anything it only adds to it as the code to hydrate tends to be larger than the code to render."

Good one liner to describe the current area of action!

Collapse
 
steakeye profile image
Andrew Keats

Well considered salt and spice added to the conversation!

Our newest Hackathon

Join the DEV x MongoDB Atlas Hackathon 2022 and use your ingenuity and creativity to build an application using MongoDB's cloud based developer data platform, MongoDB Atlas.

β†’ Get Started