The Third Age of JavaScript
swyx.io
swyx.io
I've become comfortable with the fact that JS never stops changing (note the use of the word changing, not improving). I concern myself with fundamentals, not framework-flavor-of-the-month. I encourage others to focus on the same.
What I am not comfortable with is the stubbornly-held strong opinions many JS devs have. Much of the time, a particular JS dev will believe their way is the one-true-way(tm) (which is a problem among a lot technologists in general).
JS devs are the JS fatigue...not JS itself. I get bent when JS devs judge me for not staying up to date - JS is my 9 to 5, not my life.
For all the JS devs out there who hate me right now - check out Elixir, its the new "new."
FWIW, my personal projects are Spring Boot and Kotlin.
Hmmmm... well, I might agree, but that would depend on the opinion. There was a time when all programming was done using GOTO as the sole flow-control mechanism until a guy with a stubbornly-held strong opinion named Djikstra taught us that GOTO was considered harmful. Yet it's also the most natural way to code: a lot of people argued with him (in fact, the reason beginners don't use GOTO any more is just because it's not there, not because they've gotten more sophisticated). It's also a stubbornly-held strong opinion among many, but too few, developers, that global variables are also harmful. Unfortunately they're also the simplest, most obvious way to code, so a lot of developers default to using them.
If a developer has a stubbornly-held strong opinion, I usually give them the benefit of the doubt to try to figure out why: often they have a good reason. (On the other hand, sometimes the reason is, "it's easiest", like using public static variables in Java).
This is a topic where both him and other prominent figures such as Donald Knuth have since its publication repeatedly argued for moderation in use of the GOTO statement and against the total avoidance of GOTOs.
My go to example for this is that in C and other languages that lack modern comforts such as exceptions(for better or worse) and destructors, GOTOs can largely simplify the handling of clean-up and error recovery code.
Another example is longjmp which is very useful in kernel-space or bare metal programming, and in implementation details for exception handling however outside of those niches, serves no purpose.
GOTO serves a very useful niche but can also make code nigh impossible to follow. Most other structured programming statements have the same threat but we have rules in place to avoid their abuse. The following cases can result in code that is just as problematic:
IF/ELSEIF/ELSE: overly large, overly nested, or mutating variables.
SWITCH/CASE: complicated fall-through.
FOR: mutating counter variables, mutating termination condition.
TRY/CATCH/FINALLY/THROW: exception hell/deep uncaught exceptions.
These control flow mechanisms should definitely be preferred to GOTO in most cases but they can be just as badly abused if you aren't careful. The big difference I find is that people are taught how not to abuse these mechanisms but most material about the proper uses of GOTO is almost taboo because of the cargo cult around avoiding its use.
Sorry if this doesn't really fit into the discussion but it's interesting to me how an initially very tame and rational counter-argument spawned a massive cargo cult.
No, they can't. Old-school goto can create entire new problems in a codebase, that aren't possible to replicate with the structured constructs. That's the entire point of structured programming.
Of course, it's possible to use goto well. But eliminating it eliminates the problem.
The stubborn opinions from fads, not so much. Those opinions try to signal - 'I am the smartest because I know the latest and greatest.'
Reading a treatise on globals if you don't already have the taste to suss out much of the cost/benefit of globals on your own is a recipe for taking the contents out of context and treating the recommendations too broadly/narrowly.
That's a good point - mis-applying best practices because you don't really understand them is almost as bad as just ignoring them to begin with.
The whole framework-of-the-month thing is a meme. The overwhelming majority of companies use Angular, React or (to a lesser extent, Vue). There hasn't been a serious new framework in years, except maybe Svelte, which hasn't really caught on.
> What I am not comfortable with is the stubbornly-held strong opinions many JS devs have. Much of the time, a particular JS dev will believe their way is the one-true-way(tm) (which is a problem among a lot technologists in general).
so...not actually a problem with JavaScript if it's a problem among "technologists in general"
> I get bent when JS devs judge me for not staying up to date - JS is my 9 to 5, not my life.
I'm a professional JS dev too. I don't study it on my own time, but reserve a portion of my work time for keeping up to date with language changes. Maybe nobody is paying you to do that explicitly, but having a modern JS vocabulary could mean the difference between getting the next job or not, or how much you get paid.
when I got hired at my current job it took me 2 days to start being productive because they were writing modern React and I was used to the current paradigms.
I'm so tired of devs online ranting about how the problem with JS is that everybody expects them to keep learning new things. Do what you want, but keep that "JS devs are the problem" stuff to yourself. Maybe you'd be happier writing BASIC with GOTOs
I find it interesting that you say that. Has JavaScript changed for the worse? That's not how I've seen it, since a lot of problems like the lack of real modules, no async/await, lack of syntactic sugar for "classes", no `for (const x of y)`, weird variable scoping, no constants, bound functions(i.e. fat arrow functions), have been solved. I can't see how JS has gotten worse.
Some parts of the community are worse, perhaps. It's been years since React has been released, and people still seem to believe that React should be used for anything and is the only tool for any "serious" web development.(I'm not ragging on React itself, but the people who treat it like the new jQuery) Overall, JS devs are still trying to out-innovate each other by monkey-branching paradigms, which I think is the real churn with JS.
I guess that's related to your final statement. The perceived churn of JS to me is self imposed to some extent. I've been doing Ember development exclusively for the last 4 years and haven't had a problem finding employment or contract work. If I can make a living working with what people consider a "dead" framework, then that's a sign that you don't need to chase the latest and greatest JS fad.
"Solved" is an overstatement. The javascript ecosystem is house of cards. Modularity is far from solved, for example support for the browser field in package.json is all over the place, hoisting leading to phantom dependency bugs is another clusterfuck. A large number of popular packages want to own module resolution or parsing or both (jest, typescript, CRA, storybook, yarn v2, to name just a few), leading to inconsistencies between tools. Not too long, create-react-app broke because of some oversight from some library author over some package.json field lead to a broken publish. Bizarre bugs from the tree-shaking vs side effects dichotomy. The existence of things like yarn resolutions and patch-package and proxyquire. Abysmal symlink support. The list just goes on and on.
You _can_ get little pockets of very tightly integrated experience w/ comprehensive toolsets like Angular, Ember or to some extent CRA, but if you need to venture outside in a non-trivial way, the pain of fragmentation is real.
"Solved" might be an overstatement, but there's still been a ton of improvement. ES5 is a madhouse compared to what we have now.
The other language improvements are definitely unanimous wins though.
Clarification - I don't think JS has changed for the worse, but I do not think it is clear that all the changes have been for the better, both for the language and the ecosystem.
I see it as a double edged sword.
Take the example of handling asynchronous operations - async/await is good solution for that. But now you will be working in code bases with callbacks, promises, async/await, and possibly even generators - with generators being an example of an area that was not a clear improvement in the right direction, but an experiment now obsolete because of async/await.
I'm a fan of improvement, but nowadays I try not to pick up the latest trend for concern that it might be obsolete in the near future. You demonstrate this - you picked something you like (ember) and just stuck with it. Ember solves problems, it works, no reason to refactor your ember projects to react.
* instantiating with React.createClass(), then es6 class components, with functional components and higher-order components, now react hooks
* state management, with flux, then redux and mobx, and now context API
* bundling with webpack or rollup
* types with flow and typescript
I could go on. I am sure there's more I am not even aware of.
In React land, I think the churn is mostly around what's considered idiomatic. At some point there were mixins, props-down-events-up, HOCs, old Context, new Context, render props, hooks... On the semantics side, first we started w/ "just recomputing the vdom is faster than poking the DOM a million times", then shouldComponentUpdate and object identity, React.memo, libraries automagically wiring stuff to work around the "just recompute the whole vdom" paradigm.
I wouldn't exactly say it's been a stable foundation.
Another example: React.memo does not replace shouldComponentUpdate, nor is it more idiomatic. React.memo is for /function components/, while shouldComponentUpdate is for class components [2].
Another example: the community wanted a more flexible way of using function components with state, and a way to decouple unrelated state: enter hooks. They're not necessarily more idiomatic, but instead provide an alternate way of structuring components and application logic that fits more use-cases.
New context is the same as old context. Hooks just enable another way of interacting with context.
[1] https://medium.com/@dan_abramov/mixins-are-dead-long-live-hi...
[2] https://reactjs.org/blog/2018/10/23/react-v-16-6.html#reactm...
Well, yeah, that's what churn means. Consider, for example, that Vue and Angular have more or less stayed the same in terms of how people are supposed to write idiomatic code. The vue equivalent of hooks is very much seen as yet another option on equal footing (if not slightly derided as bandwagoning) since the old ways are just as expressive. When I hear people talking about React hooks, it's certainly not framed in terms of "oh it's just a different way of writing the same thing", but rather "oh it's better because it solves a bunch of issues w/ older idioms".
Another example, Mithril.js adopted element-level lifecycle methods (similar to Inferno et al) and the community largely thinks hooks are unnecessary - the last major bump was only major due to obscure semantic technicalities rather than introducing major ways of writing code (Vue is another great example that similar in this regard as well)
No doubt the required tightening was a benefit, but the breakage was not at all visible. Luckily it was a cosmetic (non-critical) usage.
New language features are obvious improvements. The paradigm shift from imperative UI management like jQuery to declarative UI management like React has eliminated entire categories of concerns.
Almost everything you see mentioned in the "Second Age" might be easy to take for granted if you've recently arrived, but they have not always been there. While they are not perfect, to say things haven't improved is shortsighted. From the high-level view we are making major strides.
It's an iterative process, where some things win out, new ideas and "flavors of the month" gain footing or wither and die. jQuery for example had competition from mootools, prototype.js, and others, but jQuery established dominance for a variety of reasons. It won mind-share by being the best implementation to solve a class of problems the community was tackling at the time.
Meanwhile having your own stubbornly held strong opinions.
Example - at one point in my career, I wanted to Node all the backends and hated Java. Now I like Java. I am also starting to dig Elixir. I'm sure that will change again.
1) Windows 7 Support officially ended
2) Edge now switched over to Chromium
With the exception of highly niche applications and markets, sites meant to be consumed on computers can aim for Chromium support and developers can rest assured they are covering the overwhelming majority of the market. Many slower-moving enterprises are standardizing on Chromium-powered browsers. Even NetFront (browsers used by video game consoles) is switching over to Chromium
The "Third Age of JavaScript" isn't marked by tooling or frameworks or code structure, but rather by developers able to focus on one browser instead of multiple. This new age will be marked by innovative use of APIs that people disregarded in the past because they only worked in Chrome.
Ah, just like the good old days of `new ActiveXObject("Microsoft.XMLHTTP");` ;)
Sorry, I couldn't help but draw an Elder Scrolls comparison here:
"Behold, in darkness, a doom sweeps the land."
"I have seen the gates of Oblivion, beyond which no waking eye may see."
"These are the closing days of the Third Era, and the final hours of my life."
Each statement could just as well have been spoken by your typical late 30s web developer that's seen some shit. That's lived through innumerable instances of framework and toolchain hell. That's probably being pushed into management because they're almost 40.
Ironic that Gandalf was of course played by Ian McKellen in the films, and is good friends with Patrick Stewart.
One obvious shift I’ve seen is in the use of the WASM and Web GL compiled applications. The likes of Figma and Superhuman are making incredible leaps in user performance.
I suspect serious companies will make strides here.
It's done that way because documents can get really large and having more low-level memory management helps a lot there. On the other hand, writing UI in C++ is really tedious and React has served us great. For non-performance sensitive areas, I'd much rather use TypeScript + React, despite being comfortable writing C++.
So obviously we're big fans on WASM, but we don't expect nor want JS/HTML/CSS to go away anytime soon.
but all entitled to their opinions, js could die in 10 years for all we know
If you could determine which sites are built using jQuery as the primary "framework", that would be informative. But even then, jQuery is just a library of utility functions, comparing it to React/Angular/Vue is pointless.
Roast me
Sounds like he is right and you are too old and averse to change to admit it!
Yes! Component design and rendering state changes does not require Vue/React/Angular, wake up people!
Dark times are ahead. The future is chrome. https://www.youtube.com/watch?v=_SCfNhyIo_U
Nothing strikes fear into my heart like this does.
Still wondering, though, if there aren't a lot of cases where a document-oriented approach (moving markup rather than JSON, progressive enhancement, good old standards) wouldn't serve an application domain better...
Prettier is an optional part of developing in JS that is hard to live without once you're used to it. instead of worrying about perfectly formatting your code, just write it and let prettier fix the formatting.
I never used Rails, and it's true that Node.js doesn't have any single standard framework that everybody uses (maybe Express.js would be the closest?) But today there are definitely a hell of a lot more companies hiring for Node.js developers than Rails developers.
i feel like the bit about "clearing away legacy assumptions" wasn't substantiated very well – basically just "CommonJS isn't necessary anymore because ES Modules are a thing now". which is true, but i feel like a sweeping statement like that needs a bit more. and if that assumption is where other "legacy assumptions" stem from, it'd be nice to expand on it a bit
(that's a legit question – i've sifted through webpacked JS a few times, and it mostly just added a bunch of
(function(module, require, ...) {
<your module here>
})(...)
around the code. tedious to read, but not much in the way obfuscation)and i guess if ES Modules turned out to be more performant (bc the module stuff is handled by native browser code, or maybe some HTTP/2 magic with loading), that could be an incentive for adoption
We moved to Typescript two years ago, and now that I'm comfortable with that, and compiling to JS, I wouldn't be surprised to see good compilers for Rust or other languages become the standard in the future.
I hadn't worked with types before, and hated it when I first started, but once I got used to it, it's a nice experience.
but also, there’s a classic pattern of articles which look back and describe a timeline of “past, present, future” where future starts tomorrow due to this thing I’m excited about today.