That's how the article delineates it too. The term "Full-stack Frameworks" for the fourth era is a bit confusing: what the article means is the battery-included wrappers for popular component libraries like Next.js, Remix (React) or Nuxt.js (Vue) and not just any full-stack framework per se.
+the next generation: "compiler-frameworks"(or "UI compilers").
Overall this division seems weird. SSR is neither a revolution, nor universally desirable.
The real revolution is in what these next-generation frameworks like Svelte or SolidJS offer: small bundles combined with high performance achieved through eschewing virtual DOM in favour of precise changes in the DOM.
Yep. SSR has been around for ages. The very first "web frameworks" were pure SSR. And by that I'm referring to PHP and the old CGI!
The big leap forward from Solidjs and Svelte is that they do complex source-to-source compilation to avoid virtual dom diffing. That approach lets them get the best of both worlds - the programmer can pretend their components are pure & reactive. (Solidjs looks almost identical to react.) Thats great because it means there's no bugs due to fiddly or forgotten DOM updating.
But the javascript executed by the browser doesn't need any of react's complexity. The JS output by the compiler simply makes direct DOM manipulation calls when content changes. There's no heavy re-rendering of view trees, and no virtual dom to track. Unlike react, you don't need to apologize for mutating variables or re-render your entire page when you do. So we can do away with redux and all of that. A hello world app in solid or svelte is a few kilobytes, compared to 200kb+ for a react project. And it renders instantly.
It took us a few years to get here, but I'm delighted by the direction UI code in the browser is headed. I hope these ideas make it into native applications.
Actually that's just a common misconception, which I believed too.
The complex compile-time transforms enable almost no performance improvements.
As a proof just take a look at the js-framework-benchmark table [0], my framework (Voby [1]) is faster than both in the benchmark despite having an API very similar to Solid and no requirement for a Babel transform or other compile-time transform (though the basic React-like JSX transform is supported for convenience).
Those transforms actually exist 99% just for providing some convenience features to the developer. If that weren't the case it wouldn't be possible to make something similar without a transform that's faster than both. In fact Svelte is actually quite a bit slower than both Voby and Solid. Svelte is even slower than Inferno, which is a (very optimized) V-DOM framework.
It seems like a lot of these benchmarks are manipulating rows in a table? Are there any benchmarks that involve complex component trees with a lot of nesting?
Very cool framework though, I'll have to look more into how it works someday
I'm not sure. But FWIW I don't think more complex nesting would change anything in this regard. Those transforms essentially just avoid you having to wrap some things in functions manually, and avoid some extra function calls. Avoiding manual wrapping is a convenience feature and those extra function calls are not really that expensive (or it wouldn't be possible for Voby to be faster than something optimized like Solid in the benchmark).
If you'd like to come up with a different sort of benchmark where you think Solid would shine I'd be happy to write an implementation of it with Voby and see what happens. Or you can just try that yourself, the API is fairly similar.
---
I should probably add that js-framework-benchmark is heavily biased toward measuring creation time actually, which is something where compile-time optimizations should shine. If you are more interested in updating things, like you would be in a rich application, Voby is actually some 20% faster than Solid at replacing rows with other rows, because it support reusing of older nodes (opt-in) (this also lowers memory pressure in some cases by the way, no need to make and gc lots of stuff in some cases). This optimization is not supported in Solid nor Svelte, and interestingly it's not a safe optimization that can be applied all the time, so it must be opt-in, but how are you supposed to tell to Solid or Svelte when it's safe to apply it if something like Voby's "template" function, which is also used for this, is abstracted away entirely from you? In some sense the transform actively goes against performance here.
No, the difference is that if you pass to Solid's <For> a signal to an array, and make a node for each of the values of that array, and then you change the signal to point to an empty array, then Solid just deletes those nodes and they eventually get garbage collected, if you then pass the signal an array containing some values then new nodes are recreated. The difference is that in Voby, if you explicitly opt into this, nodes are not deleted but kept in memory when going to an empty array, and new one are not created when going back to a non-empty array, those nodes kept in memory are repurposed.
As a rule of thumb if you don't have any API for explicitly opting into recycling it's not happening, it's not a safe optimization that can be applied all the time.
I guess I feel like deep complex structures are where we would see significant differences between VDOM (react) and compiled (svelte) but I might be wrong, I'm not too familiar with the internals of either framework
By "full-stack" here I mean frameworks which handle both the frontend and backend simultaneously, in a seamless way. The closest thing framework that I remember from the MVC/P era which attempted this was Meteor.js, but it was really horrendous to use in my experience.
Otherwise, it was very common practice to serve an Ember or Angular app as static files Nginx or directly on a CDN. Wrapping them in a server-side framework was always a bespoke process which required you to effectively maintain two frameworks, and stitch them together yourself (unless you count Ember + Rails in the early days, but even that is a stretch IMO). When SSR was introduced in any framework, it was usually not used to its full potential to be able to accomplish the use cases I discuss in the post, like authentication, API endpoints, etc. It was just used to render the app on the server. It did not fundamentally change the DX of the framework.
I honestly was pretty skeptical of these latest frameworks until I gave them a shot! It doesn't sound that revolutionary until you actually start using them, and things which were previously quite difficult become absolutely trivial. I highly recommend trying them out some time.
I'd say JQuery and ExJS were part of the same era. JQuery was used by a lot of people that didn't embrace javascript at all and tried to not use it (e.g ASP.NET coders)
I feel like backbone deserves its own era as it seemed like all the cool kids would exclusively use that for a couple years.
Then Angular and a ton of others flooded the scene.
I never use frameworks either. In fact the last site I published didn't have any Javascript at all (it's just a static site so shouldn't need it yet that doesn't seem to stop most other sites from abusive amounts of JS).
Sure, probably works, just don't complain about age discrimination when you bring up nonconsensus things that have been superseded, and the team isnt fond of that system design
I also started out without frameworks and still prefer to work that way.
However, I have found them to come in handy when solo-ing projects that require:
- transpiling JS back into the stone age for compatibility
- accessibility
- seamless localisation
I have found I just can't keep track of all of these things as well as React does.
At the same time, I think React is a huge, dependency-laden mess, very difficult to learn (because it's changed its mind on how to do things about 100x, so no responses to issues on SO apply to your version of React, Redux, React Router, etc), slow as hell and probably overkill for most projects...
> Or in the form of "User changes parameters on screen, Javascript updates the screen accordingly".
Once this gets a bit more complicated you have a bunch of state to keep track of and you have to make sure to re-render only the parts that have changed, and deref that parts that should be GCd. I'll happily take on a reactive UI framework dep if I can avoid writing my own diff pipeline.
If you aren't using a public framework and you use any JavaScript in your app then you are creating your own framework. Nothing wrong with that.
The real value of public frameworks comes into play when you have more than one generation of developers working on your project.
It's much easier to onboard a new developer onto a react app than it is to get them to understand the weird bespoke nuances of the conventions you came up with while hacking on your site at 3am 5 years ago.
> If you aren't using a public framework and you use any JavaScript in your app then you are creating your own framework.
Sorry but a “framework” used by one project (especially not broken out into a separate subproject) is not a framework. That’s just infra code.
I think your point still stands that the value is developers understanding a framework can more quickly get to work—I’m just triggered by your exceedingly liberal usage of the word “framework”.
This might hold true when the application in question does a lot of stuff covered by a framework. For example if it does routing, then it is nice to have common ground on how routing is done. If the application mostly does custom stuff, not covered by the framework, then the framework might harm more due to the added complexity.
That is why I proposed a discussion based on real life examples.
The other thing is that frameworks change. You picked React for your example. A currently popular framework. Chances are, the next developer will not come on in 5 years, but in 15 years. And does not know anything about React. Or about React as it is today. Then they might have a harder time understanding React than to understand a well written, minimalistic piece of Javascript.
> Chances are, the next developer will not come on in 5 years, but in 15 years.
That doesn't seem likely to me at all. More likely in the next 6 months than in 15 years. Why are you planning for 15 years out? The company you are working for might not be around in 15 years. Code might not even be recognizable in 15 years. All of our programs might be written by AI in 15 years.
Optimizing for the short term makes way more sense to me. 2 or 3 years out, not 15.
Human labor is expensive. Companies aren’t going to throw away a perfectly good asset they poured tens of millions in, unless they have to.
I don’t see why a well-written, time-tested piece of software shouldn’t still be around 15 years down the road.
The initial comment was not about software quality but about "the popular framework now might not be popular in the future"
I don't see any contradiction between creating well written, time tested software and also choosing currently popular frameworks to work in.
If your React app is well written and stable and well tested, I see no reason it shouldn't be available in 15 years. And if you can't find React Developers to hire in 15 years to work on it, that's tough. Pay to have some trained.
Except that unlike React, COBOL doesn’t bring along 10000 dependencies written by 5000 different authors, randomly abandoned a few months later but teeming with unpatched vulnerabilities.
Sure, somehow I’m going to find React developers 15 years from now to maintain my line-of-business React app but how secure will it be?
One could argue that I can rewrite the framework-dependent parts. But rewrites cost money, too.
I love new stuff but I still think that, depending on the app, it may make good economic sense to plan ahead for it to be useful after a decade or two.
Working with other people and agreeing on how to do things is hard. The backend and frontend roles crystalized with a natural boundary between them being HTTP, one side doing HTML stuff, and the other defining URL endpoints (everything else is basically done by the ORM).
My previous 2 companies basically lost all marketshare because they _had to_ use Node + React for their in-house CRUD tools. The amount of time and money wasted is insane. We ended up doing most things with Airtable because the dev team(s) were too slow.
What you talking? I don't particularly endorse react but what are you comparing to? If we're talking plain js or jquery style dom manipulation react, or any of its competitor, is a vastly superior for any non-trivial app. If you're having a mostly static site I can believe you though.
Probably to simple server-side frameworks. Most web apps are based on navigation and forms, which can be done simpler with classic server-side MVC and some JS plugins for the more interactive parts. No need for client-side routing, solidifying HTTP API endpoints or duplicating data models & logic on the front-end.
Something like Laravel + alpinejs running on heroku or Google app Engine or a similar platform is what 90% of the typical crud saas webapps most of us build need.
But we definitely have more fun with React SPAs and Go microservices on Kubernetes :)
(Notice I'm listing the shinny toys of the usual 3 layers at every company)
I still remember the day I discovered Dan Steinman's Dynamic Duo Javascript library. It allowed me to do effects that I thought were reserved only for flash or java embedded applets. That was in late 1999, probably while I was struggeling to make a crappy script copied from dynamicdrive.com work in Netscape 4. Tell me about eras!!
The "Before Era" mentioned in the article can probably be subdivided further - it casually mentions that back then, "the most common thing you would do was include jQuery, throw together some scripts for a few UI widgets, and call it a day". However that was only possible after jQuery was released in 2006. Before that were the real "dark ages" of JS development, with primitive libraries, even more primitive dev tools in the browser (Firebug was also only released in 2006, and Chrome was the first browser to have integrated dev tools in 2008) and stuff like "be careful with console.log in IE, because it will crash your script unless the console is actually visible".
jQuery didn't even incept that, prototype.js did. Prototype is probably the first real jS library that moved the language (along with Dojo, Mochi, etc) from scriplets ("DHTML") to actual UI interactivity. That + XMLHttpRequest ("Ajax") were the direct progenitors to jQuery, which was used to bootstrap or complement all of the early "frameworks".
I came here looking for this comment; it seems prototype is always forgotten about as part of the "before frameworks" discussion. I remember bringing up using prototype to my coworkers in 2006/2007 (the director was a stickler for having clickable buttons that had a specific width on the left and right of the text, so I proposed using prototype to set that automatically). I recall my coworkers being mostly confounded by it and how to use it.
Didn’t Opera and Safari have Dev tools before Chrome? I remember when Chrome got released they had to replace WebKit’s debugger with their own thing, because that’s the only thing they could do to support V8.
Can someone explain what Next.js actually is and why it's so popular? "hybrid static & server rendering" is their main USP but that seems... very minor. In all my single-page applications I always fetch the data from a separate backend so SSR has never clicked for me.
This page is the first time I've heard it explained as a full-stack framework, which sounds more intriguing than just helping me with SSR.
It implements some patterns for rendering in both environments using the same code.
The main problem with rendering in both the client and server environments using the same code is that you need to fetch data in two different places. On the server your code needs to fetch data during the render itself, whereas on the client you need to fetch data asynchronously then re-render with the data once it arrives (which in React means triggering the API call as a side effect, then setting the returned data as state, triggering a re-render).
Unless you really need server side rendering and can't do it statically, Next.js is the wrong choice. IME like 98% of projects are just using it because the tech lead is resume padding or an idiot. The others are something similar to Reddit or Quora with a complex UI and dynamic data that needs to perform well on SEO. For those ones Next is probably a pretty good choice.
Stuff like Next should be the 3rd tool in your arsenal after client and static rendering. It's a bunch of extra complexity for very little gain in most cases.
> The main problem with rendering in both the client and server environments using the same code is that you need to fetch data in two different places.
`getStaticProps` and `getServerSideProps` _only_ run on the server – it's possible we're conflating "rendering" with "data fetching" here. You fetch the data on the server, and send pre-rendered HTML to the browser. You can, of course, also do client-side data fetching (e.g. `useEffect`) as you mentioned.
> Stuff like Next should be the 3rd tool in your arsenal after client and static rendering.
The philosophy of Next.js is that client, static rendering, _and_ server rendering have a place. For certain application holotypes, you might want all static. For others, all server-rendered. Next.js doesn't care - it allows you to choose which strategy you want on a per-page (e.g. route) basis.
This allows you to not have to eject from the framework because your /contact pages wants to be static, while the /dashboard part of your site is server or client rendered. It also helps for incremental adoption.
> You fetch the data on the server, and send pre-rendered HTML to the browser. You can, of course, also do client-side data fetching (e.g. `useEffect`) as you mentioned.
That's only if you're loading the app from the server on every page transition, in which case you may as well use PHP or something to do old school server rendering. The whole point of hybrid SSR is to get a fast first paint but still have the snappiness of client side navigation. The first page loads data from the server but subsequent pages need to fetch it, including returning to the original page. Meaning every page that's both tied to a URL and navigable through the UI needs to support both paradigms.
> The philosophy of Next.js is that client, static rendering, _and_ server rendering have a place.
Their philosophy is whatever will get the most people to use their tool, whether they need it or not. My philosophy is that 5% of apps need hybrid SSR at best and the rest should use something else. All 3 paradigms have their place, but not all in every codebase. The majority of apps don't need static rendering either. And static sites don't need client rendering.
Nextjs is fullstack in the sense that you write "pages" (react for the front-end) and "api" functions for the server. All you do is put these abstractions in files and Nextjs wires up the URL paths based on their file paths...
It's popularity has soared because it eliminates a lot of the routing boilerplate in react apps, and is generally quite pleasing to develop in!
> JavaScript was first released in 1995. Like I mentioned
> above, I started writing JS in 2012, almost two decades
> later, near the beginning of the era I’m dubbing the
> First Frameworks.
> [...]
> This contrasted pretty significantly with mobile apps
> when they started to hit the scene. From the get go,
> mobile apps on iOS and Android were full applications
> written in Serious Languages™ like Objective C and Java.
I'm going to make a small jump to conclusions and guess the author is too young to have accurate memories of what web development was like pre-2010.
Gmail was released in 2004, Google Maps in 2005, Google Docs in 2006. All of those used JavaScript technologies (GWT and Closure) that enabled web UIs to go head-to-head with native applications of the era. There was an entire generation of JS frameworks (maybe two?) that rose and fell before the release of the iPhone.
The primary difference between GWT/Closure and what we've got now is that JavaScript was treated as a compilation target, not a developer platform. The tooling was all in Java or C++, there was no concept of writing a transpiler or bundler in JavaScript and no culture of standalone JS interpreters. IIRC the only option at the time for running JS on the server was Rhino (based on Netscape/Mozilla), which for whatever reason never saw the broad adoption of Node.
Asynchronous, and Node being so HTTP-friendly - I cannot begin to explain the sheer number of regurgitated "build a webserver in Node" tutorials that got written up back in the day.
For whatever reason, you could have done this stuff in Rhino - for better or for worse - it's just that nobody ever took it as seriously.
Not only could you, but some of us even did (though it definitely was never, as you say, "taken seriously"). What made it super powerful (and very node.js-like) was combining it with Jetty, which was a servlet engine that could be used as a library. My (trivial, personal blog) website is still running with this stack (though I finally put it behind an nginx SSL terminator as I have been putting off upgrading Java and Bouncy Castle just couldn't keep up), and it gives me more warm fuzzies than v8 alternatives.
A "people actually used this" framework that had Rhino at its core (well, in one of many ways of using it) was Apache Cocoon (which was maybe more by-default based in XSL/T), only they did something almost ridiculously clever: as Rhino had full support for continuations, they didn't need "callback hell" (or async/await) and could even support pseudo-synchronous code that could block on the user (such as a function which sent the user a form and returned the user's selection, possibly hours later) by storing the continuation state in the user's session.
>A "people actually used this" framework that had Rhino at its core (well, in one of many ways of using it) was Apache Cocoon (which was maybe more by-default based in XSL/T), only they did something almost ridiculously clever: as Rhino had full support for continuations, they didn't need "callback hell" (or async/await) and could even support pseudo-synchronous code that could block on the user (such as a function which sent the user a form and returned the user's selection, possibly hours later) by storing the continuation state in the user's session.
Wow! I'd only dabbled in Rhino back in the day so this is a neat little bit of history. Teleports me back to when this stuff felt fun...
I think it's due to the huge hype around chrome among developers back then. Each tab as separate process was huge. It also has built-in dev tool, and v8 being actually fast excites a lot of devs and drove them away from firefox. So when nodejs was released, a lot of people already know what v8 is and have positive impression of it, probably enough to nudge them to try nodejs.
On the other hand, I never heard of Rhino until now.
I think you've hit the nail on the head; npm was the real killer app - it makes it very easy to try out node and result in a real, usable app with very little code nor (visible) complexity.
Installs in a local folder to the project (node_modules) instead of pip which installs packages to the global python installation unless ran in a virtual env. So getting anything up and running is trivial, compared to the amount of installations and steps needed with pip, unless you wanna bork your global python installation.
With npm it's also really easy (almost too easy) to take your current folder and push it to npm, making the ecosystem bloom with packages.
Virtualenv used to be a third party package, which was a very high friction because you'll need to install it system-wide first (e.g. from distro's package manager) before you can use it to create virtual environments.
Not terrible, but still not as good and easy as npm. For example, you can't make a distinction between runtime and development dependencies, and it doesn't solve circular dependencies. Luckily there is Poetry which exactly does this.
It’s more of Python’s fault that pip’s, but (AFAICT) there isn’t a way to install multiple versions of the same dependency. You might have direct dependency A which needs version <2 of X, but also direct dependency B which needs version >=2 of X.
Since those version ranges of X don’t overlap, it isn’t possible to satisfy both A and B’s requirements. Node can handle this
I stand by the opinion that allowing multiple dependency versions was a major mistake that lead to both ballooning node_modules and abandoned packages getting caught up in your dependency tree just waiting for a malicious actor to hijack them.
In pip or composer, those dependencies have to be forked or removed or they will create conflicts.
Multiple dependency versions causes problems but the alternative is pretty bad, too. You can get stuck on older versions of a dependency because newer versions have a transitive dependency that causes a conflict with a different direct dependency
I feel like that's at least a solvable problem that makes itself obvious when the dependency is added. Multiple coexisting dependency versions sounds like a ticking time bomb to me.
Suppose I use a LibraryX that provides DataTypeX, and most of the functions in my project operate on DataTypeX. I later add another LibraryY, because it provides a utility function returning DataTypeX. I should be able to take the result and use it anywhere in my existing code. However, if my direct dependency on LibraryX is a different version than transitive dependency on LibraryX through LibraryY, then it may not have the same functionality. In trying to avoid a problem at compile-time, the package manager has introduced a huge potential problem at run-time.
Declarative dependency management. Every Node project has a package.json file, which is the first thing that I look at. It gives you so much information at a glance, and it allows for reproducible builds with just one command.
With pip you have to resort to hacky solutions like like pip freeze. It also doesn't solve circular dependencies. Luckily these days the Python world has Poetry, which exactly solves this issue, and might be even better than npm. Unfortunately it's third party and adoption is a bit slow, but I use it for all my projects.
Don't know nowadays, but a few years back when I was still using python something that drove me nuts from pip was how bad it was at managing transitive dependencies.
If package A depends on package B 1.0 and package C also depends on package B but 2.0, the order in which you run pip install for A or C will lead to a different version of B. And of course either A or V would break as soon as they hit an incompatibility. Obviously you would notice that only by running the application or tests.
So you have to use pip freeze to kind of generate a semi lock file,and every project uses it in a different way, because you also need different dependencies files for dev and production....and these are just plain TXT files which I don't think it is the best "format" for this.
Then you have these text files but also a "setup.py" which is for the package you produce, but hey you need to read the txt because otherwise you need to maintain them in two places. So you add a Makefile to tie all of this together, and that's another rabbit hole.
Add to this the mess of virtualenvs already explained in sibling comments and you have the perfect storm.
I know that nowadays are things such as Poetry, which work a lot better, but there are a good bunch of tools competing with each other.
To make an analogy, npm feels like using the latest, top of the line Macbook while pip feels like using a Casio calculator from 1985 with an external keyboard. That's the gap I feel between these two tools.
So if you ever use python, try first poetry or any of the other tools, pip is a terrible mess.
In 2010 it made it very easy to share libraries which helped Node grow in popularity. I don’t believe it was possible to do anything like this in Rhino without Java packages but I could be wrong. Certainly it wasn’t as easy as with npm.
Maybe it didn’t have package signing, lock files, or deduping, but clearly it was popular in spite of those faults.
Oh it was mocked back then too—mostly for the pre-npm@3 releases that didn't dedupe. If you thought node_modules was big today, imagine what it was like then.
Though it clearly worked well enough to be fantastically successful despite valid complaints about it.
When Node first came out, all of the hype around it was using the same language on the client and the server OR at least managing all of your frontend bits in a language independent of your server side language.
At the time, there were JS/CSS/image minifiers in just about every language IIRC. Doing it with Node was a stronger argument to at least save the frontend side of the house from having to find a way to do them with Java or ASP.
During that time period, Java compile times were so slow that using PHP as a frontend that spoke to Java backends with SOAP services was really, really common just to avoid slowing everything on the frontend down with Java.
For context, the thing preceding nodejs in the hype cycle was ruby on rails. While many great things could be said about RoR, performance definitely is not one of them, especially in the early days.
> IIRC the only option at the time for running JS on the server was Rhino (based on Netscape/Mozilla), which for whatever reason never saw the broad adoption of Node.
There was SSJS on NES/iPlanet/whatever before that. I mean, it existed. It was not really useful and few people even noticed it existed at all, but it did exist.
I am, indeed, too young to have accurate memories there! Of course right after I posted this I started hearing about GWT and Closure, that's a bit of egg on my face. I mentioned Gmail as an important marker, everyone I talked to remembered it as the _moment_ which proved that JS could write full applications in the browser, but I assumed that it was written with an internal framework of some sort (none of my mentors who've been in the industry mentioned it when I brought up Gmail, and there's no mention of it on wikipedia: https://en.wikipedia.org/wiki/Gmail)
That said, I think it's an important landmark and I may end up revising this post to add a bit more discussion about it. Thanks for pointing it out!
The buzzword circa 2006 was "Rich Internet Application" framework/platform and the concept was not even totally new then. It included GWT, but also an Adobe product built on Flash called Flex and some other vendor solutions that compiled to Javascript that I no longer recall the names of. The space was well-defined enough that there was a Gartner magic quadrant for it.
I had a big interest in RIA at the time. The big players were Adobe AIR, Microsoft Silverlight, Eclipse RCP, Netbeans, and I also considered JavaFX--I might be forgetting another one.
Silverlight had the best performance/fit for my purposes and sadly was the first of many to go away, largely due to the popularity of iPhone and these platform/tools being excluded. Too bad Apple only promotes Apple's innovations and actively suppresses others.
Not to toot our own horn, but I'd look into Cappuccino and 280 Slides too (we were YC no less!) and were the first iteration in the GWT era to extend JS itself and transpile in the browser.
Honestly it’s a shame Cappuccino didn’t take off it’s actually a super interesting framework and was (is?) extremely powerful even by today's standards
Personally I feel that Cappuccino is one of the last frameworks that still cared about a kind of interaction design that’s no longer discussed on the web, replaced mostly by more devops/abstraction-oriented discussions.
I manage a web UI programming language in my free time, and the juxtaposition of folks claiming FP ergonomics benefits, then upon my request, showing a static, interaction-less end result whose improved version would obviate their pristine architecture, is pretty staggering. The typical defense is "hey we're not designers" but if you zoom out a bit you realize the whole environment doesn't foster engineers to care about design concerns anymore (barring a niche but valuable vertical of optimizing for payload size). This in turn puts pressure back onto designers who come to expect less and less of what they care about on the web.
Just the other day a newcomer shipped an animated row transition after fighting her framework for 3 weeks. The designer was delighted, but the manager didn't even get the point because he matured in whichever era of JS framework that de-emphasized acquiring taste in interactions.
I myself come from a Flash background, so rather than seeing an upward trend, I see a decline in UX concerns, followed by an incline of devops-related concerns in UI frameworks (accompanied by HN comments saying that in both cases the web should have stayed as a document format, only to end up with an awkward mix of document + app architecture their desktop apps through Electron anyway).
If I were to categorize these "eras", I'd rather take the perspective of wondering at which point, and why, framework process ended up more important than the product. Heck, a similar thing is happening on native too, unfortunately. Where did all the interaction designers go?
Maybe AR would nudge more folks to learn and focus on rendering, gestures, transitions, framerate, intent and the rest.
No worries, as you weren't working then, but to give some context, what you have in the "first frameworks" I would probably call the third generation of frameworks. So the breakdown you have is nice, but probably only covers the second half or maybe third of the story.
GWT wasn't really a javascript framework - granted it was more of a framework than something like emscripten, but from a "developer writing code conforming to a defined framework structure" perspective, there's not a huge amount of javascript involved.
Furthermore, there really wasn't very widespread "community" use of GWT (mainly Google, and outside of that, mainly oldcorps working at similar scale to JS-ify old corp codebases), and even Closure was mainly leveraged by the community as glorified early babel / webpack type tooling, rather than a full range of things, e.g. Clojure.
All that said, calling React a "framework" is a big stretch, which makes the title questionable while one is reading through the components section, so I guess one could get away with including a few not-framework-ey things.
But... overall I don't think the author's age hampers them as much as you make out: when I started programming in JS circa 2002, nothing existing in that ecosystem was really comparable to today's frameworks, so comparing them here would add little.
Around 2000 it was possible to write AJAX applications with xmlhttprequest using JavaScript to achieve no refresh apps in the browser.
Folks are building with a 20+ year old idea that has continued to evolve, in part because JavaScript is ancient in internet terms but uniquely positioned as one of the only languages (if you could call it that at the time) that was web first, instead of a traditional programming language having to connect to the web via a framework.
Ironically, the core feature for web apps in the browser to enable this existed thanks to Microsoft.
Brutally simple, efficient and likely part of what gave rise to so many JavaScript frameworks since people generally had to roll their own.
I’m sure there might be some here who reverse engineered what Outlook Web Access was doing.
“ The concept behind the XMLHttpRequest object was originally created by the developers of Outlook Web Access (by Microsoft) for Microsoft Exchange Server 2000.[4] An interface called IXMLHTTPRequest was developed and implemented into the second version of the MSXML library using this concept.[4][5] The second version of the MSXML library was shipped with Internet Explorer 5.0 in March 1999, allowing access, via ActiveX, to the IXMLHTTPRequest interface using the XMLHTTP wrapper of the MSXML library.[6]”
Building an app in the browser was not a popular idea partially because of the instability of high speed internet and the lack of performant mobile internet, and if imaginable, the lack of users on the web at that time. The first major rush of users online was likely Facebook.
Still it was possible to build a full ms office UI clone working in the browser, except it was powering your custom app.
Sometimes things are gaining popularity for a long time before they suddenly get discovered. This single call was a reason why jquery became so popular.
What I enjoyed about this article was how it speaks to an internet generation of tech or users emerging every 2-3 years, something I have long felt. Everyone starts somewhere, everyone is new to learning something and those experiences are worth sharing for new developers who do not quite have their compass in place yet.
I was doing JS with frameworks circa 2006. I remember mooTools, Dojo Toolkit, Prototype, jQuery, and some others that were around before 2010. Unless we have very different meanings for the word framework. I consider Prototype, Dojo Toolkit and mooTools frameworks while I think of jQuery as a library.
I worked at a company around 2001 that was doing a full "Ajax" style frontend for a dashboard product for some industrial control systems. But it worked in IE only, as the Ajax pieces were not available on the other browsers yet.
Memories. I remember discovering any of these existed after doing an entire AJAX frontend site with raw JS that continued to work cross browser for the next 10 years. Made me full appreciate the value of those frameworks. IIRC JSON wasn't even really a thing yet.
I don't even think mooTools and friends were really frameworks as we know them today. They were really just some kind of standard library that let you plug in fancy UX widgets and stuff... I dunno if the distinction really matters though. But I do know they weren't even in the same league of frameworks like angular or react.
I guess the difference is these new frameworks are all about letting javascript generate virtually the entire page. MooTools and friends were designed where the majority of the page was old-fashioned HTML being spat out by the backend.
It's not clear that writing tooling in Javascript has been a win.
I do hope that we can get back to that "JS as compilation target" model eventually with WebAssembly. Even with improvements like TypeScript slathered on top, it's not fun writing Javascript, the tooling sucks, and it's vastly less productive than better developer ecosystems.
> IIRC the only option at the time for running JS on the server was Rhino
Not really true[0]. You could run server side JavaScript with JScript[1] on IIS as far back as the days of IIS 3.0, circa 1997. JScript is ostensibly JavaScript and tracked the original Netscape releases and then the ECMA standards.
[0]: depending on your love/hate with Microsoft at that time :)
> Gmail was released in 2004, Google Maps in 2005, Google Docs in 2006
Lots of dynamic (and complex) web-based CRMs were competing with each other in 2000. At my job, we were doing what is called "HTML over the wire" today by posting forms and using a frame as the target.
Netscape Web Server supported server-side JavaScript since the mid 90s. Rhino was a development intended to provide JavaScript support to Netscape's all-Java browser ("Javagator"), because at the time Java was clearly The Future and we would all be running it on our desktops.
One of the funnier things about Netscape's server-side JS "LiveWire"...
LiveWire's unpopularity and subsequent death was often attributed to its need for compiling and bundling steps, which seemed cumbersome to the JS devs at the time.
I wasn't on the gmail team but my understanding from friends that were is that the Java transpilation in Gmail is for the backend, to share model and business logic, not the frontend.
I wasn't aware of anyone using GWT outside of Google. Prototype.js + Scriptaculous was what really started the JS craze IMHO, followed by jQuery. Then came the increasingly more complex MooTools and YUI and Ext.js and friends, though nothing really took off nearly as hard as jQuery did. Backbone is probably also noteworthy as the bridge between jQuery spaghetti and the structured frameworks we see today (on the library consumption side). Knockout.js also deserves a shout out on the front of library authors looking for better abstractions.
A bunch of people messed with Rhino (IIRC Jaxer was one of the bigger ones), but Rhino had a bunch of quirks. For example, strings were Java strings, meaning that length is obtained via `"foo".length()` instead of `"foo".length`. Perhaps the biggest showstopper was the JVM variable limit per class file. Compiling large enough Rhino JS code would yield class files that crashed due to that limitation. And since JS didn't have modules back then, big balls of code were the norm.
Back then, the divide between frontend and backend was also wider. "Full stack" and the uplevelling of frontend folks towards backend skillsets wasn't really as popular as it is today. Node was also seen as revolutionary due to its async I/O first philosophy, whereas Rhino was more or less just a worse Java.
I used GWT at one company for a bit. It was a mixed bag sort of like maybe React-Native today, not so much in how the tech works but in the way lots of things work and things feel different or have unexpected seams. I remember at the time thinking it was quite impressive for how much it could actually do.
I work at a ~1200 person company, been using GWT since I think 2012, before I joined. It's a mixed bag - it's clunky as hell sometimes, and we have been iteratively replacing it with React in places. Buuuut at the same time I'm often marveling at how amazing it is what they accomplished getting Java->JS compilation working like that. It's a very productive framework if you know how to actually use it. And that's tough to do
I wrote an app in GWT in 2011-12, and there was an existing sibling app also in GWT.
It worked. It let me use my existing desktop app experience (Java, C#, C++) to write code that had a familiar style ( `myButton.setText("Click Me")` ), and build very desktop-style apps that ran in a browser.
But after having learned JS and Backbone, and then React + Redux, it was clear this was a much better way to build apps in general. (Obviously I became biased towards React and Redux personally as shown by my involvement with those tools, but it truly was a big mental shift in how I approached writing code in the first place.)
React and Preact really are nice. I’ve been building native and web apps and services since y2k. Preact, combined with Typescript is probably my favorite tech yet.
Though, I’ll note that I do really miss VB6 and C# Winforms for RAD.
It took MONTHS to become proficient at early-ish frameworks like GWT, Dojo, Marionette, Angular, Knockout, Ember, Enyo, etc.
Getting up and running on React in a couple hours and almost completely understanding the entire API inside a couple days was incredible. The fact that the code was faster and had fewer bugs too was almost too much to believe.
Knockout was definitely easier to get started with vs other frameworks of the time, but still not easy by any stretch. It took time to master the template DSL, debugging templates would take you all across the guts of Knockout, and complex 2-way bindings could have you spending hours debugging them. Getting good performance was also very tricky.
You could read every scrap of documentation in around an hour or so. There were only around a dozen-ish APIs to learn along with only a couple "unique" concepts like controlled inputs, refs, and JSX.
Meanwhile, there was never a need to step into React code unless you believed React itself was buggy (I only came across this one time and the bug had already been reported and was being worked on). Even better, React code was usually faster than Knockout before optimizing stuff and the ways to improve performance were generally pretty obvious.
Prototype.js + Scriptaculous was what really started the JS craze IMHO, followed by jQuery. Then came the increasingly more complex MooTools and YUI and Ext.js and friends, though nothing really took off nearly as hard as jQuery did.
You forgot Dojo, which was the first big javascript framework.
We have a different recollection of the order of events. I was doing web dev professionally as of 2004, and how I recall it is this:
Originally people had utilities files with a bunch of javascript convenience functions copied from random blogs that they would use to enrich server-side generated pages. This is how I wrote web apps in 2004-2006: php-generated html with hand-rolled js to enrich it.
Out of those grew the first generation of libraries (not frameworks) like prototype, mootools and finally jquery (which was so good at being a web swiss army knife that it replaced every other library).
The libraries were ok to add a bit of interaction but not at building entire UI. The “write your whole UI in JS” approach I remember being popularized by dojo and yui / yui-ext / extjs. GWT was a big hype but indeed not used by many. Lots of people used dojo and extjs though. I switched to ExtJS as soon as it arrived on the scene in 2007.
Those early frameworks only solved the UI problem, they were not great at page lifecycle and backend interaction, so they relatively quickly got replaced by application frameworks that did, like backbone and angularjs. Their mistakes became the inspiration for the second generation of SPA frameworks that we are still using today.
My recollection was that Prototype.js got a big boost in popularity early on on the back of its inspiration from Ruby on Rails (in the sense that abusing prototype pollution to make DOM elements have useful methods was novel and cool). Dojo and friends were comparatively obscure/niche until much later. I recall only reading about Dojo years later, during the whole Comet hype.
My impression of the era was that visual pizzazz was all the rage, and Scriptaculous really delivered on that front (Flash was also huge back then). Whereas full blown web apps were relatively rare and a lot of library consumers just didn't see the point of things like modularization (despite the interest in "proper" engineering from library authors like Dean Edwards et al)
And even then, once interest in thick clients grew, Ext.js had a lot more fanfare among the heavier frameworks than the Dojos and MooTools, due to its focus on enterprise.
GWT was used pretty widely by "the enterprise" outside of Google. For a long time, it was a large community with heavy traffic on mailing lists and stackoverflow. GWT was featured prominently at Google I/O for several years.
I wandered into the comments to find or write the correct "before times" bit, and I think this covers everything I would've mentioned.
I'll add that looking back, EXT seemed to be a bit ahead of its time. Its data/table view rivals AG Grid [0] of today. If we could've just standardized on a table view by now, but alas.
It was pretty heavily used in enterprise on applications from around 2006-2012. I still have nightmares of it, as since it's enterprises the code bases got massive and GWT in my experience had a trend of getting a ton of code smells.
A nitpick, but MooTools is closer to the Prototype.js era than jQuery - we used both extensively at freewebs.com (a large WYSIWYG online website builder) before ultimately moving towards jQuery down the line after it took off.
As to frameworks, I know nothing. As to Javascript libraries and their order of appearance it was: YUI in Feb-2006; then JQuery in Aug-2006; and finally Mootools in Mar-2007. Not a developer but my recollection is the same as yours with regard to JQuery -- it roared to dominance seemingly overnight.
I don't remember the original Gmail having a rich editor in the compose view (I've been trying to source some screenshots but can't seem to find any with the compose view), but I do remember it being pretty impressive for the time. There definitely were a few libraries pushing the envelope back then.
SproutCore for instance was around in 2006 and Apple built it's first version of MobileMe on it[1]. Prototype.js[2] first came out in 2005. I believe it was Prototype.js that first popularised the dollar sign $() for CSS selectors, or was it cssQuery[3]? Prototype also had Dojo[4] as healthy competition right from the start.
There's a framework that always seems to get forgotten, but was there before Backbone, Angular and others: the Dojo Toolkit [1], released in 2005, it had some goodies like built-in tooling (that was hell to work with) and modules (in 2005 they were godsend!) with RequireJS.
We chose it in my company in 2008 before the framework boom and it had served us well for a very long time. It's batteries included, has for example it has a very comprehensive i10n module, which was not usual at the time.
Also worth mentioning it was started among others by Alex Russell [2], a famous developer advocate at Google.
Just search HN for "scaling server side rendering" and you'll land on a bunch of practical complications.
That doesn't mean SSR is bad. It just means we know the solution but stuck with the wrong tools.
My hypothesis is that we'll capitalize WebAssembly to run our UI rendering logic and a tiny platform-specific rendering layer to translate rendering commands from WASM to platform. Interesting side-benefit: Language choices other than Javascript.
I've already started working on a proof-of-concept React-ish library that runs on a WASM VM. IT lets you specify your UI component declaration and behaviour in Kotlin - https://github.com/joelewis/kwasm
In Spanish there's a saying that goes "Cada uno habla de la feria según le va en ella". It means that everyone tells their story, that they say the fair went well or not depending on how it went for them.
Another comment talks about revisionism and, while I think it is a valid critique, I think it goes beyond that. The author's career starts in 2012 and that's all the reference they seem to use.
Sure, they admit they will "probably going to gloss over a lot" and that they "can’t write about what [they] didn’t experience". But then... is this fair? Or, a better question -since anyone can write whatever they want, of course-, will this be, then, just some person's story or will it actually be representative or a larger reality?
Sadly, it feels like lately a lot of people seem intent in blurring that distinction. They seem to say "I may only have a limited view, but I'm going to present this as if this was the complete reality". And this is what this article does, I'm afraid.
The fact that there's is absolutely no mention at all of Dojo is telling. It's also quite telling that dismissing claim of "throw together some scripts for a few UI widgets, and call it a day", the quite absurd "everything was global", and the error of suggesting XHR came later -"As time went on and XHR was introduced and popularized"-.
I actually have a friend who wrote in Dojo, so was aware of its existence, but had no idea it was so influential/early in the First Frameworks era. Same with GWT/Closure, as has been mentioned by others. I did run this article by some mentors who have been in the industry since the 90s before posting, as I wanted to make sure I didn't gloss over it entirely, but unfortunately it seems they didn't experience those either.
And I think that's the core of the issue, even people who were around at that time do not remember all of these things. Ultimately, even those of us who are trying our best are going to miss details, and this is only going to get worse as we get further and further away from the beginning. Honestly it seems like this is a job for historians, and unfortunately I am not one, just a dev trying to share my thoughts and experience
> According to Wikipedia, XHR was introduced in 1999, 4 years after JS was introduced
Your way of commenting on XHR in this paragraph...
In this environment, it’s understandable that JS was generally seen as a toy language and not something you’d write a full app in. The most common thing you would do was include jQuery, throw together some scripts for a few UI widgets, and call it a day. As time went on and XHR was introduced and popularized, people started to put parts of their UI flow into a single page, especially for complex flows that required multiple back and forth interactions between the client and the server, but the majority of the app stayed firmly on the server.
...where you are talking about jQuery already being a common thing, which implies at the very least 2006 but more likely 2008-9, and then writing "As time went on and XHR was introduced and popularized", suggests the idea that XHR somehow was introduced much later, when jQuery was already common.
This is what I was referring to. It may have not been intentional, but the way you comment and present it suggests a mistaken timeline.
That's a good point, definitely not what I meant there. I think in my first draft I actually just said "JavaScript widgets" and when I updated it to jQuery I didn't update the rest of the paragraph. Thanks for pointing that out!
For me 2012 was the year I stopped any frontend work at all. As I remember, things felt very easy and natural when all I had to do was output html using templates, write CSS and add some touches of javascript here and there, either using jquery or mootools. Maybe a websocket to display something coming from a process. Then there was backbone, history push state, more frameworks, client side rendering, meteor, and a lot of impressive stuff. Very impressive stuff that felt needlessly complicated and made me procrastinate every time I tried to learn it.
Nowadays, every time I look at a react codebase I feel certain emotions I can only describe as disgust. Maybe I have only seen bad codebases.
I don't think you're alone. I felt the same way about overcomplexity until I had a few runs at working on already established complex frontend codebases. What seemed to happen around 2008 onward is that the basic principles of the web were sort of simple, but then to do anything at a larger scale it got pretty crazy quite quickly, and so new architecture ideas came along to address that by people who were in the business of solving engineering type architecture problems.
For any site of inherently simple interactivity, it's always been as easy if not easier than it ever has, but now it's also more manageable if you know you're going to need to scale a certain way.
It doesn't necessarily take all that much before you can start to see the reasoning. For example, take a humble grid of products, each with their own add to wishlist button, and a profile preview button in the corner of the page that indicates how many things are on your wishlist. Pretty simple to handle, render the thumbnails with unique ids and make an XHR request that stores the data with your account. Update the wishlist total count however you would.
Now suppose though that each thumbnail in the grid can open a bigger preview dialog that has more images, a bigger description, and it's own add to wishlist button. You can click that button, and it does the same thing. You close the dialog, but now your grid item needs to reflect that it's already been added to the wishlist. These things get really tiresome to keep building, something that I'm sure isn't new to you if as you say, you've been in software a while.
Sorry for the book, I mostly wrote that to challenge myself to think it through, not to imply you couldn't think of how it would be necessary to componentize things.
I'm not particularly fond of React more than Vue or anything, except for the fact that they both allow you to define UI as collections of functional state machines when it's necessary to do so.
I do totally get the point of using a framework like React or Vue to manage state on a complex app. I do purposefully call them apps, because websites are a more general term. Hand woven javascript UI, even if it was using an utility framework like mootools could get out of hand pretty easily. I recall things like extjs that were also popular.
Following my own example, managing push state by hand was tricky. So I did buy in on the premise that an opinionated way of structuring help and more importantly state was necessary. But I have been consistently failing to learn any new frontend tool ever since. This was not terrible professionally, since I mostly do what most refer to backend or systems. But still it is a bit frustrating not being able to follow along. Maybe it would be easier if this was 'it' when I started learning as sometimes it's difficult to forget and relearn.
Speaking of React / Vue codebases, I have thrice tried to contribute some changes or fix a bug on different projects and the amount of boilerplate I had to go through felt completely unnecessary and overkill. Maybe the pattern on these never 'clicked' or I was very unlucky to stumble unto bad examples. It's very easy to dismiss something one does not understand as unnecessary complex so I am still open minded about it. The feeling of disgust when I see the many levels of inference, types and juggling state around for UX that I see as pretty basic persists, though. I like the result, I abhor the execution.
I would think that “feeling disgust” and ”being open minded” are mutually exclusive. So my impression from your post is that you are not being honest (to us or to yourself) about being open minded.
I do not see why these are exclusive: When I read the code, I can't control feeling disgusted by what I see. Specially how every base starts with an opinionated and strong "this is how it's done" style, just to devolve into copypaste and hacks because someone didn't understand state, reductors, types, dispatchers, ... but I am open minded about acknowledging that the problem might be mine, be it because of stubborness on not getting it, or being extremely unlucky on what projects I stumble upon.
> Now suppose though that each thumbnail in the grid can open a bigger preview dialog that has more images, a bigger description, and it's own add to wishlist button. You can click that button, and it does the same thing. You close the dialog, but now your grid item needs to reflect that it's already been added to the wishlist. These things get really tiresome to keep building, something that I'm sure isn't new to you if as you say, you've been in software a while.
I've done this many times, using plain-old jQuery and server-side rendering, and it really isn't that hard. The "conventional" way is to (of course), render the preview(s) with classes or data attributes on the updatable elements s.t. you can quickly identify the elements that need to change (say $('.wishlist-count').text(updatedCount) for the sake of argument).
For more complex things (let's say you need to be able to insert a complicated, but slightly different, object in the wishlist, for example), you can render a template into the page, dup it on wishlist addition, and populate the variable data in any number of different ways. You can even create JS objects that encapsulate this kind of logic (e.g. Wishlist.add(itemNumber)) without much additional effort. No framework required.
Now, I grant you that when you need to do this for many different kinds dynamic elements that all interact in different ways, or when you need to absolutely guarantee minimal re-rendering, you might want to jump to a framework. But I still feel that most front-end people these days instinctively rule out simpler approaches that would work just fine, because they're prematurely optimizing. Or worse...because they simply don't know anything other than React.
React is awesome, but there is a learning curve to using it well, moreso since hooks came out.
Being able to define your view as a pure function based on your state is a very powerful.l abstraction, but it took me about 2 years to learn to wield it well.
Maybe there are no good react codebases because it encourages bad code.
The whole concept of having both code and structure definitions in the same file is just flawed at its core. Like deliberately writing all your js in html script tags for some reason, except with functional-style syntax that just makes it look more cryptic to newcomers for no reason at all.
Building front end apps has become more complex than it used to be 20 years ago to effectively output the same html.
Granted there is a level of interactivity that is different for the complexity, mostly I look forward to the grand complexities of todays frameworks to continue to simplicity and be approachable.
As soon as you need to 1) render a list of widgets asynchronously, 2) update widget #182 of 250 without re-rendering the whole widget tree, you start to realize that these front-end frameworks have solved the problems that we used to spend hours writing fiddly and confusing jQuery functions to address.
Not sure what you find 'disgusting' about a function that returns HTML; if anything it is more 'natural' than the templating and jQuery amalgamations of the past.
The thing that bothers me about React and other frameworks is the look of the code. React components look like every other React component. There are few signals of “hey, I’m a dropdown” or “hey, I’m a table” due to caked on layers of abstraction and indirection. One thing I like about serverside code is that a tree processor looks like a tree processor while a state machine looks like a state machine. I don’t have to think hard and can use pattern recognition
Maybe you will like https://svelte.dev/, I find it more close to good old html. For example, a component that is not interactive is basically an html file with an <style> tag and some html markup.
I feel the OP. It is not about HTML alone. It is about the lack of understanding of the full picture. About the fact, that you cannot rationalize everything. That everything is three layers away.
The problem with the OP feeling (and mine) is that there are shoulders of giants. You either stand on them or not. If you are not, you start on much lower level of features ;)
Makes sense and I agree. For simple things I still do vanilla js.
As soon as I need to re-use components or shared state between pages I go with sveltekit.
I started building websites amaterishly from about 1995, and professionally from about 2001, and always hated how complicated and messy my code became any time I wanted to build rich functionality (i.e., a web-app rather than a website).
That first changed for me when I discovered ExtJS (now Sencha) in 2007, then later Angular and finally React in 2017.
These days I work almost daily on a React web-app I've built for displaying realtime weather/climate data for farmers, and it continues to be a very pleasing codebase to work with, more so than any I've worked on before.
I'm in love with the design of that website. It's clean, there are subtle graphic changes such as the pixel art that changes when you toggle the light switch, a really fantastic job there (one small remark, hovering over the pixel art on Chrome makes a scroll bar appear due to the transform). I want one.
It's also proof that you can make a simple and pleasant experience with a JS framework, if you focus on the essentials, there's no need to boycott JS entirely in favour of the old web, these frameworks get rid of a lot of the boilerplate when starting from scratch.
I'm an avid supporter of SvelteKit (the framework used on that website) and how they want to make the web less SPA/JS again. In this example, navigation is fast and client side, but can fall back to SSR if JavaScript is disabled, fails to load or hasn't loaded yet. There is no heavy runtime with virtual DOM diffing. Resources are cached and a page reload only sends ~17 kB over the wire on a large blog post, showing an excellent use of Tailwind CSS. It renders on Cloudflare Workers close to the user wherever you are in the world, with zero vendor lock-in if you want to stick it on a VPS.
Why do people mention so often about js being disabled? It’s such an insignificant use case imho. Ssr(in js world) is mostly for public pages who get scanned by search bots, right?
Can't agree more with you. In my more than 20 years in this industry I'm still to find one single person at work, or a single customer with JavaScript disabled.
At this point if you have JavaScript disabled is your problem.
It's like having a car and not wanting to put gas on it and pushing it around and complaining why you have to push your car.
Not saying we don't abuse its usage, but having it disables is just extremist
A website that is able to function without JavaScript increases its accessibility, that doesn't mean that the user explicitly disabled JavaScript. You could be on a train in a 5G-equipped country with an unreliable connection. Have you came across a website having problems with stylesheets completely missing, due to CORS, caching, etc?
If the document is able to carry out navigation, without having to rely on downloading a non-negligeable amount of JS to hydrate the page, it improves the experience for that 90th percentile enourmously. Us web developers are often privileged with a very good internet connections. It's not necessarily anti-JS thinking, and SSR for crawlers generally as no longer been relevant for a number of years, it improves UX.
Edit: this also reminds me of [1], a 8.5 MB HTML file with 27.5k tweets was faster to paint than a single tweet in a React application. It depends on whether the UX can be improved by using more JS, for most websites I think less is more.
I would be very keen to know if there are any of these "full-stack" frameworks that don't depend on NPM, or more specifically built with Deno or vanilla JS in mind?
It feels like (to me at least) that at this stage it is quite clear that using NPM is an anti-pattern that is best avoided if possible (security, requiring a "dev machine" with the right version of NPM installed etc, general bloat)
I know that there is nanojsx (https://deno.land/x/nano_jsx) but would be keen to know of any other examples that anyone knows of?
> It feels like (to me at least) that at this stage it is quite clear that using NPM is an anti-pattern that is best avoided if possible (security, requiring a "dev machine" with the right version of NPM installed etc, general bloat)
For all it's problems, it's still is the killer feature that makes it easy to develop JS apps. The things you mentioned can be mitigated with proper practices.
1. Security: Supply chain attacks can be mitigated through being deliberate about versions and making sure your CI systems always install a "frozen lockfile"
2. Requiring the "right" version of NPM: Can be easily solved through "engines" in package.json. You can basically tell your project to not run unless the dev has the right version of NPM. This is not that big of a deal since a dev can just install the correct version with npm. You can take this a step further with yarn and pin a specific binary in your project so it doesn't matter what version your devs are running, they will automatically use the binary you specified inside the project.
3. Performance and Bloat: Besides NPM, there's also Yarn and PNPM (Performance NPM) that both work much faster than NPM and are fully interoperable with existing package.json's.
The ecosystem is still not perfect and security is still the biggest issue. The other issues you mentioned though can be easily mitigated through good practices.
Personally I think we already exceeded the sweet spot. Things like jQuery were merely abstractions and shortcuts, but didn't bring much to the table. In the end you had to do all the work. On the other end things like Next.js do so many things up to a point at which you start working against them to achieve certain things whilst ending up not using 80% of the framework because they are aimed at basically every possible case without being really specialized. It's mostly about accessibility these days, like getting started fast. While I don't quite agree with the clustering and categorization (as already mentioned by other comments), for me it feels like the ideal point was somewhere between era two (Knockout) and three (Vue, React), with a tendency to the second era.
The sweet spot is still there, in theory. React itself is just a few functions forming a very simple (but not necessarily intuitive) abstraction.
The issue is the community is batshit and it's almost impossible to find or build a team that's going to democratically decide to use a sensible approach. If you want to keep a simple codebase on a React project your three options are build the entire thing yourself, be the best interviewer of all time and find a one in a million team, or be willing to be an absolute nazi and piss off a bunch of confident amateurs that want to overengineer everything.
If you can somehow avoid ending up with 20 other shit dependencies then React is a big upgrade over the frameworks that came before.
Lee from Vercel (Next.js) – could you share some of things you feel you're working against the framework for? Open to any feedback. It's indeed a tricky balance between having lots of options vs. having the one "paved road" for everyone to take.
Also, I like to think of Svelte as the successor to jQuery, as it's the closest to "just vanilla JavaScript" I've seen (yes, I know there's some non-standard JS syntax in there).
Hey Lee, is there anything comprehensive you can point me to to diagnose performance problems in a next.js app? We have one and it’s brutally slow and I can’t seem to figure out the issue.
1. DHTML scripts: individual scripts that provided functionality e.g. a date picker. You grabbed the scripts, and wired them together on your pages to enhance your page. Includes the first generation of Ajax scripts (in page communication with the server, often using raw HTML, text, or XML). Hidden iframes and other techniques also used for server communications.
2. jQuery: the popular library that everyone used because it provided a fabulous API to access and modify the DOM, plus helper methods to abstract out browser differences and bug workarounds. Bringing Ajax to all web developers, allowing them to enhance the pages delivered by their backend web server of choice (PHP, RoR, etcetera).
3. component framework (Cambrian explosion): mostly enhance pages delivered by the server, each framework with a unique approach to its API. Pages use components designed for each framework. YUI, Dojo, jQuery UI, Mootools, ExtJS. Starting to see more Single Page Apps, but no widespread usage of any framework on large numbers of sites.
4. React (and other 2nd gen frameworks, mostly virtual DOM): fully component based, can easily deliver an SPA (Single Page Application) and often the server only really delivers JSON (no HTML pages except a blank container). Widespread usage of React in industry.
There were plenty of early adopters for each technology, but as far as I recall, widespread usage follows the progression above. And the above ignores plenty of important first innovators and minor steps (for example, I used script.aculo.us).
The first stunning example was back in 2000 which was Outlook Web Access on Internet Explorer 5: the first usage of XMLHttp and it was many years before anything else approached its sophistication as a (mostly?) single page app with complex updates. I presume it had a proprietary component system, and IE5 was enhanced to make it work smoothly.
The front-end world has been relatively stable since then. Sure, there have been experiments with other approaches (Cycle.js, Elm, Svelte, ...), but by and large React and its contemporaries are still by far the dominant players, and while they have evolved as well, their mental model is still largely similar, so I'd group them in the same "era".
I would class those as era #3. There was a huge variety of innovation, and some libraries/frameworks had relatively more success (angular, backbone) or less success (qooxdoo, sproutcore). I think industry usage broadly follows the four steps I gave.
The amazing thing is that everything was there back in 2000, and OWA showed the way. AFAIK IE5 had all the features needed to deliver an SPA, albeit the techniques to reliably and performantly take advantage of IE took a long time to either discover or to percolate through the industry. I remember people discovering almost hidden IE features all through the 00’s, and then taking advantage of those features. I personally recall IE5.5 definitely had all the DOM features I needed for a component framework, since I remember angrily writing minor workarounds specifically for that version.
The vast majority of web developers were glued to their particular choice of HTML backend, so industry adoption of front-end frameworks was hideously slow.
React was when frontend JavaScript frameworks appeared to me to become really mainstream, rather than just early adopters (era #3 of my list). My own progression was script.aculo.us -> dojo -> personal custom framework. My custom framework had major advantages for me over dojo (better: performance, reliability, flexibility, improved UI, development speed).
Each individual developer will have their own view of how the industry progressed, but this is how I perceived it as a generalisation.
My ecmascript/js journey switched tracks into framework land with backbone + requirejs circa 2010/11 .. Appreciate there was prior (and parallel) art, but for me that combo really presented a seismic shift in terms of seamless and integrated js application dev, ready for a post-flash/jquery/ie6-8/browser-hackfest world.
I wouldn't dare comment on how far we've come since the early days of web scripting, or frameworks for that matter, but for all the talk of added complexity I'd sure say it feels a lot easier (and infinitely less hacky) these days.
This is a nice brief write-up, thank you. i
It helps this non-full time web programmer contextualize recent changes, and lends credence to my decision to learn SvelteKit (skipping over the third gen view frameworks).
I would have liked to see some discussion of what is next. For example, where does WebAssembly fit in?
Lastly, a minor critique re.:
> That said, I can’t write about what I didn’t experience
Yes you can, it’s called historiography using primary and secondary sources. It’s a lot of work, but certainly doable, especially when so many of the participants of the history in question are still alive; you could interview them if need be.
I started out web-development in 2001 (recently worked for Apple as a senior front-end engineer), and to me the 4 eras of JavaScript are:
1. Form alerts and confirms
2. Ajax, jQuery, and plugins
3. Frameworks, from Handlebars to JSX
4. Revolution: TypeScript
I remember a time when JavaScript simply wasn't used. Everything was server-side rendered (classic ASP using VB6.0, ancient PHP, Perl, etc.) Eventually it gradually became bigger but its development was stifled by Adobe Flash taking charge of highly interactive UIs.
Then, slowly, JavaScript started to do things. Some companies started working with Ajax and suddenly you could talk to the server while you were on the client. But, for the longest of times, JavaScript was not used like it is today; we did not use it for templating or making components, because we had client-side XML and XSLT doing that with `<xsl:template>` and other such nifty tricks.
XML + XSLT + Ajax + jQuery was the status-quo for many years before we started getting UI libraries. Backbone, Ember, MooTools, and many others started to make life as a front-end developer far more interesting. We went from HTML (and later also CSS) drones to actually needing to embrace programming concepts, architecture, design, and design principles.
We had one big advantage over classically schooled university software engineering graduates: We knew JavaScript, it wasn't type-safe, it was full of little quirks, but it was ours and we had worked with it for many years. We knew it. They didn't.
And then TypeScript was born. At first, it was a monstrosity full of bugs, oversights, missing features, lack of intuitive design, and largely undocumented and confusing. Front-end engineers like myself didn't like it, because WE did not need it. We just saw that those classically schooled professionals suddenly thought they could do front-end, too, except they didn't know about HTML semantics, HTML accessibility, CSS (from floats to flexbox to grid to paint/composite/layout), browser APIs, browser differences, and so much more.
So these... people... came into our domain because TypeScript made them feel safe. They were far slower than us, they made more bugs, the code was unreadable (TypeScript generics are a hell, or in generally accepted TS-syntax: `T<G><A, H>(X<G>)<P><A><<A, B>, C>`) and worst of all, they made everything a `<div>`, including buttons and links and tables and lists and inputs and images.
Then, as the years flew by, TypeScript became more mature (except for their error messages) and it actually became somewhat intuitive to use. The back-end developers who were confronted with the fact that they knew nothing about the front-end have now either adapted and learned, or left, and the world is nice again.
The next big thing for web development and JavaScript is probably going to be the next big framework or library that we don't see coming yet. I love React, I enjoy Vue, I admire Svelte, but I don't think that React will stay around forever (libraries die because developers get bored of them, and new developers think these are getting too old), and Vue & Svelte simply haven't taken off the way I had hoped.
We'll see where it takes us.
In any case, I'll keep learning, I'll keep adapting, and I'm trying to be ahead of the hype train just so that I can keep increasing my $500,000 annual salary (excluding stock options).
I hate JavaScript and everything about it in 2022. The whole ecosystem stinks and the fact that it’s so pervasive makes me lose hope. I blame the whole thing on Microsoft and the IE team.
Very good ideas. If it was executed that way we would be in a different position. Some of the standards and browser implementations improved, many have been half baked or clunky, the JS ecosystem (which is the means to explore and extend) is chaotic and still moving incredibly fast without fundamental progress. I think two things happened since: We still don't agree on how to do interactive UI on the web and we've lost focus of this being a explorative journey that ultimately should result in agreed upon standards that everyone can build and rely on in the long term.
I've been longer (but not much), and in my time programming I believe the biggest difference was pre-jquery vs post-jquery. I use React nowadays, and the jump from jQuery to React was IMHO smaller than the massive improvement to life that was jumping from non-jquery to jquery. Specially when accounting for all the community libraries, you could just plug and play massive projects that would take you months otherwise.
243 comments
[ 3.3 ms ] story [ 278 ms ] threadExtJS, Ember, Angular, and Next are all "full-stack" frameworks and the all were released at very different times.
I would say the "eras" were more like:
Direct manipilation with custom architecture and models (JQuery) -> MVC/P (Ember/ExtJS/Angular) -> Components (React/Vue).
Overall this division seems weird. SSR is neither a revolution, nor universally desirable.
The real revolution is in what these next-generation frameworks like Svelte or SolidJS offer: small bundles combined with high performance achieved through eschewing virtual DOM in favour of precise changes in the DOM.
The big leap forward from Solidjs and Svelte is that they do complex source-to-source compilation to avoid virtual dom diffing. That approach lets them get the best of both worlds - the programmer can pretend their components are pure & reactive. (Solidjs looks almost identical to react.) Thats great because it means there's no bugs due to fiddly or forgotten DOM updating.
But the javascript executed by the browser doesn't need any of react's complexity. The JS output by the compiler simply makes direct DOM manipulation calls when content changes. There's no heavy re-rendering of view trees, and no virtual dom to track. Unlike react, you don't need to apologize for mutating variables or re-render your entire page when you do. So we can do away with redux and all of that. A hello world app in solid or svelte is a few kilobytes, compared to 200kb+ for a react project. And it renders instantly.
It took us a few years to get here, but I'm delighted by the direction UI code in the browser is headed. I hope these ideas make it into native applications.
I've found bugs in my Svelte code just by looking at the stack.
The complex compile-time transforms enable almost no performance improvements.
As a proof just take a look at the js-framework-benchmark table [0], my framework (Voby [1]) is faster than both in the benchmark despite having an API very similar to Solid and no requirement for a Babel transform or other compile-time transform (though the basic React-like JSX transform is supported for convenience).
Those transforms actually exist 99% just for providing some convenience features to the developer. If that weren't the case it wouldn't be possible to make something similar without a transform that's faster than both. In fact Svelte is actually quite a bit slower than both Voby and Solid. Svelte is even slower than Inferno, which is a (very optimized) V-DOM framework.
[0]: https://krausest.github.io/js-framework-benchmark/current.ht...
[1]: https://github.com/fabiospampinato/voby/
Very cool framework though, I'll have to look more into how it works someday
If you'd like to come up with a different sort of benchmark where you think Solid would shine I'd be happy to write an implementation of it with Voby and see what happens. Or you can just try that yourself, the API is fairly similar.
---
I should probably add that js-framework-benchmark is heavily biased toward measuring creation time actually, which is something where compile-time optimizations should shine. If you are more interested in updating things, like you would be in a rich application, Voby is actually some 20% faster than Solid at replacing rows with other rows, because it support reusing of older nodes (opt-in) (this also lowers memory pressure in some cases by the way, no need to make and gc lots of stuff in some cases). This optimization is not supported in Solid nor Svelte, and interestingly it's not a safe optimization that can be applied all the time, so it must be opt-in, but how are you supposed to tell to Solid or Svelte when it's safe to apply it if something like Voby's "template" function, which is also used for this, is abstracted away entirely from you? In some sense the transform actively goes against performance here.
As a rule of thumb if you don't have any API for explicitly opting into recycling it's not happening, it's not a safe optimization that can be applied all the time.
Otherwise, it was very common practice to serve an Ember or Angular app as static files Nginx or directly on a CDN. Wrapping them in a server-side framework was always a bespoke process which required you to effectively maintain two frameworks, and stitch them together yourself (unless you count Ember + Rails in the early days, but even that is a stretch IMO). When SSR was introduced in any framework, it was usually not used to its full potential to be able to accomplish the use cases I discuss in the post, like authentication, API endpoints, etc. It was just used to render the app on the server. It did not fundamentally change the DX of the framework.
I honestly was pretty skeptical of these latest frameworks until I gave them a shot! It doesn't sound that revolutionary until you actually start using them, and things which were previously quite difficult become absolutely trivial. I highly recommend trying them out some time.
I feel like backbone deserves its own era as it seemed like all the cool kids would exclusively use that for a couple years.
Then Angular and a ton of others flooded the scene.
My projects are usually either in the form of "User enters data, sends it to the server, server sends a new page back"
Example: https://www.gnoosic.com/faves
Or in the form of "User changes parameters on screen, Javascript updates the screen accordingly".
Example: https://www.productchart.com/laptops
In both cases, I don't see the benefit I would get from a framework.
If you have built a project that is public and benefits from using a framework, I would love to see it!
- transpiling JS back into the stone age for compatibility
- accessibility
- seamless localisation
I have found I just can't keep track of all of these things as well as React does.
At the same time, I think React is a huge, dependency-laden mess, very difficult to learn (because it's changed its mind on how to do things about 100x, so no responses to issues on SO apply to your version of React, Redux, React Router, etc), slow as hell and probably overkill for most projects...
Once this gets a bit more complicated you have a bunch of state to keep track of and you have to make sure to re-render only the parts that have changed, and deref that parts that should be GCd. I'll happily take on a reactive UI framework dep if I can avoid writing my own diff pipeline.
Not endorsing react by any means though.
The real value of public frameworks comes into play when you have more than one generation of developers working on your project.
It's much easier to onboard a new developer onto a react app than it is to get them to understand the weird bespoke nuances of the conventions you came up with while hacking on your site at 3am 5 years ago.
Sorry but a “framework” used by one project (especially not broken out into a separate subproject) is not a framework. That’s just infra code.
I think your point still stands that the value is developers understanding a framework can more quickly get to work—I’m just triggered by your exceedingly liberal usage of the word “framework”.
Infra code that over time, as your app grows, takes on more and more of the features of a framework
That is why I proposed a discussion based on real life examples.
The other thing is that frameworks change. You picked React for your example. A currently popular framework. Chances are, the next developer will not come on in 5 years, but in 15 years. And does not know anything about React. Or about React as it is today. Then they might have a harder time understanding React than to understand a well written, minimalistic piece of Javascript.
That doesn't seem likely to me at all. More likely in the next 6 months than in 15 years. Why are you planning for 15 years out? The company you are working for might not be around in 15 years. Code might not even be recognizable in 15 years. All of our programs might be written by AI in 15 years.
Optimizing for the short term makes way more sense to me. 2 or 3 years out, not 15.
I don't see any contradiction between creating well written, time tested software and also choosing currently popular frameworks to work in.
If your React app is well written and stable and well tested, I see no reason it shouldn't be available in 15 years. And if you can't find React Developers to hire in 15 years to work on it, that's tough. Pay to have some trained.
It is a similar situation to COBOL is today.
Sure, somehow I’m going to find React developers 15 years from now to maintain my line-of-business React app but how secure will it be?
One could argue that I can rewrite the framework-dependent parts. But rewrites cost money, too.
I love new stuff but I still think that, depending on the app, it may make good economic sense to plan ahead for it to be useful after a decade or two.
https://www.npmjs.com/package/react
Maybe I'm missing something but npm suggests it's only one dependency, which also only had one dependency.
I get that create_react_app pulls in a ton of dependencies, but React itself is not a culprit of dependency hell.
But we definitely have more fun with React SPAs and Go microservices on Kubernetes :)
(Notice I'm listing the shinny toys of the usual 3 layers at every company)
This page is the first time I've heard it explained as a full-stack framework, which sounds more intriguing than just helping me with SSR.
The main problem with rendering in both the client and server environments using the same code is that you need to fetch data in two different places. On the server your code needs to fetch data during the render itself, whereas on the client you need to fetch data asynchronously then re-render with the data once it arrives (which in React means triggering the API call as a side effect, then setting the returned data as state, triggering a re-render).
Unless you really need server side rendering and can't do it statically, Next.js is the wrong choice. IME like 98% of projects are just using it because the tech lead is resume padding or an idiot. The others are something similar to Reddit or Quora with a complex UI and dynamic data that needs to perform well on SEO. For those ones Next is probably a pretty good choice.
Stuff like Next should be the 3rd tool in your arsenal after client and static rendering. It's a bunch of extra complexity for very little gain in most cases.
`getStaticProps` and `getServerSideProps` _only_ run on the server – it's possible we're conflating "rendering" with "data fetching" here. You fetch the data on the server, and send pre-rendered HTML to the browser. You can, of course, also do client-side data fetching (e.g. `useEffect`) as you mentioned.
> Stuff like Next should be the 3rd tool in your arsenal after client and static rendering.
The philosophy of Next.js is that client, static rendering, _and_ server rendering have a place. For certain application holotypes, you might want all static. For others, all server-rendered. Next.js doesn't care - it allows you to choose which strategy you want on a per-page (e.g. route) basis.
This allows you to not have to eject from the framework because your /contact pages wants to be static, while the /dashboard part of your site is server or client rendered. It also helps for incremental adoption.
That's only if you're loading the app from the server on every page transition, in which case you may as well use PHP or something to do old school server rendering. The whole point of hybrid SSR is to get a fast first paint but still have the snappiness of client side navigation. The first page loads data from the server but subsequent pages need to fetch it, including returning to the original page. Meaning every page that's both tied to a URL and navigable through the UI needs to support both paradigms.
> The philosophy of Next.js is that client, static rendering, _and_ server rendering have a place.
Their philosophy is whatever will get the most people to use their tool, whether they need it or not. My philosophy is that 5% of apps need hybrid SSR at best and the rest should use something else. All 3 paradigms have their place, but not all in every codebase. The majority of apps don't need static rendering either. And static sites don't need client rendering.
It's popularity has soared because it eliminates a lot of the routing boilerplate in react apps, and is generally quite pleasing to develop in!
Gmail was released in 2004, Google Maps in 2005, Google Docs in 2006. All of those used JavaScript technologies (GWT and Closure) that enabled web UIs to go head-to-head with native applications of the era. There was an entire generation of JS frameworks (maybe two?) that rose and fell before the release of the iPhone.
The primary difference between GWT/Closure and what we've got now is that JavaScript was treated as a compilation target, not a developer platform. The tooling was all in Java or C++, there was no concept of writing a transpiler or bundler in JavaScript and no culture of standalone JS interpreters. IIRC the only option at the time for running JS on the server was Rhino (based on Netscape/Mozilla), which for whatever reason never saw the broad adoption of Node.
1. V8, which is actually really fast
2. Hype around being _asynchronous_ at the time JS itself started to become more hyped up.
For whatever reason, you could have done this stuff in Rhino - for better or for worse - it's just that nobody ever took it as seriously.
A "people actually used this" framework that had Rhino at its core (well, in one of many ways of using it) was Apache Cocoon (which was maybe more by-default based in XSL/T), only they did something almost ridiculously clever: as Rhino had full support for continuations, they didn't need "callback hell" (or async/await) and could even support pseudo-synchronous code that could block on the user (such as a function which sent the user a form and returned the user's selection, possibly hours later) by storing the continuation state in the user's session.
Wow! I'd only dabbled in Rhino back in the day so this is a neat little bit of history. Teleports me back to when this stuff felt fun...
On the other hand, I never heard of Rhino until now.
With npm it's also really easy (almost too easy) to take your current folder and push it to npm, making the ecosystem bloom with packages.
I admit that I'm not a Python engineer, but I have been in the past—twice!
Since those version ranges of X don’t overlap, it isn’t possible to satisfy both A and B’s requirements. Node can handle this
In pip or composer, those dependencies have to be forked or removed or they will create conflicts.
Suppose I use a LibraryX that provides DataTypeX, and most of the functions in my project operate on DataTypeX. I later add another LibraryY, because it provides a utility function returning DataTypeX. I should be able to take the result and use it anywhere in my existing code. However, if my direct dependency on LibraryX is a different version than transitive dependency on LibraryX through LibraryY, then it may not have the same functionality. In trying to avoid a problem at compile-time, the package manager has introduced a huge potential problem at run-time.
With pip you have to resort to hacky solutions like like pip freeze. It also doesn't solve circular dependencies. Luckily these days the Python world has Poetry, which exactly solves this issue, and might be even better than npm. Unfortunately it's third party and adoption is a bit slow, but I use it for all my projects.
If package A depends on package B 1.0 and package C also depends on package B but 2.0, the order in which you run pip install for A or C will lead to a different version of B. And of course either A or V would break as soon as they hit an incompatibility. Obviously you would notice that only by running the application or tests.
So you have to use pip freeze to kind of generate a semi lock file,and every project uses it in a different way, because you also need different dependencies files for dev and production....and these are just plain TXT files which I don't think it is the best "format" for this.
Then you have these text files but also a "setup.py" which is for the package you produce, but hey you need to read the txt because otherwise you need to maintain them in two places. So you add a Makefile to tie all of this together, and that's another rabbit hole.
Add to this the mess of virtualenvs already explained in sibling comments and you have the perfect storm.
I know that nowadays are things such as Poetry, which work a lot better, but there are a good bunch of tools competing with each other.
To make an analogy, npm feels like using the latest, top of the line Macbook while pip feels like using a Casio calculator from 1985 with an external keyboard. That's the gap I feel between these two tools.
So if you ever use python, try first poetry or any of the other tools, pip is a terrible mess.
What's so "mismanaged" about pip? Honest question, I work with NPM every day but I've never really touched pip so all.
Maybe it didn’t have package signing, lock files, or deduping, but clearly it was popular in spite of those faults.
I hate all of them, use only when it’s almost inevitable, so I can’t really have an objective opinion.
Though it clearly worked well enough to be fantastically successful despite valid complaints about it.
At the time, there were JS/CSS/image minifiers in just about every language IIRC. Doing it with Node was a stronger argument to at least save the frontend side of the house from having to find a way to do them with Java or ASP.
During that time period, Java compile times were so slow that using PHP as a frontend that spoke to Java backends with SOAP services was really, really common just to avoid slowing everything on the frontend down with Java.
There was SSJS on NES/iPlanet/whatever before that. I mean, it existed. It was not really useful and few people even noticed it existed at all, but it did exist.
https://en.wikipedia.org/wiki/Oddpost
MS themselves had fairly functional Outlook web interface in 1995 (and was the reason XMLHTTPRequest was introduced
That said, I think it's an important landmark and I may end up revising this post to add a bit more discussion about it. Thanks for pointing it out!
Silverlight had the best performance/fit for my purposes and sadly was the first of many to go away, largely due to the popularity of iPhone and these platform/tools being excluded. Too bad Apple only promotes Apple's innovations and actively suppresses others.
I manage a web UI programming language in my free time, and the juxtaposition of folks claiming FP ergonomics benefits, then upon my request, showing a static, interaction-less end result whose improved version would obviate their pristine architecture, is pretty staggering. The typical defense is "hey we're not designers" but if you zoom out a bit you realize the whole environment doesn't foster engineers to care about design concerns anymore (barring a niche but valuable vertical of optimizing for payload size). This in turn puts pressure back onto designers who come to expect less and less of what they care about on the web.
Just the other day a newcomer shipped an animated row transition after fighting her framework for 3 weeks. The designer was delighted, but the manager didn't even get the point because he matured in whichever era of JS framework that de-emphasized acquiring taste in interactions.
I myself come from a Flash background, so rather than seeing an upward trend, I see a decline in UX concerns, followed by an incline of devops-related concerns in UI frameworks (accompanied by HN comments saying that in both cases the web should have stayed as a document format, only to end up with an awkward mix of document + app architecture their desktop apps through Electron anyway).
If I were to categorize these "eras", I'd rather take the perspective of wondering at which point, and why, framework process ended up more important than the product. Heck, a similar thing is happening on native too, unfortunately. Where did all the interaction designers go?
Maybe AR would nudge more folks to learn and focus on rendering, gestures, transitions, framerate, intent and the rest.
Furthermore, there really wasn't very widespread "community" use of GWT (mainly Google, and outside of that, mainly oldcorps working at similar scale to JS-ify old corp codebases), and even Closure was mainly leveraged by the community as glorified early babel / webpack type tooling, rather than a full range of things, e.g. Clojure.
All that said, calling React a "framework" is a big stretch, which makes the title questionable while one is reading through the components section, so I guess one could get away with including a few not-framework-ey things.
But... overall I don't think the author's age hampers them as much as you make out: when I started programming in JS circa 2002, nothing existing in that ecosystem was really comparable to today's frameworks, so comparing them here would add little.
Folks are building with a 20+ year old idea that has continued to evolve, in part because JavaScript is ancient in internet terms but uniquely positioned as one of the only languages (if you could call it that at the time) that was web first, instead of a traditional programming language having to connect to the web via a framework.
Ironically, the core feature for web apps in the browser to enable this existed thanks to Microsoft.
Brutally simple, efficient and likely part of what gave rise to so many JavaScript frameworks since people generally had to roll their own.
I’m sure there might be some here who reverse engineered what Outlook Web Access was doing.
“ The concept behind the XMLHttpRequest object was originally created by the developers of Outlook Web Access (by Microsoft) for Microsoft Exchange Server 2000.[4] An interface called IXMLHTTPRequest was developed and implemented into the second version of the MSXML library using this concept.[4][5] The second version of the MSXML library was shipped with Internet Explorer 5.0 in March 1999, allowing access, via ActiveX, to the IXMLHTTPRequest interface using the XMLHTTP wrapper of the MSXML library.[6]”
Building an app in the browser was not a popular idea partially because of the instability of high speed internet and the lack of performant mobile internet, and if imaginable, the lack of users on the web at that time. The first major rush of users online was likely Facebook.
Still it was possible to build a full ms office UI clone working in the browser, except it was powering your custom app.
Sometimes things are gaining popularity for a long time before they suddenly get discovered. This single call was a reason why jquery became so popular.
What I enjoyed about this article was how it speaks to an internet generation of tech or users emerging every 2-3 years, something I have long felt. Everyone starts somewhere, everyone is new to learning something and those experiences are worth sharing for new developers who do not quite have their compass in place yet.
https://en.m.wikipedia.org/wiki/XMLHttpRequest
https://en.m.wikipedia.org/wiki/Ajax_(programming)
I worked at a company around 2001 that was doing a full "Ajax" style frontend for a dashboard product for some industrial control systems. But it worked in IE only, as the Ajax pieces were not available on the other browsers yet.
Memories. I remember discovering any of these existed after doing an entire AJAX frontend site with raw JS that continued to work cross browser for the next 10 years. Made me full appreciate the value of those frameworks. IIRC JSON wasn't even really a thing yet.
I guess the difference is these new frameworks are all about letting javascript generate virtually the entire page. MooTools and friends were designed where the majority of the page was old-fashioned HTML being spat out by the backend.
1) Libraries (jQuery/Prototype/MooTools/etc) (Beginning - ~2010ish)
2) Widget-frameworks (YUI, Dojo, jQueryUI, etc) (mid-2000s - ~2013ish)
3) Data-orientied Frameworks (Backbone-onwards) (~early 2010s - current)
Edit: (Four, maybe, if you divide 1 into a 1/0 era, with 0 being the "rando DHTML scripts that many didn't really understand" era)
I do hope that we can get back to that "JS as compilation target" model eventually with WebAssembly. Even with improvements like TypeScript slathered on top, it's not fun writing Javascript, the tooling sucks, and it's vastly less productive than better developer ecosystems.
Not really true[0]. You could run server side JavaScript with JScript[1] on IIS as far back as the days of IIS 3.0, circa 1997. JScript is ostensibly JavaScript and tracked the original Netscape releases and then the ECMA standards.
[0]: depending on your love/hate with Microsoft at that time :)
[1]: https://en.wikipedia.org/wiki/JScript
Lots of dynamic (and complex) web-based CRMs were competing with each other in 2000. At my job, we were doing what is called "HTML over the wire" today by posting forms and using a frame as the target.
LiveWire's unpopularity and subsequent death was often attributed to its need for compiling and bundling steps, which seemed cumbersome to the JS devs at the time.
In fact when I got to Google in late 2011, I believe the only thing I could confirm using GWT seriously was some display ads admin tools.
GWT was awful. And not really used inside Google much.
GMail, AFAIK, never used GWT for its UI
A bunch of people messed with Rhino (IIRC Jaxer was one of the bigger ones), but Rhino had a bunch of quirks. For example, strings were Java strings, meaning that length is obtained via `"foo".length()` instead of `"foo".length`. Perhaps the biggest showstopper was the JVM variable limit per class file. Compiling large enough Rhino JS code would yield class files that crashed due to that limitation. And since JS didn't have modules back then, big balls of code were the norm.
Back then, the divide between frontend and backend was also wider. "Full stack" and the uplevelling of frontend folks towards backend skillsets wasn't really as popular as it is today. Node was also seen as revolutionary due to its async I/O first philosophy, whereas Rhino was more or less just a worse Java.
[0]: https://vaadin.com/docs/latest/ds/overview
It worked. It let me use my existing desktop app experience (Java, C#, C++) to write code that had a familiar style ( `myButton.setText("Click Me")` ), and build very desktop-style apps that ran in a browser.
But after having learned JS and Backbone, and then React + Redux, it was clear this was a much better way to build apps in general. (Obviously I became biased towards React and Redux personally as shown by my involvement with those tools, but it truly was a big mental shift in how I approached writing code in the first place.)
Though, I’ll note that I do really miss VB6 and C# Winforms for RAD.
It took MONTHS to become proficient at early-ish frameworks like GWT, Dojo, Marionette, Angular, Knockout, Ember, Enyo, etc.
Getting up and running on React in a couple hours and almost completely understanding the entire API inside a couple days was incredible. The fact that the code was faster and had fewer bugs too was almost too much to believe.
Nah.. I don't know about the others but Knockout was super simple to learn and get going with. React was way harder IMHO.
ReactJS of the time was pretty simple.
https://web.archive.org/web/20131105184444/http://facebook.g...
You could read every scrap of documentation in around an hour or so. There were only around a dozen-ish APIs to learn along with only a couple "unique" concepts like controlled inputs, refs, and JSX.
Meanwhile, there was never a need to step into React code unless you believed React itself was buggy (I only came across this one time and the bug had already been reported and was being worked on). Even better, React code was usually faster than Knockout before optimizing stuff and the ways to improve performance were generally pretty obvious.
You forgot Dojo, which was the first big javascript framework.
We have a different recollection of the order of events. I was doing web dev professionally as of 2004, and how I recall it is this:
Originally people had utilities files with a bunch of javascript convenience functions copied from random blogs that they would use to enrich server-side generated pages. This is how I wrote web apps in 2004-2006: php-generated html with hand-rolled js to enrich it.
Out of those grew the first generation of libraries (not frameworks) like prototype, mootools and finally jquery (which was so good at being a web swiss army knife that it replaced every other library).
The libraries were ok to add a bit of interaction but not at building entire UI. The “write your whole UI in JS” approach I remember being popularized by dojo and yui / yui-ext / extjs. GWT was a big hype but indeed not used by many. Lots of people used dojo and extjs though. I switched to ExtJS as soon as it arrived on the scene in 2007.
Those early frameworks only solved the UI problem, they were not great at page lifecycle and backend interaction, so they relatively quickly got replaced by application frameworks that did, like backbone and angularjs. Their mistakes became the inspiration for the second generation of SPA frameworks that we are still using today.
My impression of the era was that visual pizzazz was all the rage, and Scriptaculous really delivered on that front (Flash was also huge back then). Whereas full blown web apps were relatively rare and a lot of library consumers just didn't see the point of things like modularization (despite the interest in "proper" engineering from library authors like Dean Edwards et al)
And even then, once interest in thick clients grew, Ext.js had a lot more fanfare among the heavier frameworks than the Dojos and MooTools, due to its focus on enterprise.
I'll add that looking back, EXT seemed to be a bit ahead of its time. Its data/table view rivals AG Grid [0] of today. If we could've just standardized on a table view by now, but alas.
AG Grid - [Ag Grid, agnostic JS table framework](https://www.ag-grid.com/)
SproutCore for instance was around in 2006 and Apple built it's first version of MobileMe on it[1]. Prototype.js[2] first came out in 2005. I believe it was Prototype.js that first popularised the dollar sign $() for CSS selectors, or was it cssQuery[3]? Prototype also had Dojo[4] as healthy competition right from the start.
I also remember YUI[5] and its offshot Ext.js[6].
Most will also remember YUI[4] and its offshoot Ext.js[5] 1. https://techcrunch.com/2008/06/09/want-to-try-out-mobileme-c... 2. https://en.wikipedia.org/wiki/Prototype_JavaScript_Framework 3. http://dean.edwards.name/my/cssQuery/ 4. https://en.wikipedia.org/wiki/Dojo_Toolkit 5. https://en.wikipedia.org/wiki/YUI_Library 6. https://en.wikipedia.org/wiki/Ext_JS
We chose it in my company in 2008 before the framework boom and it had served us well for a very long time. It's batteries included, has for example it has a very comprehensive i10n module, which was not usual at the time.
Also worth mentioning it was started among others by Alex Russell [2], a famous developer advocate at Google.
[1] https://en.wikipedia.org/wiki/Dojo_Toolkit
[2] https://infrequently.org/
Now that we've realized SSRs cannot be an optional afterthought, we'll soon realize SSRs with running JS on the server is a nightmare to scale - https://engineeringblog.yelp.com/2022/02/server-side-renderi...
Just search HN for "scaling server side rendering" and you'll land on a bunch of practical complications.
That doesn't mean SSR is bad. It just means we know the solution but stuck with the wrong tools.
My hypothesis is that we'll capitalize WebAssembly to run our UI rendering logic and a tiny platform-specific rendering layer to translate rendering commands from WASM to platform. Interesting side-benefit: Language choices other than Javascript.
I've already started working on a proof-of-concept React-ish library that runs on a WASM VM. IT lets you specify your UI component declaration and behaviour in Kotlin - https://github.com/joelewis/kwasm
Another comment talks about revisionism and, while I think it is a valid critique, I think it goes beyond that. The author's career starts in 2012 and that's all the reference they seem to use.
Sure, they admit they will "probably going to gloss over a lot" and that they "can’t write about what [they] didn’t experience". But then... is this fair? Or, a better question -since anyone can write whatever they want, of course-, will this be, then, just some person's story or will it actually be representative or a larger reality?
Sadly, it feels like lately a lot of people seem intent in blurring that distinction. They seem to say "I may only have a limited view, but I'm going to present this as if this was the complete reality". And this is what this article does, I'm afraid.
The fact that there's is absolutely no mention at all of Dojo is telling. It's also quite telling that dismissing claim of "throw together some scripts for a few UI widgets, and call it a day", the quite absurd "everything was global", and the error of suggesting XHR came later -"As time went on and XHR was introduced and popularized"-.
And I think that's the core of the issue, even people who were around at that time do not remember all of these things. Ultimately, even those of us who are trying our best are going to miss details, and this is only going to get worse as we get further and further away from the beginning. Honestly it seems like this is a job for historians, and unfortunately I am not one, just a dev trying to share my thoughts and experience
> and the error of suggesting XHR came later
According to Wikipedia, XHR was introduced in 1999, 4 years after JS was introduced: https://en.wikipedia.org/wiki/XMLHttpRequest
Your way of commenting on XHR in this paragraph...
...where you are talking about jQuery already being a common thing, which implies at the very least 2006 but more likely 2008-9, and then writing "As time went on and XHR was introduced and popularized", suggests the idea that XHR somehow was introduced much later, when jQuery was already common.This is what I was referring to. It may have not been intentional, but the way you comment and present it suggests a mistaken timeline.
Nowadays, every time I look at a react codebase I feel certain emotions I can only describe as disgust. Maybe I have only seen bad codebases.
For any site of inherently simple interactivity, it's always been as easy if not easier than it ever has, but now it's also more manageable if you know you're going to need to scale a certain way.
It doesn't necessarily take all that much before you can start to see the reasoning. For example, take a humble grid of products, each with their own add to wishlist button, and a profile preview button in the corner of the page that indicates how many things are on your wishlist. Pretty simple to handle, render the thumbnails with unique ids and make an XHR request that stores the data with your account. Update the wishlist total count however you would.
Now suppose though that each thumbnail in the grid can open a bigger preview dialog that has more images, a bigger description, and it's own add to wishlist button. You can click that button, and it does the same thing. You close the dialog, but now your grid item needs to reflect that it's already been added to the wishlist. These things get really tiresome to keep building, something that I'm sure isn't new to you if as you say, you've been in software a while.
Sorry for the book, I mostly wrote that to challenge myself to think it through, not to imply you couldn't think of how it would be necessary to componentize things.
I'm not particularly fond of React more than Vue or anything, except for the fact that they both allow you to define UI as collections of functional state machines when it's necessary to do so.
I do totally get the point of using a framework like React or Vue to manage state on a complex app. I do purposefully call them apps, because websites are a more general term. Hand woven javascript UI, even if it was using an utility framework like mootools could get out of hand pretty easily. I recall things like extjs that were also popular.
Following my own example, managing push state by hand was tricky. So I did buy in on the premise that an opinionated way of structuring help and more importantly state was necessary. But I have been consistently failing to learn any new frontend tool ever since. This was not terrible professionally, since I mostly do what most refer to backend or systems. But still it is a bit frustrating not being able to follow along. Maybe it would be easier if this was 'it' when I started learning as sometimes it's difficult to forget and relearn.
Speaking of React / Vue codebases, I have thrice tried to contribute some changes or fix a bug on different projects and the amount of boilerplate I had to go through felt completely unnecessary and overkill. Maybe the pattern on these never 'clicked' or I was very unlucky to stumble unto bad examples. It's very easy to dismiss something one does not understand as unnecessary complex so I am still open minded about it. The feeling of disgust when I see the many levels of inference, types and juggling state around for UX that I see as pretty basic persists, though. I like the result, I abhor the execution.
I've done this many times, using plain-old jQuery and server-side rendering, and it really isn't that hard. The "conventional" way is to (of course), render the preview(s) with classes or data attributes on the updatable elements s.t. you can quickly identify the elements that need to change (say $('.wishlist-count').text(updatedCount) for the sake of argument).
For more complex things (let's say you need to be able to insert a complicated, but slightly different, object in the wishlist, for example), you can render a template into the page, dup it on wishlist addition, and populate the variable data in any number of different ways. You can even create JS objects that encapsulate this kind of logic (e.g. Wishlist.add(itemNumber)) without much additional effort. No framework required.
Now, I grant you that when you need to do this for many different kinds dynamic elements that all interact in different ways, or when you need to absolutely guarantee minimal re-rendering, you might want to jump to a framework. But I still feel that most front-end people these days instinctively rule out simpler approaches that would work just fine, because they're prematurely optimizing. Or worse...because they simply don't know anything other than React.
If I need to do WebUI stuff on my own, it is classical vanilajs with SSR in Java/.NET frameworks.
Being able to define your view as a pure function based on your state is a very powerful.l abstraction, but it took me about 2 years to learn to wield it well.
Maybe there are no good react codebases because it encourages bad code.
The whole concept of having both code and structure definitions in the same file is just flawed at its core. Like deliberately writing all your js in html script tags for some reason, except with functional-style syntax that just makes it look more cryptic to newcomers for no reason at all.
Granted there is a level of interactivity that is different for the complexity, mostly I look forward to the grand complexities of todays frameworks to continue to simplicity and be approachable.
Still things get more complex before they get streamlined.
Frameworks like svelte, vue, and even flutter to a degree feel different than react when putting together similar experiences in some cases.
The problem with the OP feeling (and mine) is that there are shoulders of giants. You either stand on them or not. If you are not, you start on much lower level of features ;)
I started building websites amaterishly from about 1995, and professionally from about 2001, and always hated how complicated and messy my code became any time I wanted to build rich functionality (i.e., a web-app rather than a website).
That first changed for me when I discovered ExtJS (now Sencha) in 2007, then later Angular and finally React in 2017.
These days I work almost daily on a React web-app I've built for displaying realtime weather/climate data for farmers, and it continues to be a very pleasing codebase to work with, more so than any I've worked on before.
It's also proof that you can make a simple and pleasant experience with a JS framework, if you focus on the essentials, there's no need to boycott JS entirely in favour of the old web, these frameworks get rid of a lot of the boilerplate when starting from scratch.
I'm an avid supporter of SvelteKit (the framework used on that website) and how they want to make the web less SPA/JS again. In this example, navigation is fast and client side, but can fall back to SSR if JavaScript is disabled, fails to load or hasn't loaded yet. There is no heavy runtime with virtual DOM diffing. Resources are cached and a page reload only sends ~17 kB over the wire on a large blog post, showing an excellent use of Tailwind CSS. It renders on Cloudflare Workers close to the user wherever you are in the world, with zero vendor lock-in if you want to stick it on a VPS.
At this point if you have JavaScript disabled is your problem.
It's like having a car and not wanting to put gas on it and pushing it around and complaining why you have to push your car.
Not saying we don't abuse its usage, but having it disables is just extremist
If the document is able to carry out navigation, without having to rely on downloading a non-negligeable amount of JS to hydrate the page, it improves the experience for that 90th percentile enourmously. Us web developers are often privileged with a very good internet connections. It's not necessarily anti-JS thinking, and SSR for crawlers generally as no longer been relevant for a number of years, it improves UX.
Edit: this also reminds me of [1], a 8.5 MB HTML file with 27.5k tweets was faster to paint than a single tweet in a React application. It depends on whether the UX can be improved by using more JS, for most websites I think less is more.
[1]: https://twitter.com/zachleat/status/1169998370041208832?s=20...
It feels like (to me at least) that at this stage it is quite clear that using NPM is an anti-pattern that is best avoided if possible (security, requiring a "dev machine" with the right version of NPM installed etc, general bloat)
I know that there is nanojsx (https://deno.land/x/nano_jsx) but would be keen to know of any other examples that anyone knows of?
For all it's problems, it's still is the killer feature that makes it easy to develop JS apps. The things you mentioned can be mitigated with proper practices.
1. Security: Supply chain attacks can be mitigated through being deliberate about versions and making sure your CI systems always install a "frozen lockfile"
2. Requiring the "right" version of NPM: Can be easily solved through "engines" in package.json. You can basically tell your project to not run unless the dev has the right version of NPM. This is not that big of a deal since a dev can just install the correct version with npm. You can take this a step further with yarn and pin a specific binary in your project so it doesn't matter what version your devs are running, they will automatically use the binary you specified inside the project.
3. Performance and Bloat: Besides NPM, there's also Yarn and PNPM (Performance NPM) that both work much faster than NPM and are fully interoperable with existing package.json's.
The ecosystem is still not perfect and security is still the biggest issue. The other issues you mentioned though can be easily mitigated through good practices.
The issue is the community is batshit and it's almost impossible to find or build a team that's going to democratically decide to use a sensible approach. If you want to keep a simple codebase on a React project your three options are build the entire thing yourself, be the best interviewer of all time and find a one in a million team, or be willing to be an absolute nazi and piss off a bunch of confident amateurs that want to overengineer everything.
If you can somehow avoid ending up with 20 other shit dependencies then React is a big upgrade over the frameworks that came before.
Also, I like to think of Svelte as the successor to jQuery, as it's the closest to "just vanilla JavaScript" I've seen (yes, I know there's some non-standard JS syntax in there).
1. DHTML scripts: individual scripts that provided functionality e.g. a date picker. You grabbed the scripts, and wired them together on your pages to enhance your page. Includes the first generation of Ajax scripts (in page communication with the server, often using raw HTML, text, or XML). Hidden iframes and other techniques also used for server communications.
2. jQuery: the popular library that everyone used because it provided a fabulous API to access and modify the DOM, plus helper methods to abstract out browser differences and bug workarounds. Bringing Ajax to all web developers, allowing them to enhance the pages delivered by their backend web server of choice (PHP, RoR, etcetera).
3. component framework (Cambrian explosion): mostly enhance pages delivered by the server, each framework with a unique approach to its API. Pages use components designed for each framework. YUI, Dojo, jQuery UI, Mootools, ExtJS. Starting to see more Single Page Apps, but no widespread usage of any framework on large numbers of sites.
4. React (and other 2nd gen frameworks, mostly virtual DOM): fully component based, can easily deliver an SPA (Single Page Application) and often the server only really delivers JSON (no HTML pages except a blank container). Widespread usage of React in industry.
There were plenty of early adopters for each technology, but as far as I recall, widespread usage follows the progression above. And the above ignores plenty of important first innovators and minor steps (for example, I used script.aculo.us).
The first stunning example was back in 2000 which was Outlook Web Access on Internet Explorer 5: the first usage of XMLHttp and it was many years before anything else approached its sophistication as a (mostly?) single page app with complex updates. I presume it had a proprietary component system, and IE5 was enhanced to make it work smoothly.
edit: ok looks like they were contemporaries
The amazing thing is that everything was there back in 2000, and OWA showed the way. AFAIK IE5 had all the features needed to deliver an SPA, albeit the techniques to reliably and performantly take advantage of IE took a long time to either discover or to percolate through the industry. I remember people discovering almost hidden IE features all through the 00’s, and then taking advantage of those features. I personally recall IE5.5 definitely had all the DOM features I needed for a component framework, since I remember angrily writing minor workarounds specifically for that version.
The vast majority of web developers were glued to their particular choice of HTML backend, so industry adoption of front-end frameworks was hideously slow.
React was when frontend JavaScript frameworks appeared to me to become really mainstream, rather than just early adopters (era #3 of my list). My own progression was script.aculo.us -> dojo -> personal custom framework. My custom framework had major advantages for me over dojo (better: performance, reliability, flexibility, improved UI, development speed).
Each individual developer will have their own view of how the industry progressed, but this is how I perceived it as a generalisation.
I wouldn't dare comment on how far we've come since the early days of web scripting, or frameworks for that matter, but for all the talk of added complexity I'd sure say it feels a lot easier (and infinitely less hacky) these days.
I would have liked to see some discussion of what is next. For example, where does WebAssembly fit in?
Lastly, a minor critique re.:
> That said, I can’t write about what I didn’t experience
Yes you can, it’s called historiography using primary and secondary sources. It’s a lot of work, but certainly doable, especially when so many of the participants of the history in question are still alive; you could interview them if need be.
Thanks again for a nice high-level write-up.
1. Form alerts and confirms 2. Ajax, jQuery, and plugins 3. Frameworks, from Handlebars to JSX 4. Revolution: TypeScript
I remember a time when JavaScript simply wasn't used. Everything was server-side rendered (classic ASP using VB6.0, ancient PHP, Perl, etc.) Eventually it gradually became bigger but its development was stifled by Adobe Flash taking charge of highly interactive UIs.
Then, slowly, JavaScript started to do things. Some companies started working with Ajax and suddenly you could talk to the server while you were on the client. But, for the longest of times, JavaScript was not used like it is today; we did not use it for templating or making components, because we had client-side XML and XSLT doing that with `<xsl:template>` and other such nifty tricks.
XML + XSLT + Ajax + jQuery was the status-quo for many years before we started getting UI libraries. Backbone, Ember, MooTools, and many others started to make life as a front-end developer far more interesting. We went from HTML (and later also CSS) drones to actually needing to embrace programming concepts, architecture, design, and design principles.
We had one big advantage over classically schooled university software engineering graduates: We knew JavaScript, it wasn't type-safe, it was full of little quirks, but it was ours and we had worked with it for many years. We knew it. They didn't.
And then TypeScript was born. At first, it was a monstrosity full of bugs, oversights, missing features, lack of intuitive design, and largely undocumented and confusing. Front-end engineers like myself didn't like it, because WE did not need it. We just saw that those classically schooled professionals suddenly thought they could do front-end, too, except they didn't know about HTML semantics, HTML accessibility, CSS (from floats to flexbox to grid to paint/composite/layout), browser APIs, browser differences, and so much more.
So these... people... came into our domain because TypeScript made them feel safe. They were far slower than us, they made more bugs, the code was unreadable (TypeScript generics are a hell, or in generally accepted TS-syntax: `T<G><A, H>(X<G>)<P><A><<A, B>, C>`) and worst of all, they made everything a `<div>`, including buttons and links and tables and lists and inputs and images.
Then, as the years flew by, TypeScript became more mature (except for their error messages) and it actually became somewhat intuitive to use. The back-end developers who were confronted with the fact that they knew nothing about the front-end have now either adapted and learned, or left, and the world is nice again.
The next big thing for web development and JavaScript is probably going to be the next big framework or library that we don't see coming yet. I love React, I enjoy Vue, I admire Svelte, but I don't think that React will stay around forever (libraries die because developers get bored of them, and new developers think these are getting too old), and Vue & Svelte simply haven't taken off the way I had hoped.
We'll see where it takes us.
In any case, I'll keep learning, I'll keep adapting, and I'm trying to be ahead of the hype train just so that I can keep increasing my $500,000 annual salary (excluding stock options).
https://extensiblewebmanifesto.org/
Very good ideas. If it was executed that way we would be in a different position. Some of the standards and browser implementations improved, many have been half baked or clunky, the JS ecosystem (which is the means to explore and extend) is chaotic and still moving incredibly fast without fundamental progress. I think two things happened since: We still don't agree on how to do interactive UI on the web and we've lost focus of this being a explorative journey that ultimately should result in agreed upon standards that everyone can build and rely on in the long term.