Remix.run Logo
jongjong 4 days ago

SPAs are nice when your app requires complex state; multiple rows of nested tabs, modals, multiple interlinked select inputs which load data dynamically, charts or graphs which can lazy-load data and update on the fly in response to user actions.

There is a certain level of complexity beyond which you need to load data on the fly (instead of all up front on page load) and you literally cannot avoid an SPA. Choosing to build an SPA is not just some arbitrary whimsical decision that you can always avoid.

Sometimes people just go straight to SPA because they're unsure about the level of complexity of the app they're building and they build an SPA just to be sure it can handle all the requirements which might come up later.

One of my first jobs involved rebuilding a multi-page EdTech 'website' as an SPA, the multi-page site was extremely limiting, slow and not user-friendly for the complex use cases which had to be supported. There was a lot of overlay functionality which wouldn't make sense as separate pages. Also, complex state had to be maintained in the URL and the access controls were nuanced (more secure, easier enforce and monitor via remote API calls than serving up HTML which can mix and match data from a range of sources).

I think a lot of the critiques of SPAs are actually about specific front end frameworks like React. A lot of developers do not like React for many of the reasons mentioned like 'resetting scrollbars' etc... React is literally a hack to try to bypass the DOM. It was built on the assumption that the DOM would always be unwieldy and impossible to extend, but that did not turn out to the the case.

Nowadays, with custom web components, the DOM is actually pretty easy to work with directly but info about this seems to be suppressed due to React's popularity. Having worked with a wide range of front end frameworks including React for many years, the developer experience with Web Components is incomparably superior; it works exactly as you expect, there are no weird rendering glitches or timing issues or weird gotchas that you have to dig into to. You can have complex nested components; it's fast and you have full control over the rendering order... You can implement your own reactivity easily by watching attributes from inside a Web Component. The level of flexibility and reliability you get is incomparable to frameworks like React; also you don't need to download anything, you don't need to bundle any libraries (or if you do, you can choose how to bundle them and to what extent; you have fine-grained control over the pre-loading of scripts/modules), the code is idiomatic.

dannye 4 days ago | parent | next [-]

> there are no weird rendering glitches or timing issues or weird gotchas that you have to dig into to.

Ehm... define the Web Component render blocking in the head, because you want to prevent FOUCs. Then try to access the .innerHTML of your Web Component in the connectedCallback

https://dev.to/dannyengelman/web-component-developers-do-not...

jongjong 2 days ago | parent [-]

Interesting but I wouldn't call that a gotcha. Trying to read the DOM outside of the component is kind of an anti-pattern and I think this kind of behavior should be expected. You'd generally want the web component to be a black box and it works pretty well once you understand the rendering order and focus only on internal or slotted elements. I think the only real 'gotcha' I came across was the order of when the attribute changed callback gets called versus the connect callback but it's easy to adjust the logic internally to take this into account. I can make do with a custom render() method and sometimes additional methods to perform specific granular updates to the component's own DOM...

With React, the component either gets rendered or it doesn't get rendered; all or nothing and React fully controls this. With web components you can also just nit-pick a single element within the component's DOM and only update that one. It gives you more opportunities in terms of performance optimization and how you split up your components... But you can also achieve a similar result as React by just re-rendering the whole component if necessary.

The one difficulty which is actually an advantage IMO is that you cannot pass JavaScript object or function references to Web Components via HTML attributes; you have to pass primitive values... But IMO this a BENEFIT because it forces separation of concerns and it makes the DOM way easier to debug in the dev console. For advanced use cases you can still pass JS refs to a child component by calling methods on it but I try to avoid this because it makes it harder to understand the state of a component.

I like it when I can understand the state of a component just by looking at its attributes and I like those values to be as simple and human-readable as possible. I love opening up my dev console and just tweaking the HTML attributes directly and see the change happening. Makes debugging a breeze. Kind of tricky to do with React and you get into all sorts of weird situations where a render may not trigger when you expect when you change properties of an object without changing the reference itself. React adds a lot of unnecessary complexity there.

Tokumei-no-hito 4 days ago | parent | prev [-]

i remember seeing web components years ago, it sounds like they've improved a lot.

what do you do about the lack of (i assume) ecosystem? due to the ready ubiquity there's practically a library for everything. do you find that using WC you are having to hand roll a lot? i don't mean to be a package slave but for complex and tedious things like graphs / charts.

niutech 4 days ago | parent [-]

There is an ecosystem for Web Components: Polymer, Lit, WCB, ready-built web components at https://webcomponents.org

dannye 4 days ago | parent [-]

Latest blogpost on that site is from 2018

I presume Web Components are so great they haven't had anything happen since 2018