Very cool overview and a great article—it’s fascinating to see how far web components have come. Data passing, interactivity, and state management still seem pretty tedious in vanilla, though!
Data passing seems inherently broken in web components, because all HTML attrs must have string keys and values. Such a model just can't be built on top of.
At that point you're not using HTML anymore, you're just calling html() in a fancy way, and that's the whole point of the complaint, that custom-elements are not good at being plain HTML even though that's like its whole thing.
That's not web components, though that's lit-html. That's an additional library you need to pull in to manage your web components. Which kind of ruins a lot of the stated benefits of web components. If I need a framework to write my web components, why not just pull in a different framework that skips the web component level completely and just outputs HTML/CSS directly? What is this intermediate step actually bringing me?
In theory it is completely an implementation detail, I agree. In practice, it's bloat. If every web component I use in my project might pull in a completely different framework behind the scenes (and worse: if those web components depend transitively on other web components that pull in yet more frameworks), then I now have to deal with all of those different frameworks. Each of them will load more bytes and make my page's startup time slower. Each of them will have their own state management systems. Each of them will have their own approach to templating. Each of them will behave subtly differently in practice.
Why bother when I can just write everything in a single framework?
Imagine 50 years ago: “Data passing seems inherently broken in Unix, because all processes must use strings for input and output. Such a model just can't be built on top of.”
As a matter of fact, Tcl/Tk has been doing exactly that since the 1990s. Of course, Tk has been "borrowed" by other languages, Python's tkinter is well-known. Any language using Tk widgets still has to input options in text form. Obviously that's not particularly difficult to accomplish.
You're right, it is just a method call from a class. Nothing interesting or new. And that's exactly why I like it! I like me FE code as boring, unimpressive and as simple as possible.
Presumably I've defined a .toString() method on w that will behave as I wish when implicitly invoked to perform this coercion.
If I haven't, then presumably I'll be satisfied with the inherited default behavior, which will probably look something like "<h1>[object Worker]</h1>".
If I care about this extremely contrived example case, in other words, I'll do something to handle it. If I don't, I won't. If I do, it's been easy for at least 25 years now; iirc .toString() was specified in ES3, which was published in March 2000.
If I want in the general case to append a child node to a parent (as here with the h1 as parent and the stringified interpolated value as child), I will in almost every case call parent.appendChild(child), where parent and child both implement Node, which is the parent class of Element. The result will correspond closely to the element tree which would be constructed by assigning a string like your example to some other element's innerHTML. (You are essentially using the browser DOM implementation as a templating engine. As sugar over a lot of createElement calls and piecewise tree construction, this isn't a terrible strategy! The JSX with which you're familiar is a more elaborate and more typesafe solution for essentially the same problem.)
Similarly, these references would be from the JS perspective a POJO with lots of seriously heavy implicit "render magic," so you can use them, as with any first-class Javascript value, as function arguments parallel to but a superset of what React does with its props. See the MDN documentation on Node.appendChild (and Node, Element, HTMLElement, etc) for more: https://developer.mozilla.org/en-US/docs/Web/API/Node
If I want to represent the state of a worker thread in the UI, a problem I first recall solving over a weekend in 2016, the way I do it will end up closely resembling the "MVC pattern," with the Worker instance as "model,"
the DOM element structure as "view," and a "controller" that takes a Worker and returns an element tree. Even if I'm using React to build the UI - which I have also been mostly doing for about as long - I am still going to handle this translation with a library function, even if my component actually does accept a Worker as a prop, which it actually very likely will since that will enable me to easily dispatch effects and update the UI on changes of worker state. I might define that "business logic" function alongside the component which uses it, in the same module. But React or vanilla, I won't put that logic in the UI rendering code, unless it is trivial property mapping and no more (unlikely in this case, since any interesting worker thread state updates will arrive via message events requiring the parent to keep track in some way.)
will just stringify the worker and pass that string to the `my-component`. To get the worker instance to be passed correctly, I'd need to do something like
So this isn't even a question about web workers, it's a question about how to prop-drill non-string/number data through multiple layers of web-components.
Tbh, I'm not sure there's a way for that. But why not just define a method in your target child component and pass the worker in there?
Yeah, I think the original question was a bit weirdly worded which made people focus on web workers rather than complex data in general.
You can use properties (as opposed to attributes) as I demonstrated, and you can use methods like you suggest, but these are both verbose and limited, and add an extra "the component has been created but the props haven't been fully passed" state to the component you're writing. Imagine a component with maybe five different props, all of which are complex objects that need to be passed by property. That's a lot of boilerplate to work with.
I showed earlier how it takes multiple lines and some fiddling with DOM to set a simple property with vanilla web components. Sure, if you're using a framework like lit, you have access to template binding, but at that point you might as well use an equivalent framework like SolidJS or Svelte which just skips the web component layer.
Every time I go back to give Web Components another 5 minutes, I hit this point where using lit or a lit-like would take a lot of the pain of the problems Web Components don't solve and have no planned solution for away.
But once I decide to cross the "no dependencies" line, using something like Preact + htm as a no-build solution would also take the most of the rest of the pain away, and solve many, many other problems Web Components have no solution and no planned solution for.
I'm late getting to this but someone emailed us to point out that your attempt at code formatting didn't quite work, so I fixed it, using the formatting markup documented here: https://news.ycombinator.com/formatdoc. Hope that's OK!
Well it's not a lie, it's how HTML and the DOM work. Attributes are strings, and what you write in HTML will be passed as attributes.
You do also have access to properties, but only in Javascript — you can't for example write something like `<my-custom-component date="new Date(2024, 02, 04)">`. That means that if you need to pass around complex data types, you need to either manipulate the DOM objects directly, or you need to include some sort of templating abstraction that will handle the property/attribute problem for you.
This is my main criticism of web components. At the simplest levels, they're not useful — you could build this website very easily without them, they aren't providing a particularly meaningful abstraction at this level of complexity. But at the more complex levels, they're not sufficient by themselves — there's no state management concept, there's no templating, there's not even much reactivity, other than the stuff you could do with native JS event emitters.
As far as I can tell, the best use-case for web components is microfrontends, which is a pretty useful use-case (much better than iframes), but it's very niche. Apart from that, I really don't see why you wouldn't just write normal Javascript without worrying about web components at all.
It is absolutely a lie, because web components can handle arbitrary data just at much as any framework.
You're holding web components to a higher standard here in expecting them to take arbitrary data in HTML when HTML itself doesn't support arbitrary data. Notably you can't assign arbitrary data to framework components from within HTML either, so how are web components any more limited?
The original comment was that "all HTML attrs must have string keys and values", which is completely true.
The point of web components is that they create normal HTML elements. So it makes sense to consider what the value of them being normal HTML elements is. You can write them directly in your HTML source code, for example. But if you do that, you only get access to attributes and not to properties, and therefore everything needs to be strings. Alternatively, you can treat them as DOM nodes in Javascript, at which point you get access to properties and can use non-string values, but now you've got to deal with the DOM API, which is verbose and imperative, and makes declarative templating difficult.
Yes, we could compare them to components from other frameworks, but that's honestly an absurd comparison. They're simply trying to do different things. Frameworks aren't trying to create HTML elements. They're trying to reactively template the DOM. It's just a completely different goal altogether. The comparison doesn't make sense.
The "old ways" are relevant again here. Just like in the old Progressive Enhancement era (the jQuery/Knockout era) to pass objects/arrays as attributes you use the special data- attributes and the `dataset` property. As the old ways suggest you probably still want to account for strings and serialize/deserialize via JSON for the most compatibility with things like static rendering, but many a jQuery script "upgraded" such things in-place.
State management is arguably one of the most important problems to solve. That's why we use React and Vue. You can very easily build complex user interfaces at scale with those frameworks. And you can even take web components along for the ride if you want to. They are partially overlapping solutions for different problems.
Just for anyone reading this and wondering what the dependency footprint of React is:
- React-DOM has one runtime dependency (a cooperative scheduler)
- React itself has no runtime dependencies
It's possible the poster above is referring to build time dependencies. This is harder to assess because there are several options. For example, if compiling JSX using TypeScript, this adds only one more dependency.
Question - why would you do this in current year? Is it that much more performant? I might be ignorant but frameworks seem to be the lingua franca for a reason - they make your life much easier to manage once set up!
Because of the ridiculous complexity in their setup and operation, their glacially slow performance if it is actually written in JavaScript and not a non-web platform language that compiles to native code, and their extreme volatility and instability/pace of deprecation.
The benchmarks I've seen actually show web components being slightly slower than the best frameworks/libraries.
The idea is: no build steps initially, minimal build steps later on, no dealing with a constant stream of CVEs in transitive dependencies, no slow down in CI/CD, much more readable stack traces and profiling graphs when investigating errors and performance, no massive node_modules folder, etc. Massive worlds of complexity and security holes and stupid janky bullshit all gone. This will probably also be easier to serve as part of the backend API and not require a separate container/app/service just running node.js and can probably just be served as static content, or at least the lack of Node build steps should make that more feasible.
It's a tradeoff some people want to make and others don't. There isn't a right and wrong answer.
Frameworks are fine when you just need to get a job done quickly. And they're ideal when you're in a typical corporate code factory with average turnover, and for the same reasons Java is ideal there.
React is the new Java.
But when you need something the framework can't provide, good luck. Yes, high performance is typically one of those things. But a well engineered design is almost always another, costing maintainability and flexibility.
This is why you almost always see frameworks slow to a crawl at a certain point in terms of fixing bugs, adding features, or improving performance. I'd guess React did this around like 2019 or so.
Overly hated on and conflated with frameworks, yes.
React requires very little from you. Even less if you don't want to use JSX. But because Facebook pushes puzzlingly heavy starter kits, everyone thinks React needs routers or NextJS. But what barebones React is, at the end of the day, is hardly what I'd call a framework, and is suitable for little JS "islands."
For example - I have a fairly complex app, at least for a side project, but so far I managed to keep everything without a single external dependecy nor any build tool. Now I have to convert it all to react and I'm not very happy about that, I will have to add a ton of tooling, and what's most important for me, I won't be able to make any changes without deploying the tooling beforehand.
Well, one nice thing about doing things this way is that it'll still be as viable in five years as it is today.
I'm sitting on two UIs at work that nobody can really do anything with, because the cutting-edge, mainstream-acceptable frameworks at the time they are built in are now deprecated, very difficult to even reconstruct with all the library motion, and as a result, effectively frozen because we can't practically tweak them without someone dedicating a week just to put all the pieces back together enough to rebuild the system... and then that week of work has to largely be done again in a year if we have to tweak it again.
Meanwhile the little website I wrote with just vanilla HTML, CSS, & JS is chugging along, and we can and have pushed in the occasional tweak to it without it blowing up the world or requiring someone to spend a week reconstructing some weird specific environment.
I'm actually not against web frameworks in the general sense, but they do need to pull their weight and I think a lot of people underestimate their long-term expense for a lot of sites. Doing a little bit of JS to run a couple of "fetch" commands is not that difficult. It is true that if you start building a large enough site that you will eventually reconstruct your own framework out of necessity, and it'll be inferior to React, but there's a lot of sites under that "large enough" threshold.
Perhaps the best way to think about it is that this is the "standard library" framework that ships in the browsers, and it's worth knowing about it so that you can analyze when it is sufficient for your needs. Because if it is sufficient, it has a lot of advantages to it. If it isn't, then by all means go and get something else... again, I'm definitely not in the camp of "frameworks have no utility". But this should always be part of your analysis because of its unique benefits it has that no other framework has, like its 0KB initial overhead and generally unbeatable performance (because all the other frameworks are built on top of this one).
Mostly for the virtue signaling. There's something to be said for going with the fundamentals, but people who loudly preach fundamentals tend to be, well...
Frameworks can help in many cases, especially for complex or high-scale apps. But in simple CRUD apps, particularly in consulting environments, they often add more complexity than value.
I've seen this play out repeatedly. A company needs a basic CRUD system. Consultancy A brings in designers who produce “wireframes” (usually full-featured eye candy) and UX-centric “journeys.” To justify its bloated fees, the consultancy builds something super-slick using frameworks to match the designs. But once the budget runs out, the customer struggles to maintain it. Eventually, the app becomes unmanageable.
So the consultancy sends in a designer again to produce new mockups and “journeys.” The cycle repeats, this time with another framework.
As a react dev I find this fascinating - in the same way I was fascinated by the foraging walk I went on the other day - but was SO HAPPY that supermarkets exist when I saw how much effort it is.
Although I do think there is merit to "light" frameworks such as Astro, with its scoped styling and better component syntax. But at the same time, independence is also important.
I started something similar with https://webdev.bryanhogan.com/ which focuses on writing good and scalable HTML and CSS.
I am not sold on web-components yet. Especially now with @scoped and import{type:css}, I think there's still a lot of merit to rendering an element statically, shipping it, and updating it dynamically via modern JS. I'm not sold on how people typically do that, and I think we should keep trying to innovate outside of the typical frameworks like React/Svelte, but I definitely don't see any part of web-components being useful to any type of site I run (and I run several disparate types).
Web components provide a clean abstraction boundary. You can add additional methods to your own tags which can encapsulate the logic for updating the data in the component.
You can use the shadow DOM outside of custom elements, and can use custom elements without a shadow DOM.
Edit: I just added a shadow root to a div in your comment, saving its content beforehand, moved its content inside the shadow root, and added a style with * { all: initial } and your comment text got Times New Roman.
Web Components don't solve the problems I do have and add new problems I don't want.
Many of the 25 mentions of Shadow DOM in the Components Page and 14 mentions of it in the Styling page are about solving problems you now only have because the site recommended you use Shadow DOM, and the problem Shadow DOM itself is _trying_ to solve is one I don't have in components written specifically for my app, which will only be used in my app.
Hard agree, from practical experience also. One thing will push you towards shadow dom (slots, for example) then ten things will push you back towards light dom. I don't exactly understand what the spec is aiming to solve with the way things currently are. But I do appreciate no build process.
Given the way most templates about Web Components are going it feels like a dirty secret that you don't need to use Shadow DOM at all when building Web Components and that it actually feels nice to build Web Components without it.
I think it’s time to go back to Unobtrusive JavaScript. What is needed for this are lightweight libraries or practices you can code yourself. HTMX is lightweight which is nice but it’s like script tags. I would rather the urls and methods go in plain HTML and stuff like hx-target be determined by JavaScript, using data- attributes if needed. That way all the unused HTMX features aren’t included.
You can use shadow-dom without using web-component. web-component and shadow-dom are orthogonal to eachother:
* web-component is a way to attache javascript to certain elements. There are other ways to do it, but sometime this way feel cleaner, like when you do server-side rendering and not using any javascript framework.
* shadow-dom is a way to organize your styles. As you said there are other ways to do it, but I find it useful because it offers full isolation, and is compatible with browsers 3 years back.
Other than for learning purposes or very lean projects, you'll de-framework yourself just so that you have to spend extra time rebuilding it instead of focusing on the essence of your project
This is the common wisdom about frameworks but I think it ignores the wastage & other side effects around frameworks and the things they make easy or difficult. Many of the decisions made in any framework will represent guardrails for things that don’t apply to you specifically.
I know you’ll “write your own framework” but maybe that’s optimal in some situations - more than we might give credit to at the moment.
I really wish web components weren't promoted as a "framework alternative" and more of a standardization of custom display components. Frameworks like enhance.dev and lit.dev are good examples of this.
> The most basic structuring technique is separating CSS into multiple files. We could add all those files in order as \<link> tags into the index.html but this quickly becomes unworkable if we have multiple HTML pages. Instead it is better to import them into the index.css (via @import)
You'll eventually need \<link> anyway for preloads, especially with web fonts, since that's the only way to prevent FOUC. Personally I lean on build steps to solve this. I don't like bundlers or frameworks, but I have grown accustomed to custom-building.
I don't find this convincing. For one, many sites don't need web fonts to begin with. For two, the sites that do can use `font-display` or, even better, just let the browser figure it out. Browser developers have spent way more time on these problems than any one of us individually ever will and more often than not, the behavior you get out of the box is already pretty fine.
As a user of websites, I definitely notice when a website uses web fonts and relies on font-display. Preloading them is the only way to avoid jarring changes to the layout. Even if the changes are relatively small, they're very jarring. I won't do that to users of my sites. It's not hard to take care of properly.
That's a very subjective take on what properly means in this context. Many would argue that serving the content is the main thing that matters to your users, and if your font takes so long to load that you need to deal with it separately, it would be better to not do that to begin with. To put another way, as a fellow user of websites, I would much rather read what's written than look at a blank page while some marginally different version of Helvetica is fetched in the background.
That's the point of preloads. You don't need to choose. As soon as the HTML is loaded, the font is ready. You see the HTML immediately (about 10-20ms) with the web font. Win win.
I work for about 2k users, they do not give a shit about reactivity... build a monolith, make it comfy, embrace page refresh (nobody gives a fuck about that in the real world), and get shit done.
I have seen more broken SPAs than MPAs, by far. Ironic, considering SPAs are supposed to improve conversion rates and user experience. Even from big companies with no excuse - Reddit is almost unusable on phones, X was straight up broken for a month straight with image loading on mobile.
If you’re writing an SPA, and it isn’t Twitter or a content consumption platform, and it isn’t necessary to be API-driven, seriously just stop. You’re not clever, you’re not improving the experience, you’re only appealing to the tastes of other programmers. If billion-dollar companies can’t get them working perfectly, you certainly won’t.
We created a generation of developers that AIM to over-engineer requirements... and we also came up with extremely pervasive frameworks to go with it... My firm cannot hire people with no React experience... people REALLY only know how to build cruft these days...
I have no React, Vue, or Angular experience. My websites were built with Livewire, some HTMX (basically Hotwire in the Rails world, server rendered HTML partials; or maybe Blazor SSR in the .NET world). I use Tailwind and a Laravel backend, but have some experience with C#.
If you think that’s interesting, send me your firm’s URL, I’ll consider applying. (Edit: or really anyone reading this who is interested - government of a foreign nation outside the US is not viable, unfortunately.)
As a Rails developer with no desire to work in a React codebase, I'm not qualified for about 50-60% of the Rails jobs postings. My lastest full time was at Shopify where I said over an over that I was Ruby only and not interested in a React position only to be told a few months in I needed to know React to get promoted. It is exhausting.
I have given up on doing frontend work for the time being, because of this crap. I used to do full stack with modern JS, TS, CSS, HTML and whatnot, but then someone made it all go to shit by advertising for NextJS and React, while there was zero interactivity on the whole platform, except for a couple of checkboxes. A few years later, there still isn't much. Some page transitions for when things happen in the backend. I told them in the beginning, that there is not much interactive stuff, but they all got flashed by some one minute low effort Material Design shit, and the idea of the whole thing being "modern" and hiring more React devs. So I stepped away from that while frontend part and let them dig their own hole.
Moving a navigation/menu from one app to another takes 3 people 2-3 weeks by now. Changing the "router" to update the TS version is just as time consuming. Things that would have taken 1 day max. take now 2-3 weeks. That is 1/14th of the productivity and people get paid for that, more than I did. Oh and did I mention the menu responsiveness was broken for months at a certain viewport width? I did report it, but apparently it was so hard to fix, that it could not be done in a quiet hour, so it took months laying around in the queue of things to fix.
Might be a bit of a selection bias though. I certainly remember a lot of crappy MPAs before SPAs got big. The crappines just moved to SPAs as they became mainstream. Overall I agree that MPAs are better default, though, good SPAs are hard to build.
Part of the complaints about MPAs originally was that navigating all the different pages was slow, because loading new pages was slow. But plenty of today's SPAs deliver content even slower and the user is staring at a spinner for lengthy stretches. The key is quick, efficient server responses, whether using SPA or MPA approaches.
Yeah. In theory SPAs should be faster, but in practice rendering/sending the whole template is not as bad. And as you mention, both can be slow, due to the non-cached API/DB call, so...
Even in theory, producing json is just typically slower than producing HTML.
It seems unintuitive, but traversing an object tree using reflection to generate json is just slower than using an HTML template, which is probably a rope data structure.
I guess the rendering itself is pretty much the same for both SPAs and MPAs, since in the end it can be pretty much the same markup, but the SPA is also at a disadvantage here because it has to combine template/components + JSON to generate the HTML :/
That reminds me of when I first benchmarked a Rails app and noticed that JSON rendering was significantly slower than the remote database call. No lie, jbuilder was taking about 80% of the request time for about 90% of all endpoints.
I believe it’s finally enabled by default in nightly builds, so it should be standard soon. I may be wrong and it may have been scoped css enabled, but both are available by feature flags on nightly and plan to be enabled by default by the end of the year.
This just means that user doesn't get the animation tho, right? The actual page transition still happens, so you get graceful fallback without the need to do anything special.
This feels like bringing the annoying transitions people used to use between slides in PowerPoint to the web. There's nothing smooth about the transition in the linked demo, it's quite jarring.
Also, it’s a mess separating stuff between react and the server, especially when building with express/node as the backend and the whole codebase together
It’s such a pain having clear separation in development where everything runs off of the react server by default, but then it won’t when deploying, so either you end up doing all sorts of weird stuff or you need to be building and running production locally constantly, thus defeating the whole convenience of having a dev server that can hot reload the changes
Sure, but the runtime is not exactly designed to guide you to the best way to do this. Hence the prevalence of frameworks to paper over the runtime.
I openly admit that I'd rather learn a new framework than touch anything to do with figuring out how the browser is intended to behave in practice. What an abomination and insult to humanity.
Edit: holy shit y'all do not like the earnest approach to technology
Something like that. Doesn't get much easier. Gone are the days of browser inconsistencies, at least of you stick to "Baseline Widely available" APIs which is now prominently displayed on MDN.
No-framework web tinkerer here. If I had a nickel for every second of my life I've spent typing document.getElementById, I'd be able to afford new fingers. Should've been renamed to getId() and put in global scope two decades ago, if not three. At least querySelector() is a few characters shorter, but I always feel bad using such an alarmingly overdesigned tool for anything trivial.
You don’t have to call getElementById or querySelector on document. You can narrow the search by starting at a specific node, just most people default into document as it’s already a global.
If I'm just adding sprinkles of interactivity to a statically-rendered page for something that vanilla is good enough for (i.e. minimal-to-no display logic), I use the expando giving an element an `id` adds to `window`:
That's a code smell. If you're creating the element you ought to already know about it. If you're not creating the element you should inventory them all at once as the page (or component) loads.
"Nobody knows how to do anything and shit is inefficient and slow and why does all of this software suck" - customers of things built using frameworks but no understanding of the system being abstracted
I guess openly admitting that you refuse to learn how your platform actually works is an "earnest approach", of a sort, but so is admitting that you routinely leave grocery carts in the parking lot and don't see a problem with it.
Theres even an insane amount of documentation on the web about the web. MDN is very well maintained to boot. Im not as versed as some on front end web, but I recognize that I can slice through a lot of front end stuff by just referring to MDN.
I have a few sites that aren’t that complex, and I use JS to run a PHP file and populate the results in a div. It appears reactive, but it’s dead simple.
I get that huge apps probably need a lot more than that, but so many people these days reach for heavy frameworks for everything, because it’s all they know.
The nice thing about the plain "vanilla" approach is it can be used to enhance a more traditional SSR-rendered site. And it doesn't need a complete rewrite in React or whatever.
The author of this article blog is describing some more advanced SPA-like scenarios, but those are completely optional
As a counterpoint, many systems that were originally implemented as native desktop applications have since been migrated to the web. The motivation for this shift is not particularly strong from a technical standpoint, but it is a practical one: deploying native applications is simply too costly.
The web finally provides a widespread standard for deploying applications inexpensively. Unfortunately, the technology used to build user interfaces for the web remains somewhat mediocre.
It’s unfortunate that history took some wrong turns with X11, Java, Flash, Silverlight, .NET, and countless other alternatives that I haven’t personally lived through.
Hopefully, someone will eventually find a way to make developing web applications comfortable and the broader community will embrace it.
> deploying native applications is simply too costly.
I do not understand why people hold this impression, especially in corporate environments.
Windows supports both system and per-user deployments; the latter so you don't even need administrator rights. And with Intune, deployments can be pulled or pushed.
Many desktop applications are written in .Net so you don't even need to install the runtime because it's preinstalled on the operating system.
Even ClickOnce deployments -- which you can deploy on the web or on a file share -- pretty much make deployments painless.
EDIT: For the naysayers: please then explain to me why Steam is so successful at deploying large games on multiple platforms?
That sounds nice and it probably works fine if you're targeting a single business running Windows, but targeting Mac, Windows and Linux remains more difficult, no?
And is there even a guarantee that your deploy will be rolled out in X minutes?
Version skew remains one of the biggest sources of catastrophic bugs at the company I work for, and that's not even taking into client app ver, just skew between the several services we have. Once you add client app ver, we have to support things for 3 years.
At my one-person company I just do a Kubernetes deploy, it goes out in a couple minutes and everyone has the latest ver whether they like it or not. I don't have the resources to maintain a dozen versions simultaneously.
In large corporate environments I agree but small companies still mostly don’t have central management of end user computers. They order a computer from Dell and use it as delivered. Much easier to just access everything via a browser that way.
Even the most friction-free ClickOnce deployment is going to be more of a deployment hassle than "hey, users, you know how you go to https://subdomain.local-intranet/place to add or subtract items from the inventory database? Well, continue doing that".
The webapp doesn't care if someone's machine was down overnight or if the paranoid lady in design managed to install some local "antivirus" which blocked the updated rollout or if the manager of sales has some unique setting on his machine which for some inscrutable reason does silly things to the new version. If their web browser works, the inventory database works for them, and they're on the latest version. If their web browser doesn't work, well, your support teams would have had to eventually take care of that anyway.
The web browser is not some magic tool that is always guaranteed to work. Group policy alone can wreck total havoc on web apps on all the major browsers.
Some people should probably only be given thin clients, because they are too inept to be allowed to handle anything else.
Not sure yet how to solve this problem on the Internet yet though. How can we prevent uninformed masses from creating incentives for businesses, that turn the web into a dystopia?
Here's a good example: I used Weylus which turns any touch device (phone, tablet etc) into a drawing tablet + screen mirror. It can be used to turn your iPad into a second monitor or as a touch device for your laptop.
Weylus gives you a URL that you can visit on the device and instantly use it. Try doing that with native apps. They'd need native apps for Windows, Linux, Mac, iOS, Android... get them on the app stores too, support all the different Linux distros... or just a single URL that works instantly anywhere.
Steam works for the same reason the App Store works, it targets mostly a single platform (Windows) and all dependencies are bundled in. The Steam client itself is a web app running on the chrome engine, though.
Of course. I was strictly refering to .NET preinstalled in Windows as per the comment I replied to, which I believe only applies to Framework 4.8.
Although, on re-read, maybe they meant there's a good chance another application already installed it? This I wouldn't agree with, as applications often insist on installing different versions of the system-wide runtime, even for the same major version.
There’s a hidden cost in web applications as well: you lose the value of the operating systems application language. Every website and thus electron app suffers from this. There’s no standard place for settings, buttons and windows don’t behave normally. There’s a lot of value in native apps in usability just in it sharing the same UX language as the operating system. Sadly this is mostly dead for new applications.
We have 2 main products: a SaaS and a desktop app (1mln+ users combined). It's a pain in the ass to support the desktop app:
- many people refuse to upgrade for various reasons so we have to support ancient versions (especially for important clients), for stuff like license activations etc.
- various misconfigurations (or OS updates) on Windows can make the app suddenly crash and burn
- and you waste time investigating the problem. My favorite recent bug: the app works OK everywhere except on some Japanese systems where it just crashes with access violation (see the next bullet point)
- debugging is hard, because you don't have immediate access to the machine where the bug triggered
- originally it was built 100% for Windows but now we have people asking for a MacOS port and it's a lot of work
- people crack our protection 1 day after release and can use it without paying
SaaS has none of those problems:
- people are used to the fact that SaaS applications are regularly updated and can't refuse to upgrade
- modern browsers are already cross-platform
- browser incompatibilities are easier to resolve
- you debug your own, well-known environment
- if someone doesn't play by the rules, you just restrict access with 1 button
You could of course also make your desktop app auto update without offering a way to refuse. Or you could make it display an error, if the user accesses it without being at the newest version, and block all further interaction. Those are considered impolite, but it seems you are doing it anyway in your web app already.
Building a game for multiple platforms for steam is way more work than building a single web app. Builting the game often requires unique settings for each platform, machines for each target platform, testing on each target platform, dealing with bugs on each target platform. Getting noterized/certified on each
> EDIT: For the naysayers: please then explain to me why Steam is so successful at deploying large games on multiple platforms?
How many games are multi-platform on steam? Checking the top 20 current most played games, 14 of them are windows only. If it's so easy to be multi-platform, why would 14 of the top 20 games not be multi-platform? Oh, it's because it's NOT EASY. Conversely, web apps are cross platform by default.
Only 2 of the top 20 games supported 3 platforms (windows, mac, steam-deck). 1 was windows+steam-deck, 3 were windows+mac
> please then explain to me why Steam is so successful at deploying large games on multiple platforms?
if you look into the support forums on steam for any random game you'll find lots of complaints about stability and crashes, many of which are likely to be esoteric system-specific problems.
I love ClickOnce and am amazed that it never got that popular. Installs and updates are seamless.
I wrote an inventory management program for my father's hazardous waste company. Used .net mvc as the backend, WPF as the frontend. WPF sucks in many ways, but I got it working and have had zero complaints.
I built that program almost 20 years ago. Until last year I spend maybe 5-6 hours total in maintenance, mostly ssl cert updates. Let that sink in.
I get the impression this is said by people who observe large enterprises or don't have good device management. I work for a big company that deploys proper MDM to our Macs and PCs, and as long as the application is packaged correctly, they sure can push stuff out fast and without user intervention, including killing a running process if they so choose. Making an app that packages well is also hard, but that's not on those who push them to environments.
Nothing wrong with Flash and Silverlight except each being controlled by a single company. I liked those technologies. Adobe Flex was very nice to program in and use for it's time.
My experience circa. 2008/9 was it was fine (used it on a commercial app in lieu of good enough web standards for the featureset). It was fast and reactive for an app-like experience.
Games were made in flash so it can't be that slow.
Maybe slow for time to load. I think we got that down a bit and this wasn't to render content but a utility for a signed up user.
Flash was a lot of things, but also, at the same time, neither of these things. (You could come across poorly coded and thus poorly performing apps, but that wasn’t the standard).
Modern day SPAs are far, far worse offenders when it comes to smothering resources.
Nothing got my old iMac G5 whipped into a frenzy like loading a page that had Flash on it somewhere. I’m not kidding when I say that there were many areas in World of Warcraft, a full-fat seamless open world 3D MMORPG, that didn’t make its fans as angry as Flash could manage to.
I was so happy when it finally started to disappear. That kind of sheer disregard for my system resources is inexcusable.
It probably could’ve been great, but unfortunately such a thing would’ve been unlikely at best with Flash being solely controlled by Adobe. Not only does that company have a disinclination towards optimization that persists to this day, but with there having been no alternative implementations of Flash, there was no possibility of other organizations taking up that torch or for there to be competition between implementations driving things forward.
The flash player leaked memory. The longer-running the app, the more noticeable it was. I believe this is why Adobe Air (flash player packaged as deliverable) failed.
As for the speed of the flash player itself it was quite good.
They were resource intensive (though probably less so than yr average React based site these days) but Flash, especially post AS3, was an order of magnitude or two faster than JS + html/svg/canvas at the time. It was years after the death of Flash that standards based tech finally caught up.
I think that using browser as the way to, essentially, deliver desktop LOB apps to the users seamlessly, updates and all, makes perfect sense. Writing those apps in HTML/CSS/JS, not so much - it's forced on us because that's the only stack that browsers have historically supported, but even with all the app-centric additions to HTML over the past two decades, it's clearly not designed for them first and it shows.
I hope that, in the long term, wasm and canvas (or something similar) will gradually take over this niche. Frameworks like Avalonia already let you write a desktop app and then surface it in the browser, today. This stuff is still rough around the edges, particularly wrt accessibility, but there's nothing unsolvable there in principle, it just needs time and effort (and money).
I’m making a web game and using html, css and vanilla javascript for the UI is fine. I have transitions, sounds and everything is very fast without any of the bloat. The actual game itself is in canvas but everything else is standard web stuff.
Not going to lie, that's a pretty out of touch opinion in the current decade, where most software feels an order of magnitude slower and less reactive than a mechanical device made 120 years ago.
Most of that software are bloated SPAs that somehow manage to be slower than a complete page reload of any website or app, that is rendered server side using any traditional web framework statically rendering HTML templates.
And adTech. I’ve been a happy user or the local gumtree [0] that always worked fine with my 9yo iPhone… until last year: the business model seems to have changed as they added in-list advertisement and I can only scroll the products list until the first ad wrapper shows up. Then the UI freeze and never gets back to life. I don’t even see the advertisements itself.
Edit: just tried it again and seems they fixed it! The ads stays in loading state forever but the site is usable again. Wonder if they did something on their side or if they changed ad provider.
People looking to get shit done don't really care but, when they're just mindlessly clicking, they'll hit the back button to the main feed way before the time it takes to fetch a modern framework if your site happens to be the first they hit with that particular version from the CDN.
Still the case in most Asian countries where UIs are all Craigslist alike and UX is just shit. People just got use to it. Apparently westerns willing to pay a premium for better UX. It's a culture gap.
Side note but as a buyer looking to buy used tools from locals, Craigslist's UX could not be better. I just started using it recently (after forgetting about it for a decade). Absolutely the opposite of shit.
Though I think maybe if one is using it for a different purpose, like looking for apartments or roommates then that's probably shit.
Page refresh between pages is ok. Lag when updating a form based on your inputs isn't. Frontend UI is like a bigger monitor or faster PC - you may not have known what you were missing, but once you've experienced it it's very frustrating to go back to the clunky old thing.
It's really irritating for your users. They might not consciously be able to point it out as the cause of their irritation, but they'll like your app a lot less.
My business doesn't use React anymore, and I'm so happy I don't have to do pointless maintenance.
A side note, included in my repository: you update your element's innerHtml from the constructor, not from the connectedCallback. MDN and the web standards seem to be inconsistent on this, and elsewhere people write about it, too.
People talk a lot about data and binding, etc. I think it's weird, it's like people have forgotten how to just use setters. You can call a render() method from a setter, and it does the same thing WebKit et al do when you call an internal setter on an HTML element.
I don't see the value in these frameworks anymore.
I support the general idea here but just because something is in a browser doesn't mean it's a good formalism.
Notably, Web Components. They're fantastic for distributing components - after all, a Web Component will work in every framework (even React, the IE of frameworks, finally added support), or even in vanilla HTML. So you can build a component once and everybody can use it. It's fantastic.
But for internally composing a web application, Web Components are simply awful. They add nearly no helpful features that vanilla JS doesn't already have, and they add bucketloads of extra complexity. You got attributes and properties, and they're mostly the same but kinda not always and oh by the way, attributes can only be strings so good luck keeping that in sync. You got shadow DOM which is great for distribution but super restrictive if you want any sort of consistent global styling (and a total pain in devtools, especially once you go 10 levels deep). You can turn that off, of course, but you gotta know to do that. And plenty more quirks like this. It's just.. It makes lots of easy things 5x harder and 1 hard thing 1.5x easier. Totally not worth it!
If you really want to not use a big clunky framework, but at the same time you have a complex enough app that composition and encapsulation is important, you'd be much better off just making your own object hierarchy (ie without extending HTMLElement), skipping all that awkward web component luggage and solely doing what they do best (tie an object to an element).
Or, better yet, get over yourself and just use a framework that does this for you. Your future self will thank you (and your colleagues even more so).
ps. rant time: If only the web browser people had gotten off their high horse and not proposed the word "Web Components"! If they would've just been named "Custom Elements", which is what they are, then we wouldn't have had 5+ years of people mistaking them for a React competitor.
I remember when web components first came out and there was some hype around them, and just being really confused on what they're actually good for. I think it's really telling that since web components came out there's never been a popular framework, website, or company that has heavily leveraged them.
I haven't started using Web Components, but I was under the impression that libraries like Lit address most of the issues you mentioned for devs who don't want to write their own minimal base class, no?
Sure but this page is about not using a framework. Once you're on board with using a framework like Lit, you might as well use Preact or Svelte or a similarly lightweight framework. The "web component" angle adds no value if it's all internal to your app.
Lit is amazing though. It's fast, lean, and easy to learn. In fact, to my experience, the only things about it that are un-ergonomic, are due to the fact that it's built around web components. Lit without web components would be so much better (again, except if you're building something to be distributed to other programmers on any framework). It wouldn't have a single global registry of components, it wouldn't have that attribute mess, and I bet it'd not need a compiler at all (it doesn't need it now either, but is easier/nicer with it).
> Sure but this page is about not using a framework.
Fair enough, but the way I read TFA, it doesn't dissuade developers from using tiny convenience libraries that leverage native browser capabilities. Based on your pushback, it sounds like my perception that Lit is mostly a convenient base class for Web Components is very incorrect. I'll dig into that more, thanks!
> it sounds like my perception that Lit is mostly a convenient base class for Web Components is very incorrect.
It has custom syntax, custom directives that look like regular JS functions but cannot be used like regular functions, a custom compiler in the works etc. etc.
They will keep telling you it just a small library and very vanilla though.
And they're right! IMO Lit is a marvel of engineering. I think the goal they set themselves (make it easier to build an entire app out of web components) is silly, but given that goal, they hit a total homerun. It's fast, the compiler is very optional (not using it just means a bit more boilerplate around attributes etc - it's not like using React without a JSX compiler or something), lit-html is a genius alternative to virtual DOMs, etc. The custom html syntax, IMO, is super useful too (eg it lets you workaround The Attribute Mess by passing data straight to properties, as you would in any sane non-web-component framework). And it's a lot closer to regular HTML than eg React's custom HTML syntax (JSX).
> lit-html is a genius alternative to virtual DOMs, etc
It's a haphazard solution that they now fight against with "directives" and even a custom compiler "for when initial render needs to be fast". It's not bad, but it's far from genius. And honestly, the only reason it works is that browsers have spent ungodly amounts of time optimizing working with strings and making innerHtml fast.
Additionally, it's weird to ask for "close to html" in a 100% Javascript-driven library/framework.
As for "etc.", I don't even know what etc. stands for. lit is busy re-implementing all the things all other frameworks have had for years. Including signals, SSR etc.
The classMap must be the only expression in the class attribute, but it can be combined with static values
--- end quote ---
So now you have to figure out which attribute this is called from, whether this particular call is allowed in this attribute etc.
So what they do is they parse (with regexes) their "close to HTML" code into a structure not dissimilar to React's, figure all this stuff out, reassemble actual HTML and dump it to the DOM
I do know what you specifically mean when you say that, but… _all_ libraries are leveraging native browser capabilities, even ones which implement a better component model than Web Components.
The irony is: I wrote a bunch of small custom elements [0][1] that do one thing and I don't use Lit for that, because Lit is still overhead. The litte bit of boilerplate overhead of Web Components, I simply wrote by hand.
Based on the JS Framework Benchmarks (so caveats apply), an app built with lit-html (i.e. just the HTML templating part, as I understand it) is about the same size as SolidJS, and an app built with lit (i.e. the full framework) is about the same size as Svelte or Preact, and at a similar order of magnitude to Vue or Mithril.
So at least in terms of minimal bases, all of these frameworks are much of a muchness.
> then we wouldn't have had 5+ years of people mistaking them for a React competitor.
The browser people literally promoted them as a React alternative. Then their goals and role changed every year, and now they are again promoted as an alternative
Yeah what a waste of collective brainspace that was eh. If they had promoted them as "custom elements are the best way to distribute components!" then I bet they'd have been much more widely embraced by now, by merit of not overselling them.
I really agree with you. Custom elements are a great way to distribute primitives. They start creating friction when trying to actually compose applications.
Perhaps my brain has been addled by a decade of React but as the examples became more advanced, they just looked a lot noiser and more complex compared to JSX or Svelte components.
Very nice! I wish this was the world we lived in. I'm from the before times, when W3C stuff was all we had, and it was miserable because it was so immature, and we hired people who "knew jQuery, but not JS". But if I'm being honest post query selector frameworks don't have a strong cost benefit argument - testing frameworks notwithstanding, which are quite lovely.
I run sites that serve hundreds of millions per day and we pour a ton of resources into these projects. We're trapped in a framework (react) prison of our own creation. All failures are those of complexly. Highly coupled state machines with hacked, weaved, minified, compiled, transpiled, shmanzpiled etc. into unreadable goop in production. Yes I know source maps, but only when needed, and they are yet another layer of complexity that can break - and they do. How I long for the good old days before frameworks.
Perhaps nostalgia and the principle of KISS (and a few others) is clouding my judgement here, after all, frameworks are made for a reason. But it's difficult to imagine a new engineer having any more difficulty with vanilla than learning framework after framework.
It's a popular non-netflix/google video streaming app that you've maybe heard of. HTML5 apps/sites/whatever are just part of our supported clients. All clients are supported by a largish SOA. All of the HTML clients are indeed sites, SPAs on a CDN to be more specific, and not "apps" but this is the sickly nomenclature our industry has adopted. But I really should have called them sites if I want to motivate others to do the same, thanks for the correction.
>Perhaps nostalgia and the principle of KISS (and a few others) is clouding my judgement here, after all, frameworks are made for a reason. But it's difficult to imagine a new engineer having any more difficulty with vanilla than learning framework after framework.
I feel the same way. React and Angular (well an earlier version of Angular) were made prior to ES2015 being mainstream, so I do think they made sense to use when they were initially created. Since then, I've become burned out from the constant churn of new frontend frameworks to learn. Even within the world of React, there's different ways of writing components, and different state managers.
I wanted to refute the "the constant churn of new frontend frameworks to learn". If you just stuck with React since 2015, they've only had 4 major versions since then and every ver they deprecate only a few things and then you have a full release cycle to migrate to the new hot thing. It's probably the best upgrade paths of any of the libs I work with.
But you're not wrong about there being many ways to write components and manage state.
And RSC is a mess. But thankfully you can keep pretending that doesn't exist.
> I wanted to refute the "the constant churn of new frontend frameworks to learn". If you just stuck with React since 2015, they've only had 4 major versions since then and every ver they deprecate only a few things and then you have a full release cycle to migrate to the new hot thing.
Contrast that with non-framework JS/HTML, where _you_ decide how long it lives and how often you need to upgrade (or not). Having to rejigger a web app every 2-3 years because someone outside of your organization changes something is not only unappealing, but it's horribly expensive for large-scale businesses and possibly prohibitively expensive for small-scale businesses or solo developers.
It happened to me with a personal project, I abandoned it for about 2 years and one day I decided to take it up again to add some features and when I did npm install I almost died.
I'm also from the before times, and still think one of the major issues with all of this is that we've decided to build a global application ecosystem by hacking stuff on top of a document format.
HTML was supposed to just a slight markup layer to make it easier to transit and render text documents, likewise that's all HTTP was designed for. The ratio of text-to-markup should be fairly high (I'm sure today it's less than 1). But for some reason (probably the initial ease of publishing globally) we decided that the future of application development should be to entirely reinvent GUIs to be built on top of this layer. If you look under the hood at what React is doing, we just have decades of hacks and tricks well organized to create the illusion that this is a rational way to create UIs.
Imagine a world where we decided we wanted to create applications by hacking Excel documents and Visual Basic (being from the before times, I had seen attempts at this), or have every app be a PDF file making clever use of PostScript? When one remembers how ridiculous it is to attempt to do what we have collectively done, it's not too surprising that a website can require megabytes of JS to render properly and, more importantly, to allow reasonable development processes allowing for some organization of the code base.
Yes, making UI’s is not a new problem but building on top of the DOM/HTML as the backbone is.
I too am from the before times where I guess we built essentially our own frameworks to handle own unique issues and take security into our own hands (verses have to trust external libraries and external resources….)
I sadly laugh when I hear 20+ years late people are still fighting back button navigation issues. I still see sites that can’t handle double posts correctly or recovery gracefully when post responses fail/timeout.
I’m out of the game now but for all the benefits of the web it’s been haves to death to support stuff the underlying infrastructure was nit designed for.
Look at WPF (or its more modern incarnations like Avalonia or Uno) for a decent example of what a GUI framework designed for desktop apps from the get go can look like.
Things like these haven't taken over the world because they didn't have the ease of app delivery that browsers provide, and attempts to bolt them onto browsers (Silverlight etc) didn't work out because they didn't work out of the box for most end users.
These days though we have enough bits and pieces directly in the browser (wasm, canvas, WebGL etc) to recreate something like Silverlight that "just works" in any modern browser. Take a look at https://eremex.github.io/controls-demo/ for an example of what's possible.
Yes, my first GUI apps were about 20 years ago in visual basic. It was far easier than laying out webpages (assuming you're targeting desktop users). It's just far harder to get users to download and run something (and should be). But the browser's layout system (the DOM) has 0 to do with that, there is nothing but inertia locking us into that.
Desktop apps have had superior UIs compared to the web for decades, and are still superior today. The Web is a terrible application platform which only persists because it's very easy to distribute to users.
Yup, the web is a thoroughly mediocre application platform†, but the world’s best application distribution platform.
†I know this claim will rub some people the wrong way, but if you compare the capabilities of web tooling to build rich application UIs against desktop app tooling of even 20-30 years ago, there’s no comparison. The web is still primitive, and while JS and CSS are improving at a good pace, HTML is almost frozen in carbonite.
Not really - there are pretty big escape hatches - you can do pretty much anything in canvas, custom elements allows you to define your own elements with their own behaviour.
I'd say the problem is the opposite - one of the reasons desktop apps from 20-30 years ago ( say MacOS 7 ) where great from a user perspective is pretty much all apps looked and worked in the same way, using the same UI toolkit and the same UI principals. And from a developer perspective - a lot of the key decisions had already been made for you.
The web of today is a zoo of UI styles and interaction modes.
The problem isn't so much a lack of innovation or possibilities, but perhaps rather the opposite.
It's both, really. HTML makes it really easy to do "corporate branded" fancy buttons, but you still have to jump through hoops to do something that could be done with a database and the stock data grid widget in <10 lines of code in VB or Delphi.
You also might not need any access control, network traffic security, cross platform deployment, instant install, evergreen updating, trivial UI integration ( links ) etc etc.
If you really want something simple you could use Excel, Access or Filemaker as a front end.
I agree life has got more complex - and in some cases unnecessarily so - case in point it's becoming increasingly hard to write web apps without SSL - even if you don't need it.
> But if I'm being honest post query selector frameworks don't have a strong cost benefit argument
To me the killer app in the modern world is reactivity, ie making views that update in response to changes in the data model. To manually create listeners and do differential updates, and manage removal and teardown of event listeners etc, is akin to doing manual memory management. We used to do that with jquery sometimes, and it’s the most error-prone thing you can do. It’s a stateful shithole.
Once they manage to find a way to modularize components in a way that is largely view-declarative, I would be happy to crawl up on the surface of vanilla JS again, but not before. It’s simply missing functionality, imo.
Reactivity features are helpful, but in my opinion they're only helpful in a problem that largely shouldn't exist.
For a vast majority of websites out there state largely lives on the server. Reactivity is only helpful when the state reacted to is client side, and for that most sites that's only going to happen when we decide to keep a duplicate copy of state in the client rather than rendering on the back end where the state lives.
I get the desire for smooth transitions, optimistic rendering, etc. Those goals lead to endless complexity and bugs when the actual source of truth lives elsewhere.
How a site is build becomes way more simple when we stick to keeping HTML rendering where the state lives even if that means making UX tradeoffs.
Yes and for those cases it’s kind of already solved decently like with htmx or just plain old forms and post requests. I think those old ways are underrated.
But, for a chat app it isn’t gonna cut it. Or a collaborative app, where changes need to be pushed to the client. Or maps, or similar. Or anything which needs offline working. (I’m working on a desktop app where majority of state is owned by and lives on the client.)
TLDR I agree for passive web pages but the web is often more than that, many times for good reason.
Not sure if its an unpopular opinion here, but in those kinds of cases I think browsers are just a bad deployment target for the problem.
Dealing with cross-platform issues and app store policies can be frustrating, but the web was fundamentally designed for documents and it just doesn't lend itself well to complex, mostly or entirely clients side apps.
It’s not unpopular, I see it as the majority opinion on HN. It’s based on skepticism against web in general, and outright hatred for electron (which is at least somewhat justified).
My app is 11MB bundle (most of which is an unrelated native extension) on most platforms, and has complex stateful business logic and views. It performs mediocre only on Linux due to lacking investment in webkitgtk.
> the web was fundamentally designed for documents
And yet it successfully penetrated the application server market, which it (JS) was never designed for. Stateful apps are much closer to the original design. The gap is essentially a few enumerable pain points that get smaller every year. Most importantly though, the only other toolkit supporting all 3 desktop, 2 mobile and web is Flutter, which is proprietary and entirely downstream the goodwill of a mega-corp.
But you don't have to learn "framework after framework". Realistically, at a well-organised organisation you learn React and that's it. You don't worry about the compilation and minification and what have you, because you have a working build system that does the build and does the source maps, and you have a culture that fixes these things if they break or become flaky.
As someone who stepped away from web for a while and came back to it a couple of years ago, a straight React or Next.js application is so, so much nicer to work with than old-school webapps were. It feels like the web has finally been dragged kicking and screaming into a world of regular software development best practices. JS isn't the best programming language but it's a proper programming language and it does the job, I'm continually baffled that people would rather contort themselves with the sub-Turing tarpit of CSS and what have you instead of just using some libraries, writing some code, and actually solving their problems in what's usually an objectively easier and better way.
It doesn't necessarily need to be Turing complete, but CSS in its current form is harder to understand, debug or make sense of than most Turing-complete languages.
Do you mean because of how its designed to cascade, and all the details of priority that requires? Or something else?
Personally I've never found the language itself hard to understand other than issues where a style somewhere else bleeds in and I have to hope browser dev tools can point me in the right direction.
> Do you mean because of how its designed to cascade, and all the details of priority that requires? Or something else?
Mainly that. But there are other parts that feel clunkier than they need to be too, e.g. media queries force you to repeat yourself a lot when most of the time you just want to write an expression, before/after gives you a whole new way to write elements that's only used for this one niche thing. The language has these weirdly powerful individual features but weak general features and no overall cohesion.
> issues where a style somewhere else bleeds in and I have to hope browser dev tools can point me in the right direction.
The converse part is even worse IMO. There's no way to do any kind of "find usages", so you can never tell whether a given style is used or not. With the result that people never refactor or delete anything, and the codebase gets worse and worse.
Any attempt to show that vanilla web components are somehow a viable solution always read like a parody.
The boilerplate, the innerHTML strings, the long list of caveats, the extra code to make basic things like forms work, manually attaching styles etc. etc.
One recommendation is to change the mental model here. In my eyes it isn’t “don’t use a framework”, it’s “build the framework you need”. It’s tremendously easy to set up an extension of HTMLElement that has 90% of the functionality you’d want out of react. My SPA non.io is built like this - one master component that has class functions I want, and one script for generic functions.
so hard that React is still working on that final 90% after 10 years with 90% more to go now that they think a compiler is the solution for the current mess.
This guide assumes web components is a viable alternative for frameworks like React or Vue. That's a very superficial assumption. React and Vue render the UI as declarative function of state, with the help of components. That's why we use those frameworks. Web components don't solve the state management problem.
State management, state manage management everybody yells when talking about web dev.
It’s not some sort of mystery, it’s just a global of your variables.
The example given clearly showed components backed by JavaScript. Which means you could implement a state management system in seconds.
But beyond that state management is overrated. I remember when react came out and somebody from face book was describing updating some pending message count number. And how they had trouble with it. The issue was they made shitty code, and the result of react was a solution that hid that shitty code. Because I bet to this day if you profile their example they still had the bug but the state management system silently hid it as a future performance problem.
State should really only be kept at rest in the backend, form elements, and the occasional variable. SPA state management is fun to puzzle around with, but gives developers the false impression of productivity and is totally redundant to the browser's built-in capabilities for shuttling data back and forth to a server.
Could you explain what you mean by "storing it in a variable"? It's perfectly fine to store data in a variable (that's what most frameworks do in the end), but that state needs to be reactive in some way — updating that state needs to trigger the necessary UI changes (and ideally in such a way that the entire component isn't being regenerated every time the state changes). This is what makes state management so hard.
Maybe I'll write a blog post on it someday. It depends on the exact method you use to build the calendar my man. You could just change classes and attributes. Or you could use a variable within the scope of where you initialize the component. I wouldn't re-render the whole thing to apply changes, but that's up to you. The nice thing about using vanilla APIs is you don't typically have to worry about thrashing the DOM with unnecessary renders because that's rarely (perhaps never?) the easiest way to patch changes to it, unlike in React where useMemo is prevalent.
Sure, that's what we did in the good old days, and there's good reason that most of us, when building more complex components, switched to better state management systems.
The main issue is that, typically, if you're storing data directly in the DOM, you're storing redundant data. For example, if you've got an input that should have a green background if the input is one string, and a purple background if the input is another string, what state should you store here? Fundamentally, there's only one thing that's interesting: the input's value. Anything else — say, the class used to set the background colour — is derived from that value. And therefore we always want our data to flow in one direction: the input value is the source, and any other state or UI updates are based on that.
But in practice, it's usually hard to maintain that strict flow of data. For example, you'll probably have multiple sources that combine in different ways to create different derived data. Or you might have multiple different ways of updating those sources that all need to perform the same updates to the derived data. Or you might have multiple levels of derived data.
It's definitely possible to build applications like this — I started out this way, and still use this for simple projects where the state is fairly easy to manage. But as projects get more complex — and as the state gets more complex — it almost invariably leads to weird glitches and broken states that shouldn't exist. Hence why state management is the core of most modern frameworks — it's the most important problem to solve.
N.B. `useMemo` in React has nothing to do with the DOM — React will never thrash the DOM with unnecessary changes, that's the point of the diffing process. `useMemo` is instead about reducing the number of times that React builds its own VDOM nodes.
This is a comical misrepresentation of reality. The actual reason people switched to React was because it was what Facebook was doing and they wanted to imitate one of the wealthiest companies to ever exist, not because the masses had problems with rendering form widgets. This problem was solved twenty years ago. Perhaps the worst part about this slander is that benchmarks have actually shown time and again that vanilla JS is superior to React in terms of performance.
Of course vanilla JS is superior to any framework in terms of performance. Anything you can do in a framework, you can do directly in vanilla JS. But performance isn't the only issue here, otherwise we'd all be writing a lot more assembly code.
I find your version of history amusing, because the first project that I migrated away from vanilla JS was actually to Angular, because the team found React's JSX syntax too weird. And these weren't even the first wave of frameworks — people had been using state management systems long before then, but they had other flaws that made them difficult to work with in their own right. React became popular very quickly because it had a very simple rendering model, and because it was quick in comparison to a lot of other options at the time. Since then, the field has developed a lot, and at this point I wouldn't recommend React at all.
Listen, if you're losing track of the date in your date picker as implied previously, then I don't know what to tell you man. Not a problem I've ever seen with progressive enhancement, and I've worked on more complex user interfaces than most. I have witnessed people struggle to solve state-related issues in SPAs for even relatively simple problems though, where the solution would be trivial in vanilla js. If it's not for the performance, and it's not cutting down development time, then what is the endless framework churn really accomplishing? Because that js date picker from twenty years ago still works.
I mostly use SolidJS. It's super lightweight - in many ways, it's just a wrapper around `document.createElement` and a signals library - so you've got a lot of flexibility to use it how you want. It works well for complex web applications, but the library part of it is small enough that you could probably use it for individual widgets on a page and not have too much overhead. The UX is React-like (hooks and JSX), but honestly feels simpler - JSX gets compiled directly to DOM nodes rather than a VDOM abstraction, and there's no "rules of hooks" to learn.
That said, it's kind of niche, which means you need to be more willing to write stuff yourself, so a good mainstream alternative is Vue. Vue is also signals-based and relatively lightweight, but still has a lot of batteries included and a wider ecosystem that is fairly strong. They're also great at taking the parts of other frameworks that work best and implementing them in Vue, but in a fairly considered way. I understand there's also some fairly battle-tested full-stack frameworks in the Vue ecosystem, although I've not had much personal experience of that.
Both libraries are signals-based, which is a completely different reactivity concept to React, which will take a bit of getting used to. But I suspect Vue will make that transition a bit easier - despite SolidJS's more superficial similarities to React, it behaves quite differently.
yeah idk either I didn't read it carefully enough or it was edited at roughly the same time, because I thought I was responding to something very different.
Is UI state really a backend concern? I think this is a nice theory but anyone who has built a sizeable SPA (web application, not website), knows you'll be dealing with UI state complexity very soon.
I get so tired of framework people talking about state as the hill they are willing to die on. State is stupid simple. You use the frameworks because you cannot figure it out on your own and need the giant tool to do it for you.
Interoperable: You can build a Web Component once and it should work "out of the box" in the latest Angular, React, Vue, Svelte, etc. (React was among the last holdouts on Web Component support because of Virtual DOM silliness.) Interoperable Web Components get us away from the era of needing to build npm libraries like ng-mycomponent, react-mycomponent, vue-mycomponent, for all the various combinations of drastically different component systems and ways of writing components, even when your component's core was as Vanilla as you could make it and you shared as much code as you could between implementations there were still so many small subtle things to do differently.
In theory, “de-frameworking yourself” is cool, but in practice, it’ll just lead to you building what effectively is your own ad hoc less battle-tested, probably less secure, and likely less performant de facto framework.
I’m not convinced it’s worth it.
If you want something à la KISS[0][0], just use Svelte/SvelteKit[1][1].
Nowadays, the primary exception I see to my point here is if your goal is to better understand what’s going on under the hood of many libraries and frameworks.
As someone with a 'full stack' history (ie basic front end knowledge compared to a full-timer on that coal face every day), I do notice a lot of the stuff jQuery does is now native to the browser, like being able to use fetch with promises in a few lines of code, or select stuff with querySelector(All)? or xpath. Then all the nice additions to CSS (and HTTP, no more sprites) that weren't possible in the past and remove the need for frameworks.
I tend to rely on Bootstrap so the layout is reasonable on mobile- but that's purely through my own lack of experience.
But I guess someone with a more intimate knowledge can easily get the idea of building a framework. Then add on all the use cases and feature requests...
Some web pages, particularly traditional media websites are absolute hell holes of bloat, but I guess that's more about their ad serving than lean web development.
Man, the example web components seem to work great if you wish to hide data from scraping and search indexing... And if you try to work around this, you end up with something very very similar to https://stimulus.hotwired.dev/ .
Funny story, I have a comment chain here from a few years ago with someone who didn’t realize it wasn’t actually a framework. Total woosh. Lumped it in with the other frameworks and dismissed them all in the same sentence.
714 comments
[ 3.1 ms ] story [ 338 ms ] threadHere's a lit-html template that sets a property:
That the element may use a library for its implementation is basically irrelevant.
The goal of web components is to enable interoperable, encapsulated, reusable components, where how they're built is an implementation detail.
You can use a web component that used lit-html without knowing anything about lit-html, it even that the component uses it.
Why bother when I can just write everything in a single framework?
You're right, it is just a method call from a class. Nothing interesting or new. And that's exactly why I like it! I like me FE code as boring, unimpressive and as simple as possible.
Fine for x:string, but what about w:WebWorker?
If I haven't, then presumably I'll be satisfied with the inherited default behavior, which will probably look something like "<h1>[object Worker]</h1>".
If I care about this extremely contrived example case, in other words, I'll do something to handle it. If I don't, I won't. If I do, it's been easy for at least 25 years now; iirc .toString() was specified in ES3, which was published in March 2000.
Similarly, these references would be from the JS perspective a POJO with lots of seriously heavy implicit "render magic," so you can use them, as with any first-class Javascript value, as function arguments parallel to but a superset of what React does with its props. See the MDN documentation on Node.appendChild (and Node, Element, HTMLElement, etc) for more: https://developer.mozilla.org/en-US/docs/Web/API/Node
If I want to represent the state of a worker thread in the UI, a problem I first recall solving over a weekend in 2016, the way I do it will end up closely resembling the "MVC pattern," with the Worker instance as "model," the DOM element structure as "view," and a "controller" that takes a Worker and returns an element tree. Even if I'm using React to build the UI - which I have also been mostly doing for about as long - I am still going to handle this translation with a library function, even if my component actually does accept a Worker as a prop, which it actually very likely will since that will enable me to easily dispatch effects and update the UI on changes of worker state. I might define that "business logic" function alongside the component which uses it, in the same module. But React or vanilla, I won't put that logic in the UI rendering code, unless it is trivial property mapping and no more (unlikely in this case, since any interesting worker thread state updates will arrive via message events requiring the parent to keep track in some way.)
Does that help clear up what I'm getting at?
Tbh, I'm not sure there's a way for that. But why not just define a method in your target child component and pass the worker in there?
You can use properties (as opposed to attributes) as I demonstrated, and you can use methods like you suggest, but these are both verbose and limited, and add an extra "the component has been created but the props haven't been fully passed" state to the component you're writing. Imagine a component with maybe five different props, all of which are complex objects that need to be passed by property. That's a lot of boilerplate to work with.
You can set them declaratively with a template binding in most template systems.
https://plainvanillaweb.com/blog/articles/2024-10-07-needs-m... https://plainvanillaweb.com/blog/articles/2024-08-30-poor-ma...
I haven't tried signals yet, but I couldn't see why you could pass in an object with multiple values.
But once I decide to cross the "no dependencies" line, using something like Preact + htm as a no-build solution would also take the most of the rest of the pain away, and solve many, many other problems Web Components have no solution and no planned solution for.
All HTML elements are JavaScript objects that have properties. You can pass arbitrary data to custom elements via those properties.
Look at any modern HTML template system and you'll see the ability to pass data to properties declaratively.
You do also have access to properties, but only in Javascript — you can't for example write something like `<my-custom-component date="new Date(2024, 02, 04)">`. That means that if you need to pass around complex data types, you need to either manipulate the DOM objects directly, or you need to include some sort of templating abstraction that will handle the property/attribute problem for you.
This is my main criticism of web components. At the simplest levels, they're not useful — you could build this website very easily without them, they aren't providing a particularly meaningful abstraction at this level of complexity. But at the more complex levels, they're not sufficient by themselves — there's no state management concept, there's no templating, there's not even much reactivity, other than the stuff you could do with native JS event emitters.
As far as I can tell, the best use-case for web components is microfrontends, which is a pretty useful use-case (much better than iframes), but it's very niche. Apart from that, I really don't see why you wouldn't just write normal Javascript without worrying about web components at all.
You're holding web components to a higher standard here in expecting them to take arbitrary data in HTML when HTML itself doesn't support arbitrary data. Notably you can't assign arbitrary data to framework components from within HTML either, so how are web components any more limited?
The point of web components is that they create normal HTML elements. So it makes sense to consider what the value of them being normal HTML elements is. You can write them directly in your HTML source code, for example. But if you do that, you only get access to attributes and not to properties, and therefore everything needs to be strings. Alternatively, you can treat them as DOM nodes in Javascript, at which point you get access to properties and can use non-string values, but now you've got to deal with the DOM API, which is verbose and imperative, and makes declarative templating difficult.
Yes, we could compare them to components from other frameworks, but that's honestly an absurd comparison. They're simply trying to do different things. Frameworks aren't trying to create HTML elements. They're trying to reactively template the DOM. It's just a completely different goal altogether. The comparison doesn't make sense.
- write a simple web service in C# on top of ASP.NET MVC v1
- build a web frontend on top of it using Prototype.js (or jQuery) and a library of components like ExtJS
/s
- React-DOM has one runtime dependency (a cooperative scheduler)
- React itself has no runtime dependencies
It's possible the poster above is referring to build time dependencies. This is harder to assess because there are several options. For example, if compiling JSX using TypeScript, this adds only one more dependency.
The benchmarks I've seen actually show web components being slightly slower than the best frameworks/libraries.
The idea is: no build steps initially, minimal build steps later on, no dealing with a constant stream of CVEs in transitive dependencies, no slow down in CI/CD, much more readable stack traces and profiling graphs when investigating errors and performance, no massive node_modules folder, etc. Massive worlds of complexity and security holes and stupid janky bullshit all gone. This will probably also be easier to serve as part of the backend API and not require a separate container/app/service just running node.js and can probably just be served as static content, or at least the lack of Node build steps should make that more feasible.
It's a tradeoff some people want to make and others don't. There isn't a right and wrong answer.
React is the new Java.
But when you need something the framework can't provide, good luck. Yes, high performance is typically one of those things. But a well engineered design is almost always another, costing maintainability and flexibility.
This is why you almost always see frameworks slow to a crawl at a certain point in terms of fixing bugs, adding features, or improving performance. I'd guess React did this around like 2019 or so.
Overly hated on and conflated with frameworks, yes.
React requires very little from you. Even less if you don't want to use JSX. But because Facebook pushes puzzlingly heavy starter kits, everyone thinks React needs routers or NextJS. But what barebones React is, at the end of the day, is hardly what I'd call a framework, and is suitable for little JS "islands."
For me it's mostly about de-tooling your project.
For example - I have a fairly complex app, at least for a side project, but so far I managed to keep everything without a single external dependecy nor any build tool. Now I have to convert it all to react and I'm not very happy about that, I will have to add a ton of tooling, and what's most important for me, I won't be able to make any changes without deploying the tooling beforehand.
Cognitive burden is relevant to 100% of web apps.
When frameworks are used for that 99% of web apps for which they are overkill, performance actually drops.
> frameworks seem to be the lingua franca for a reason
Sure, but theres no evidence that the reason is what you think it is.
The reason could just be "legacy", ie. " this is the way we have always done it".
I'm sitting on two UIs at work that nobody can really do anything with, because the cutting-edge, mainstream-acceptable frameworks at the time they are built in are now deprecated, very difficult to even reconstruct with all the library motion, and as a result, effectively frozen because we can't practically tweak them without someone dedicating a week just to put all the pieces back together enough to rebuild the system... and then that week of work has to largely be done again in a year if we have to tweak it again.
Meanwhile the little website I wrote with just vanilla HTML, CSS, & JS is chugging along, and we can and have pushed in the occasional tweak to it without it blowing up the world or requiring someone to spend a week reconstructing some weird specific environment.
I'm actually not against web frameworks in the general sense, but they do need to pull their weight and I think a lot of people underestimate their long-term expense for a lot of sites. Doing a little bit of JS to run a couple of "fetch" commands is not that difficult. It is true that if you start building a large enough site that you will eventually reconstruct your own framework out of necessity, and it'll be inferior to React, but there's a lot of sites under that "large enough" threshold.
Perhaps the best way to think about it is that this is the "standard library" framework that ships in the browsers, and it's worth knowing about it so that you can analyze when it is sufficient for your needs. Because if it is sufficient, it has a lot of advantages to it. If it isn't, then by all means go and get something else... again, I'm definitely not in the camp of "frameworks have no utility". But this should always be part of your analysis because of its unique benefits it has that no other framework has, like its 0KB initial overhead and generally unbeatable performance (because all the other frameworks are built on top of this one).
20 lines of anonymous function calling gibberish is so unpalatable.
It's hard to understand what is actual application code in these stacks.
I've seen this play out repeatedly. A company needs a basic CRUD system. Consultancy A brings in designers who produce “wireframes” (usually full-featured eye candy) and UX-centric “journeys.” To justify its bloated fees, the consultancy builds something super-slick using frameworks to match the designs. But once the budget runs out, the customer struggles to maintain it. Eventually, the app becomes unmanageable.
So the consultancy sends in a designer again to produce new mockups and “journeys.” The cycle repeats, this time with another framework.
Although I do think there is merit to "light" frameworks such as Astro, with its scoped styling and better component syntax. But at the same time, independence is also important.
I started something similar with https://webdev.bryanhogan.com/ which focuses on writing good and scalable HTML and CSS.
Noob question, but what happens behind the scenes in terms of these concepts for web components instead?
Edit: I just added a shadow root to a div in your comment, saving its content beforehand, moved its content inside the shadow root, and added a style with * { all: initial } and your comment text got Times New Roman.
Many of the 25 mentions of Shadow DOM in the Components Page and 14 mentions of it in the Styling page are about solving problems you now only have because the site recommended you use Shadow DOM, and the problem Shadow DOM itself is _trying_ to solve is one I don't have in components written specifically for my app, which will only be used in my app.
[0]: https://github.com/kgscialdone/facet
* web-component is a way to attache javascript to certain elements. There are other ways to do it, but sometime this way feel cleaner, like when you do server-side rendering and not using any javascript framework.
* shadow-dom is a way to organize your styles. As you said there are other ways to do it, but I find it useful because it offers full isolation, and is compatible with browsers 3 years back.
I know you’ll “write your own framework” but maybe that’s optimal in some situations - more than we might give credit to at the moment.
You'll eventually need \<link> anyway for preloads, especially with web fonts, since that's the only way to prevent FOUC. Personally I lean on build steps to solve this. I don't like bundlers or frameworks, but I have grown accustomed to custom-building.
If you’re writing an SPA, and it isn’t Twitter or a content consumption platform, and it isn’t necessary to be API-driven, seriously just stop. You’re not clever, you’re not improving the experience, you’re only appealing to the tastes of other programmers. If billion-dollar companies can’t get them working perfectly, you certainly won’t.
If you think that’s interesting, send me your firm’s URL, I’ll consider applying. (Edit: or really anyone reading this who is interested - government of a foreign nation outside the US is not viable, unfortunately.)
Moving a navigation/menu from one app to another takes 3 people 2-3 weeks by now. Changing the "router" to update the TS version is just as time consuming. Things that would have taken 1 day max. take now 2-3 weeks. That is 1/14th of the productivity and people get paid for that, more than I did. Oh and did I mention the menu responsiveness was broken for months at a certain viewport width? I did report it, but apparently it was so hard to fix, that it could not be done in a quiet hour, so it took months laying around in the queue of things to fix.
It seems unintuitive, but traversing an object tree using reflection to generate json is just slower than using an HTML template, which is probably a rope data structure.
Issues with SPAs are "core features straight up don't work " and "page is now just an endless spinner."
I know which I prefer.
https://m.youtube.com/watch?v=jnYjIDKyKHw
It’s such a pain having clear separation in development where everything runs off of the react server by default, but then it won’t when deploying, so either you end up doing all sorts of weird stuff or you need to be building and running production locally constantly, thus defeating the whole convenience of having a dev server that can hot reload the changes
I openly admit that I'd rather learn a new framework than touch anything to do with figuring out how the browser is intended to behave in practice. What an abomination and insult to humanity.
Edit: holy shit y'all do not like the earnest approach to technology
``` fetch('/my-content').then(async res => { if(res.ok) { document.getElementById('my-element').innerHtml = await res.text(); } }) ```
Something like that. Doesn't get much easier. Gone are the days of browser inconsistencies, at least of you stick to "Baseline Widely available" APIs which is now prominently displayed on MDN.
You do have to call `getElementById` on a document. There can be many documents in a window.
Although a very consistent convention, there are no guardrails put in place to prevent something from setting the same id on two or more elements.
getElementById will return the first element that it finds with the id, but you can't know for sure if it is the only one without additional checks
function getId(v) {return document.getElementById(v)}
Dev tools allows $ $$, dunno, make a macro?
We must not defy the system!
But what's the problem again?
I get that huge apps probably need a lot more than that, but so many people these days reach for heavy frameworks for everything, because it’s all they know.
The author of this article blog is describing some more advanced SPA-like scenarios, but those are completely optional
The web finally provides a widespread standard for deploying applications inexpensively. Unfortunately, the technology used to build user interfaces for the web remains somewhat mediocre.
It’s unfortunate that history took some wrong turns with X11, Java, Flash, Silverlight, .NET, and countless other alternatives that I haven’t personally lived through.
Hopefully, someone will eventually find a way to make developing web applications comfortable and the broader community will embrace it.
I do not understand why people hold this impression, especially in corporate environments.
Windows supports both system and per-user deployments; the latter so you don't even need administrator rights. And with Intune, deployments can be pulled or pushed.
Many desktop applications are written in .Net so you don't even need to install the runtime because it's preinstalled on the operating system.
Even ClickOnce deployments -- which you can deploy on the web or on a file share -- pretty much make deployments painless.
EDIT: For the naysayers: please then explain to me why Steam is so successful at deploying large games on multiple platforms?
And is there even a guarantee that your deploy will be rolled out in X minutes?
Version skew remains one of the biggest sources of catastrophic bugs at the company I work for, and that's not even taking into client app ver, just skew between the several services we have. Once you add client app ver, we have to support things for 3 years.
At my one-person company I just do a Kubernetes deploy, it goes out in a couple minutes and everyone has the latest ver whether they like it or not. I don't have the resources to maintain a dozen versions simultaneously.
The webapp doesn't care if someone's machine was down overnight or if the paranoid lady in design managed to install some local "antivirus" which blocked the updated rollout or if the manager of sales has some unique setting on his machine which for some inscrutable reason does silly things to the new version. If their web browser works, the inventory database works for them, and they're on the latest version. If their web browser doesn't work, well, your support teams would have had to eventually take care of that anyway.
Not sure yet how to solve this problem on the Internet yet though. How can we prevent uninformed masses from creating incentives for businesses, that turn the web into a dystopia?
Not on my computers. At home, or at work
Weylus gives you a URL that you can visit on the device and instantly use it. Try doing that with native apps. They'd need native apps for Windows, Linux, Mac, iOS, Android... get them on the app stores too, support all the different Linux distros... or just a single URL that works instantly anywhere.
Steam works for the same reason the App Store works, it targets mostly a single platform (Windows) and all dependencies are bundled in. The Steam client itself is a web app running on the chrome engine, though.
The last .NET version to be deployed this way has a 10 year old feature set. Nowadays you bundle the parts of .NET you need with the application.
https://learn.microsoft.com/en-us/dotnet/core/install/window...
Although, on re-read, maybe they meant there's a good chance another application already installed it? This I wouldn't agree with, as applications often insist on installing different versions of the system-wide runtime, even for the same major version.
To be specific, .NET install is version-aware and would manage those side by side, unless the destination folder is overridden.
Because Valve puts lots of time and money into making it work for their customers (https://github.com/ValveSoftware/Proton/graphs/contributors), time and money that the average small business can't afford.
- many people refuse to upgrade for various reasons so we have to support ancient versions (especially for important clients), for stuff like license activations etc.
- various misconfigurations (or OS updates) on Windows can make the app suddenly crash and burn - and you waste time investigating the problem. My favorite recent bug: the app works OK everywhere except on some Japanese systems where it just crashes with access violation (see the next bullet point)
- debugging is hard, because you don't have immediate access to the machine where the bug triggered
- originally it was built 100% for Windows but now we have people asking for a MacOS port and it's a lot of work
- people crack our protection 1 day after release and can use it without paying
SaaS has none of those problems:
- people are used to the fact that SaaS applications are regularly updated and can't refuse to upgrade
- modern browsers are already cross-platform
- browser incompatibilities are easier to resolve
- you debug your own, well-known environment
- if someone doesn't play by the rules, you just restrict access with 1 button
> EDIT: For the naysayers: please then explain to me why Steam is so successful at deploying large games on multiple platforms?
How many games are multi-platform on steam? Checking the top 20 current most played games, 14 of them are windows only. If it's so easy to be multi-platform, why would 14 of the top 20 games not be multi-platform? Oh, it's because it's NOT EASY. Conversely, web apps are cross platform by default.
Only 2 of the top 20 games supported 3 platforms (windows, mac, steam-deck). 1 was windows+steam-deck, 3 were windows+mac
if you look into the support forums on steam for any random game you'll find lots of complaints about stability and crashes, many of which are likely to be esoteric system-specific problems.
I wrote an inventory management program for my father's hazardous waste company. Used .net mvc as the backend, WPF as the frontend. WPF sucks in many ways, but I got it working and have had zero complaints.
I built that program almost 20 years ago. Until last year I spend maybe 5-6 hours total in maintenance, mostly ssl cert updates. Let that sink in.
Games were made in flash so it can't be that slow.
Maybe slow for time to load. I think we got that down a bit and this wasn't to render content but a utility for a signed up user.
Modern day SPAs are far, far worse offenders when it comes to smothering resources.
I was so happy when it finally started to disappear. That kind of sheer disregard for my system resources is inexcusable.
As for the speed of the flash player itself it was quite good.
I hope that, in the long term, wasm and canvas (or something similar) will gradually take over this niche. Frameworks like Avalonia already let you write a desktop app and then surface it in the browser, today. This stuff is still rough around the edges, particularly wrt accessibility, but there's nothing unsolvable there in principle, it just needs time and effort (and money).
Nice work. Reminds me of "A Dark Room" and how a simple mostly-text interface with a bit of HTML/CSS/JS can have such a big impact.
https://adarkroom.doublespeakgames.com/
[0] https://www.leboncoin.fr/
Edit: just tried it again and seems they fixed it! The ads stays in loading state forever but the site is usable again. Wonder if they did something on their side or if they changed ad provider.
Though I think maybe if one is using it for a different purpose, like looking for apartments or roommates then that's probably shit.
Why not?
It's really irritating for your users. They might not consciously be able to point it out as the cause of their irritation, but they'll like your app a lot less.
My business doesn't use React anymore, and I'm so happy I don't have to do pointless maintenance.
A side note, included in my repository: you update your element's innerHtml from the constructor, not from the connectedCallback. MDN and the web standards seem to be inconsistent on this, and elsewhere people write about it, too.
People talk a lot about data and binding, etc. I think it's weird, it's like people have forgotten how to just use setters. You can call a render() method from a setter, and it does the same thing WebKit et al do when you call an internal setter on an HTML element.
I don't see the value in these frameworks anymore.
Notably, Web Components. They're fantastic for distributing components - after all, a Web Component will work in every framework (even React, the IE of frameworks, finally added support), or even in vanilla HTML. So you can build a component once and everybody can use it. It's fantastic.
But for internally composing a web application, Web Components are simply awful. They add nearly no helpful features that vanilla JS doesn't already have, and they add bucketloads of extra complexity. You got attributes and properties, and they're mostly the same but kinda not always and oh by the way, attributes can only be strings so good luck keeping that in sync. You got shadow DOM which is great for distribution but super restrictive if you want any sort of consistent global styling (and a total pain in devtools, especially once you go 10 levels deep). You can turn that off, of course, but you gotta know to do that. And plenty more quirks like this. It's just.. It makes lots of easy things 5x harder and 1 hard thing 1.5x easier. Totally not worth it!
If you really want to not use a big clunky framework, but at the same time you have a complex enough app that composition and encapsulation is important, you'd be much better off just making your own object hierarchy (ie without extending HTMLElement), skipping all that awkward web component luggage and solely doing what they do best (tie an object to an element).
Or, better yet, get over yourself and just use a framework that does this for you. Your future self will thank you (and your colleagues even more so).
ps. rant time: If only the web browser people had gotten off their high horse and not proposed the word "Web Components"! If they would've just been named "Custom Elements", which is what they are, then we wouldn't have had 5+ years of people mistaking them for a React competitor.
Lit is amazing though. It's fast, lean, and easy to learn. In fact, to my experience, the only things about it that are un-ergonomic, are due to the fact that it's built around web components. Lit without web components would be so much better (again, except if you're building something to be distributed to other programmers on any framework). It wouldn't have a single global registry of components, it wouldn't have that attribute mess, and I bet it'd not need a compiler at all (it doesn't need it now either, but is easier/nicer with it).
Fair enough, but the way I read TFA, it doesn't dissuade developers from using tiny convenience libraries that leverage native browser capabilities. Based on your pushback, it sounds like my perception that Lit is mostly a convenient base class for Web Components is very incorrect. I'll dig into that more, thanks!
It has custom syntax, custom directives that look like regular JS functions but cannot be used like regular functions, a custom compiler in the works etc. etc.
They will keep telling you it just a small library and very vanilla though.
It's a haphazard solution that they now fight against with "directives" and even a custom compiler "for when initial render needs to be fast". It's not bad, but it's far from genius. And honestly, the only reason it works is that browsers have spent ungodly amounts of time optimizing working with strings and making innerHtml fast.
Additionally, it's weird to ask for "close to html" in a 100% Javascript-driven library/framework.
As for "etc.", I don't even know what etc. stands for. lit is busy re-implementing all the things all other frameworks have had for years. Including signals, SSR etc.
> Additionally, it's weird to ask for "close to html" in a 100% Javascript-driven library/framework.
Fair point. I don't personally really care about that either. I guess I just meant to be say that it's not all too custom :-)
E.g. classMap https://lit.dev/docs/templates/directives/#classmap
--- start quote ---
The classMap must be the only expression in the class attribute, but it can be combined with static values
--- end quote ---
So now you have to figure out which attribute this is called from, whether this particular call is allowed in this attribute etc.
So what they do is they parse (with regexes) their "close to HTML" code into a structure not dissimilar to React's, figure all this stuff out, reassemble actual HTML and dump it to the DOM
[0]: Table of contents element: https://github.com/cmaas/table-of-contents-element
[1]: SVG avatars (React-free fork of Boring Avatars): https://github.com/cmaas/playful-avatars
So at least in terms of minimal bases, all of these frameworks are much of a muchness.
The browser people literally promoted them as a React alternative. Then their goals and role changed every year, and now they are again promoted as an alternative
Perhaps my brain has been addled by a decade of React but as the examples became more advanced, they just looked a lot noiser and more complex compared to JSX or Svelte components.
I run sites that serve hundreds of millions per day and we pour a ton of resources into these projects. We're trapped in a framework (react) prison of our own creation. All failures are those of complexly. Highly coupled state machines with hacked, weaved, minified, compiled, transpiled, shmanzpiled etc. into unreadable goop in production. Yes I know source maps, but only when needed, and they are yet another layer of complexity that can break - and they do. How I long for the good old days before frameworks.
Perhaps nostalgia and the principle of KISS (and a few others) is clouding my judgement here, after all, frameworks are made for a reason. But it's difficult to imagine a new engineer having any more difficulty with vanilla than learning framework after framework.
I feel the same way. React and Angular (well an earlier version of Angular) were made prior to ES2015 being mainstream, so I do think they made sense to use when they were initially created. Since then, I've become burned out from the constant churn of new frontend frameworks to learn. Even within the world of React, there's different ways of writing components, and different state managers.
But you're not wrong about there being many ways to write components and manage state.
And RSC is a mess. But thankfully you can keep pretending that doesn't exist.
Contrast that with non-framework JS/HTML, where _you_ decide how long it lives and how often you need to upgrade (or not). Having to rejigger a web app every 2-3 years because someone outside of your organization changes something is not only unappealing, but it's horribly expensive for large-scale businesses and possibly prohibitively expensive for small-scale businesses or solo developers.
HTML was supposed to just a slight markup layer to make it easier to transit and render text documents, likewise that's all HTTP was designed for. The ratio of text-to-markup should be fairly high (I'm sure today it's less than 1). But for some reason (probably the initial ease of publishing globally) we decided that the future of application development should be to entirely reinvent GUIs to be built on top of this layer. If you look under the hood at what React is doing, we just have decades of hacks and tricks well organized to create the illusion that this is a rational way to create UIs.
Imagine a world where we decided we wanted to create applications by hacking Excel documents and Visual Basic (being from the before times, I had seen attempts at this), or have every app be a PDF file making clever use of PostScript? When one remembers how ridiculous it is to attempt to do what we have collectively done, it's not too surprising that a website can require megabytes of JS to render properly and, more importantly, to allow reasonable development processes allowing for some organization of the code base.
I also don't like the state of the web.
I too am from the before times where I guess we built essentially our own frameworks to handle own unique issues and take security into our own hands (verses have to trust external libraries and external resources….)
I sadly laugh when I hear 20+ years late people are still fighting back button navigation issues. I still see sites that can’t handle double posts correctly or recovery gracefully when post responses fail/timeout.
I’m out of the game now but for all the benefits of the web it’s been haves to death to support stuff the underlying infrastructure was nit designed for.
Things like these haven't taken over the world because they didn't have the ease of app delivery that browsers provide, and attempts to bolt them onto browsers (Silverlight etc) didn't work out because they didn't work out of the box for most end users.
These days though we have enough bits and pieces directly in the browser (wasm, canvas, WebGL etc) to recreate something like Silverlight that "just works" in any modern browser. Take a look at https://eremex.github.io/controls-demo/ for an example of what's possible.
†I know this claim will rub some people the wrong way, but if you compare the capabilities of web tooling to build rich application UIs against desktop app tooling of even 20-30 years ago, there’s no comparison. The web is still primitive, and while JS and CSS are improving at a good pace, HTML is almost frozen in carbonite.
Not really - there are pretty big escape hatches - you can do pretty much anything in canvas, custom elements allows you to define your own elements with their own behaviour.
I'd say the problem is the opposite - one of the reasons desktop apps from 20-30 years ago ( say MacOS 7 ) where great from a user perspective is pretty much all apps looked and worked in the same way, using the same UI toolkit and the same UI principals. And from a developer perspective - a lot of the key decisions had already been made for you.
The web of today is a zoo of UI styles and interaction modes.
The problem isn't so much a lack of innovation or possibilities, but perhaps rather the opposite.
That old VB code that queried the database directly wouldn't work well over a non-local network.
ie there is a bit of apples and oranges comparison here.
You also might not need any access control, network traffic security, cross platform deployment, instant install, evergreen updating, trivial UI integration ( links ) etc etc.
If you really want something simple you could use Excel, Access or Filemaker as a front end.
I agree life has got more complex - and in some cases unnecessarily so - case in point it's becoming increasingly hard to write web apps without SSL - even if you don't need it.
To me the killer app in the modern world is reactivity, ie making views that update in response to changes in the data model. To manually create listeners and do differential updates, and manage removal and teardown of event listeners etc, is akin to doing manual memory management. We used to do that with jquery sometimes, and it’s the most error-prone thing you can do. It’s a stateful shithole.
Once they manage to find a way to modularize components in a way that is largely view-declarative, I would be happy to crawl up on the surface of vanilla JS again, but not before. It’s simply missing functionality, imo.
For a vast majority of websites out there state largely lives on the server. Reactivity is only helpful when the state reacted to is client side, and for that most sites that's only going to happen when we decide to keep a duplicate copy of state in the client rather than rendering on the back end where the state lives.
I get the desire for smooth transitions, optimistic rendering, etc. Those goals lead to endless complexity and bugs when the actual source of truth lives elsewhere.
How a site is build becomes way more simple when we stick to keeping HTML rendering where the state lives even if that means making UX tradeoffs.
But, for a chat app it isn’t gonna cut it. Or a collaborative app, where changes need to be pushed to the client. Or maps, or similar. Or anything which needs offline working. (I’m working on a desktop app where majority of state is owned by and lives on the client.)
TLDR I agree for passive web pages but the web is often more than that, many times for good reason.
Dealing with cross-platform issues and app store policies can be frustrating, but the web was fundamentally designed for documents and it just doesn't lend itself well to complex, mostly or entirely clients side apps.
My app is 11MB bundle (most of which is an unrelated native extension) on most platforms, and has complex stateful business logic and views. It performs mediocre only on Linux due to lacking investment in webkitgtk.
> the web was fundamentally designed for documents
And yet it successfully penetrated the application server market, which it (JS) was never designed for. Stateful apps are much closer to the original design. The gap is essentially a few enumerable pain points that get smaller every year. Most importantly though, the only other toolkit supporting all 3 desktop, 2 mobile and web is Flutter, which is proprietary and entirely downstream the goodwill of a mega-corp.
As someone who stepped away from web for a while and came back to it a couple of years ago, a straight React or Next.js application is so, so much nicer to work with than old-school webapps were. It feels like the web has finally been dragged kicking and screaming into a world of regular software development best practices. JS isn't the best programming language but it's a proper programming language and it does the job, I'm continually baffled that people would rather contort themselves with the sub-Turing tarpit of CSS and what have you instead of just using some libraries, writing some code, and actually solving their problems in what's usually an objectively easier and better way.
Personally I've never found the language itself hard to understand other than issues where a style somewhere else bleeds in and I have to hope browser dev tools can point me in the right direction.
Mainly that. But there are other parts that feel clunkier than they need to be too, e.g. media queries force you to repeat yourself a lot when most of the time you just want to write an expression, before/after gives you a whole new way to write elements that's only used for this one niche thing. The language has these weirdly powerful individual features but weak general features and no overall cohesion.
> issues where a style somewhere else bleeds in and I have to hope browser dev tools can point me in the right direction.
The converse part is even worse IMO. There's no way to do any kind of "find usages", so you can never tell whether a given style is used or not. With the result that people never refactor or delete anything, and the codebase gets worse and worse.
The boilerplate, the innerHTML strings, the long list of caveats, the extra code to make basic things like forms work, manually attaching styles etc. etc.
One recommendation is to change the mental model here. In my eyes it isn’t “don’t use a framework”, it’s “build the framework you need”. It’s tremendously easy to set up an extension of HTMLElement that has 90% of the functionality you’d want out of react. My SPA non.io is built like this - one master component that has class functions I want, and one script for generic functions.
The last 10%, OTOH...
That in itself undermines a lot of the author's message, as they were not able to reasonably de-framework themselves.
(And - it's not hard to get the navbar right, in any number of ways. But you do have to do a bit of work before you preach things to others.)
It’s not some sort of mystery, it’s just a global of your variables.
The example given clearly showed components backed by JavaScript. Which means you could implement a state management system in seconds.
But beyond that state management is overrated. I remember when react came out and somebody from face book was describing updating some pending message count number. And how they had trouble with it. The issue was they made shitty code, and the result of react was a solution that hid that shitty code. Because I bet to this day if you profile their example they still had the bug but the state management system silently hid it as a future performance problem.
Even something simple like a date picker. Where are you going to store which month you're looking at?
There's state everywhere, and we should not be sending it all back and forth to the server.
The main issue is that, typically, if you're storing data directly in the DOM, you're storing redundant data. For example, if you've got an input that should have a green background if the input is one string, and a purple background if the input is another string, what state should you store here? Fundamentally, there's only one thing that's interesting: the input's value. Anything else — say, the class used to set the background colour — is derived from that value. And therefore we always want our data to flow in one direction: the input value is the source, and any other state or UI updates are based on that.
But in practice, it's usually hard to maintain that strict flow of data. For example, you'll probably have multiple sources that combine in different ways to create different derived data. Or you might have multiple different ways of updating those sources that all need to perform the same updates to the derived data. Or you might have multiple levels of derived data.
It's definitely possible to build applications like this — I started out this way, and still use this for simple projects where the state is fairly easy to manage. But as projects get more complex — and as the state gets more complex — it almost invariably leads to weird glitches and broken states that shouldn't exist. Hence why state management is the core of most modern frameworks — it's the most important problem to solve.
N.B. `useMemo` in React has nothing to do with the DOM — React will never thrash the DOM with unnecessary changes, that's the point of the diffing process. `useMemo` is instead about reducing the number of times that React builds its own VDOM nodes.
I find your version of history amusing, because the first project that I migrated away from vanilla JS was actually to Angular, because the team found React's JSX syntax too weird. And these weren't even the first wave of frameworks — people had been using state management systems long before then, but they had other flaws that made them difficult to work with in their own right. React became popular very quickly because it had a very simple rendering model, and because it was quick in comparison to a lot of other options at the time. Since then, the field has developed a lot, and at this point I wouldn't recommend React at all.
Out of curiosity, what would you recommend?
That said, it's kind of niche, which means you need to be more willing to write stuff yourself, so a good mainstream alternative is Vue. Vue is also signals-based and relatively lightweight, but still has a lot of batteries included and a wider ecosystem that is fairly strong. They're also great at taking the parts of other frameworks that work best and implementing them in Vue, but in a fairly considered way. I understand there's also some fairly battle-tested full-stack frameworks in the Vue ecosystem, although I've not had much personal experience of that.
Both libraries are signals-based, which is a completely different reactivity concept to React, which will take a bit of getting used to. But I suspect Vue will make that transition a bit easier - despite SolidJS's more superficial similarities to React, it behaves quite differently.
Rendering libraries like Lit handle declarative templates, and there are many state management solutions, the same ones you can use with React, etc.
Interoperable - can you expand on this?
> An explainer for doing web development using only vanilla techniques. No tools, no frameworks — just HTML, CSS, and JavaScript.
You're thinking of a lightweight site, which this isn't claiming to be.
I’m not convinced it’s worth it.
If you want something à la KISS[0][0], just use Svelte/SvelteKit[1][1].
Nowadays, the primary exception I see to my point here is if your goal is to better understand what’s going on under the hood of many libraries and frameworks.
[0]: https://en.wikipedia.org/wiki/KISS_principle
[1]: https://svelte.dev
I tend to rely on Bootstrap so the layout is reasonable on mobile- but that's purely through my own lack of experience.
But I guess someone with a more intimate knowledge can easily get the idea of building a framework. Then add on all the use cases and feature requests...
Some web pages, particularly traditional media websites are absolute hell holes of bloat, but I guess that's more about their ad serving than lean web development.
Interesting. Why do web components have this effect, but some JS frameworks apparently do not? Or do they all?