Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
The JavaScript ecosystem is delightfully weird (fly.io)
173 points by todsacerdoti on May 11, 2023 | hide | past | favorite | 238 comments


Coffeescript was well before "tree shaking" (the JS ecosystem's way of spelling "dead code removal") and code splitting, both being relatively new things in the bundler world ("tree shaking" being introduced with rollup if memory serves). Then came Acorn, which gave way to a whole slew of JS transformation bits.

It also didn't help that Node was fixed at 0.12 for years and years, and we had the IO.js fork until Node was released by Joyent for OSS community members to take over. That caused more issues to boot.

Also the whole bundling fiasco started with Babel, which wasn't a bundler at all and instead started as a means to provide polyfills for supporting "old browsers" (really, IE). From that whole thing came the concept of "evergreen browsers" which is a term that has largely fallen out of the common vocabulary with the rise of Edge.

Now we have "anything is a valid feature request" TC-39, and "it's really just Google at this point" browsers dictating how the web works.

It's a nightmare. As a maintainer of several large JS packages, and being so dreadfully burnt out on JS, there are other words I'd use to describe the whole thing than "delightful".


> As a maintainer of several large JS packages, and being so dreadfully burnt out on JS, there are other words I'd use to describe the whole thing than "delightful".

My first project that used JS was in 1996, so I've been along the ride every step of the way. Up until today where I am working with all of this on an Angular 15 enterprise project.

I actually would describe it as delightful, compared to what it was like only a short 10 years ago. 1996-ES6 was painful.

I understand your pain as maintainer and am also burnt out on ... um ... 27 years of JavaScript. Yikes.

But now it can just be written in TypeScript and I'll let the transpilers and other tools handle the details.

It is so much better.


The thing about JS is that it was always terrible 5-10 years ago, and is always "actually good now".

[EDIT] Though I actually agree that it's nearly-tolerable now that we have TypeScript and async/await to force what always should have been the default behavior.


Not sure what language you were coding in but I remember actively hating it 5-10 years ago and definitely didn't think "it's actually good now". It was always getting better of course, but even these days there's lots of problems that would prevent me from saying "it's actually good now".

The Web APIs are pretty lacking:

* WebUSB has only been available for a couple of years

* WebGPU is only now becoming a thing despite the aborted attempt that was WebGL

* Raw TCP/UDP sockets are still experimental

* WASM is still struggling to solve the scaling challenges to make it possible to make available a large portion of existing software as libraries for JS to interop with without overhead.

* WebCrypto doesn't have streaming hash support & fails to standardize protocols that are relatively popular (e.g. ED25519)

From a language level, there's all sorts of footguns/edges that can't be fixed due to back compat and the language is both slow in adopting good features but also fast to adopt features that don't work too well or just plain annoyances when switching between langauges (e.g. did any/all really have to be unique and called some/every?).

The ecosystem also has large annoying challenges with TypeScript being super slow to type check even small projects, a mess of bundlers to pick from (most of which are ass slow except for ESBuild and maybe SWC), linters (only really ESLint in the game which is slow for TS), formatters (prettier which is slow but thankfully there's now dprint), ES/CJS bifurcation that's a nightmare to manage, tooling that only works with very specific combinations of things, etc etc etc.

You can usually build something passably if you know what you're doing but it's a mess for someone new entering the field and even after having spent some time in it I'm finding myself futzing with project settings quite a bit to accomplish some slightly off the beaten path combination of tools.


I mean that at any time it was extremely common to see something like "well yes it was bad [amount of time ago], but now it's actually good!"

Before long that "actually good" is lumped in with the time when it was bad... but now, of course, it's actually good!


If something continuously improves then you'll always have people saying that as it crosses their personal threshold of "good". That doesn't mean they're wrong or that there is any contradiction. If you ask the same person what year javascript became good, their answer is not likely to change much over time.


The thing about JavaScript is lots of people are touching it and are innovating both in how to use it, and for language features.

It's always getting better, and always has opportunities to get better


If other tools handling the details just works for you, thats pretty amazing (and kinda surprising). Last time I was working on JS tooling there was a smorgesboard of various choices and it looked like most are opinionated just enough to not work with each other.


I've been at it since DHTML as well. I miss ES5. It should have ended there.


I feel like this is a normal thing for any language that becomes this ubiquitous. Python, C++ , Haskell, Java don't run in the browser the way JavaScript does. They don't have the same requirements that the JavaScript ecosystem does.


> "tree shaking" (the JS ecosystem's way of spelling "dead code removal")

I’m not altogether against giving it a different name. It’s very limited compared to what proper ahead-of-time compilers manage. I’d really like to see some actual effort put into partial evaluation and symbolic-execution-guided code simplification and dead code removal. Google tried something a little like it in Closure Compiler’s advanced optimisations mode, many years ago, but hasn’t really kept it up; and Facebook tried some five years ago with Prepack, but quickly gave up on it for unclear reasons.


Qwik is interesting here, very just-in-time with running JS on the client side.

https://qwik.builder.io/docs/concepts/resumable/


Qwik is basically more granular code splitting combined with a smart loader. We were already doing this ten years ago, just manually without a compiler.


> Coffeescript was well before "tree shaking"

From my quick research, it looks like the initial release of google's closure compiler, which had some amount of tree shaking, predates Coffeescript by about a month.


Joyent. Loved their free cloud server plans before until it was accquired by Samsung. It was also at that time I started looking at NodeJS, which is one of the side project from their software engineer for their SmartOS based on Solaris amirite?

But anyhow, boy oh boy, look at what we have today.


So, what language/ecosystem do you prefer nowadays if you were free to choose?


For web apps is just Javascript. And since you are forced to use it, why not run it on the server too and use less programing languages? Not a fan, but it is what it is.


I firmly believe Rust is the future.


I wouldn't say bundling started with babel... but was predated by browserify and other bundlers... oh the days of gulp/grunt and browserify...


What do you think about Deno?


Not a fan, for one reason in particular: they allow URL imports[0]. It's a massive uptime and security flaw in my opinion that was added because someone asked for it. It's been asked for on the Node repository as well where it's received mixed feedback (namely, negative feedback from several core contributors) due to it being, well... a dumb idea.

I've never seen the need for Deno. Every library I've written that has more than a few hundred users has inevitably been spammed about "Deno support when?" which also turned me off from it.

[0] https://deno.com/manual@v1.0.0/linking_to_external_code


They have ways to lock, bundle & version those in the faq you linked, so it doesn't seem to be a problem. I wonder if people have the same complaints about golang


Locking, bundling and versioning do not solve availability.


I'm not sure what you mean the versioning & bundling both ensure you have the right version in your local repository if desired. Of course the upstream source can go down but that isn't really different from any other package manager.


I like javascript, but I always think about the time when I was working as a front end developer, and a guy across the room suddenly stood up, walked over to the white board, and wrote "F*CK JAVASCRIPT" in massive letters. I believe his concern was around the lack of type safety (this was before we used Typescript). And this was someone not prone to dramatic gestures.

At the time I laughed. Guy must be having a bad day. Javascript rules, look at this widget I made.

Cut to a few years later. I am fed up with React, and the entire javascript ecosystem in general. The trend-based, article-driven development, the new framework/pattern you have to learn/unlearn every six months, the SPAS that made a simple web app spool up the user's laptop fan with all the javascript it was processing just to do basic stuff we could do much more simply in the 90s.

I ultimately quit being a developer in 2019, switched to doing design full time. I still write javascript for personal projects, because it's the thing I'm most familiar with. But, only vanilla javascript.

Javascript rules, but also: f*ck javascript.


> I am fed up with React, and the entire javascript ecosystem in general. The trend-based, article-driven development, the new framework/pattern you have to learn/unlearn every six months, the SPAS that made a simple web app spool up the user's laptop fan with all the javascript it was processing just to do basic stuff we could do much more simply in the 90s.

I must be living in a parallel world cause I write React & TypeScript code on a daily basis (among many other things, including writing Python and SQL too), I've done it for a few years now and I quite enjoy it. Last time I had to learn a new "pattern" was Hooks I guess, and it was like 3 years ago? I was hesitant at first, I didn't have any issues with class components... but Hooks actually increased my productivity and simplified my code. Otherwise I feel like coding in React hasn't changed much over the years. I would definitely not want to go back to the technologies I was using in the 2010s.


Yeah that’s right. I think a lot of JS devs are jumping on fads but it’s absolutely not a requirement. Just pick a couple of well supported projects for the stuff you really need and stick with it.

I’d much rather have some dependency discipline and a vibrant fast-moving ecosystem than the opposite. Just pick the fruit of other people’s labor when it’s ready instead of dogfooding questionable and bloated deps.

Oh yeah and do not read medium articles about JS.


I’m the same here. React with TS just makes sense as it is. We have a mix of class and functional components which can easily be understood. State lives here, logic goes there, render, done! It does become tricky when you start adding things to its simplicity like Redux, useEffects, useContext, useReducer, locationState, params, props, classes, StorageProvider (and the list goes on) without a clear standardized code guide for each scenario/patterns.


I always find myself coming back to react.

Its so delightfully simple at its core. Typically super easy to debug. Extremely composable and reusable.


> the entire javascript ecosystem in general. The trend-based, article-driven development, the new framework/pattern you have to learn/unlearn every six months

Maybe it’s worth logging off Twitter for a while and understand that you can just not pay attention to these ‘trends’ and learn a new pattern every six months and you’ll be absolutely fine. Yes, ecosystems and communities can encourage this, but individuals also have got to take some responsibility for opting themselves out (or into) this hamster wheel.

I’ve seen this React Server Components stuff on the periphery for a while now, but I don’t really understand it and I don’t intend to for a while. I’ll let the twitter us hype beasts sort out what they want to do with it and I’ll circle back and check out what it’s like in a few years.


My experience with javascript as a non-software developer/non web person has often involved frustration.

A good example is an experience I had a few years ago (circa 2018)

My work acquired some new software which published some results using a REST endpoint. I wanted to pass some parameters to the endpoint get a response and display the response on a webpage.

I'm used to working with Python/R and SQL databases it is relatively easy to write code in these languages to execute a SQL query and publish the result.

To do the same thing with endpoint I had to learn about ajax, asynchronous code, callbacks and then later deferred promises. What I thought would be relatively simple ended up being horrendously complicated to code.

I think part of the problem is the javascript language changes and adds new features so rapidly it is very hard to search google for help in my case I found code examples using callbacks, I had massive issues trying to make it work only to later discover that was old way to do it and the new way was to use Promises instead. Most of google searches I made went to horrendously outdated stackoverflow posts and there was no obvious way to tell if answer was best practice or not.

Doing the same google search again today in 2023 it looks like they have reinvented how to do it with something called "Await" now.


You would find it even more difficult in almost every other language available.. What you're describing is simply the pain of learning a programming language with virtually no prior experience.

Maybe it's more simple in Python but this really isn't that complicated, it's certainly not a valid criticism of JS.


Sounds like a perfect use for jquery. You don't always need to use the newest framework.


Await is just syntactic sugar for promises.


> a guy across the room suddenly stood up, walked over to the white board, and wrote "F*CK JAVASCRIPT" in massive letters

>Guy must be having a bad day.

He was having a bad day because he was doing stupid things with the code he wrote that led to problems. I've never had a problem with Javascript's type system, or having the wrong type show up where it shouldn't. I accepted the dynamic nature of JS long ago when it first came out in Netscape, and I adjusted my coding style accordingly. And Javascript types are not a mystery, type coercion is fairly simple and doesn't produce unexpected results if you actually understand the language. If you don't understand the language (or any programming language), then writing things like "F*CK JAVASCRIPT" in massive letters on a whiteboard is something that might happen.


> I've never had a problem with Javascript's type system, or having the wrong type show up where it shouldn't. I accepted the dynamic nature of JS long ago when it first came out in Netscape, and I adjusted my coding style accordingly

Different languages have their own strengths and weaknesses as well as generally accepted coding practices and sometimes different paradigms. I find the folks who struggle the most are trying to write JS as if they are still a C# or Java developer so they constantly run into square peg round hole issues and blame it on the tool. I love JavaScript. I also love C#. But you've got to approach how you solve problems with them differently. How you write long term maintainable code in both is different.


> I find the folks who struggle the most are trying to write JS as if they are still a C# or Java developer so they constantly run into square peg round hole issues and blame it on the tool. I love JavaScript. I also love C#. But you've got to approach how you solve problems with them differently. How you write long term maintainable code in both is different.

Weird take. Because the best way to write maintainable JS by far, whether you're using TypeScript to enforce it or not, is to keep all the lessons that informed the design of Java in your heart. Go ahead and decompose your program into classes and interfaces, eschew with clever tricks and just focus on readable code instead, and make sure you or anyone else can without much difficulty work out at any given point what the "shape" (type) of a value is.


There are lots of well-liked dynamic languages. But JS deserves the bad rap, it has so many WTFs in it's dynamic behavior and as a rule doesn't raise errors when things go sideways. Just painting it as a dynamic vs static thing is misleading.


Yeah, Javascript isn't even the only dynamically typed language out there, but you don't see people compiling strictly typed supersets of Python or Lisp because they consider those languages unusable otherwise. With any other language people are willing to learn the idioms and accept and work with the quirks, but for some reason Javascript alone seems to be the exception.


Didn't python add static typing?


Only type hints. They help a linter/IDE bitch about types but they don't have any enforcement beyond that. They're great for self documenting methods but don't remove any dynamic typing from the language itself.


I'd argue that typescript is the same, just stricter by default if using TSC. Many people run type checking separately from building/running the code, just like in python.


Javascript is this generation's C++. It's a massive language and the only way to stay sane on a project is to agree to use a well demarcated subset of it.

Nothing wrong with being C++. The reason JS is so massive and weird is because it's the language that everybody uses, or has to use at some point. Upsides and downsides.


JS is far smaller language than C++. You don't need to agree on common part of language, it's the rest of the ecosystem around that's the problem as you "need" a lot just to fix JS deficiencies


Yes.


> Javascript is this generation's C++. It's a massive language and the only way to stay sane on a project is to agree to use a well demarcated subset of it.

No, it's not massive compared to C++, it's actually quite simple. No explicit pointer management, no memory management, no user defined operator overloading and so on and so forth. The only difference between classes and function prototypes AFAIK is "super" late binding, otherwise one can replace classes with functions everywhere they want.

The problem isn't javascript itself, it's the different runtimes that have different API. But the javascript spec is tiny compared to C++.

As for the ecosystem, it's mostly node's that is a mess, as the result of core Node API being barebone. Browser API are actually quite extensive and do a lot of stuff, from shaders to XML parsing to sound generation, but this isn't javascript it's the DOM/Browser API.


JavaScript, The Good Parts by Douglas Crockford symbolises this well today

https://www.reddit.com/r/ProgrammerHumor/comments/621qrt/jav...


"JavaScript, The Good Parts" is not really relevant to modern JS. But Crockford's new book "How JavaScript Works" is basically the updated version. As an amateur coder I found it very useful, definitely worth reading.


Javascript, The Good Parts, is not really relevant to today's Javascript, unless it's been refreshed. I remember working through it 10+ years ago:

* `var` is no longer a thing.

* Even `let` is less common now.

* Using closures and prototypes to enable functions to be used like classes and have private variables and static variables, have been replaced with proper classes

Nowadays if you want to use the good parts of Javascript, just install eslint with insane defaults and let it tell you if you're trying to use the non-good parts


Surprise surprise, class syntax is basically just syntactic sugar on top of prototypes, and they essentially work the same way, besides bring able to have private members (which seems like a anti-pattern anyways).

You'll able to accomplish exactly the same with both, so why create yet another way? Seems bit wasteful..


The syntax sugar paves a "garden path" for the common experience to be the best experience. It encodes "best practices" from previous prototype-based code, including private members. (They were always possible/always existed [as closures inside a constructor function, among even wilder solutions], but the patterns for building and using them was all over the map. It is nice to have standards now over a lot of ad hoc solutions.) I don't think it is wasteful, because it saves you from having to read books like "JS: The Good Parts" and hunt around for the right toolkit or design pattern to do the right things easily.


You could always create private members with closures.


>just install eslint with insane defaults

where do I find these insane defaults?


There used to be a lot of nice default packages, but I'm not aware of any actively maintained ones (other than "company X's config"). So instead...

First, find the docs for ESLint and each of the integration packages that you've installed for each major dependency. Then just set each rule to the strictest setting. Then as you're developing, you'll start running into overzealous rules, prompting you to either disable the rule or write some override/exception.

TSConfig, on the other hand, isn't extensible so you can just throw a couple configs from github.com/tsconfig/bases in your `"extends": [...]`. The base config `@tsconfig/strictest` might be of interest to you.


lol, that was a typo, should have said "the sane defaults"

On the other hand, it's a testament to the comment being written (or at least edited) by a human, and not an LLM right?


Sorry, but var is absolutely still a thing. It has plenty of valid use cases and sometimes using let just needlessly complicates the code.


I'm curious, what use case? I can honestly say I don't think I've used var once in the last 5 years but maybe my coding style is different. Where is var useful?


I imagine the person above deals with legacy codebases or vanilla JS (with no SPA framework) on the front-end, because I haven't seen "var" in over 5 years outside of those contexts.


It's mostly outdated now, thank goodness, but anyone born after 1990 should read it cover to cover to appreciate the current state of JS and why we got here. hasOwnProperty?? Lol

Looking at the book now, I still like some sections like "Curry" and "Memoization".


The joke is about the size of the books in the photo, not about JavaScript features.


Are you talking about JS the language, or the ecosystem?

JS as a language isn't nearly as big as C++ or, say, Swift... I'd say Python complexity is on par or even higher than JS, in terms of core language features.

There are some language features that are outdated but it's hardly like the C++ situation.


ECMAScript Language Specification 13th Edition / June 2022 (846 pages): https://www.ecma-international.org/wp-content/uploads/ECMA-2...

Working Draft, Standard for Programming Language C++ from 2020-01-14 (1815 pages): https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/n48...

I'm not sure what's the "correct" spec for the current C++ standard is. Still a big difference between these languages, but 846 pages isn't exactly small either.


To be fair, so much of the C++ standard is literally just being explicit about what the standard does not define and often who defines it instead. But to be fair, it would probably be entirely reasonable to categorize that as essential language knowledge and a "part of the language."

Meanwhile, the ECMAScript spec really does not leave very much wiggle room. It (like every other web standard) is almost just documentation or often even pseudocode-ification of an actual implementation... Certainly makes you think.


Random committee draft of the C spec from 2007 (552 pages): https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf

Intel 64 and IA-32 Architectures Software Developer’s Manual, Volume 2 Instruction Set Reference (2552 pages!!!): https://cdrdv2-public.intel.com/774492/325383-sdm-vol-2abcd....

The ECMAScript language spec is closer to the C spec than the C++ spec, by a large margin. I'm not sure how much you can deduce about relative complexity from these figures.


I agree JS spec is like C, whereas some JS frameworks like Typescript are more like C++ where it's 100% using JS but w/ brevity to the end user. Think:

Note: I'm a moderate JS dev so correct me if I'm wrong.


There are far more ways to write javascript than any of us want.

For objects with methods you can make literals, use a constructor with new and have prototype methods, use a class, or use Object.extend, or Object.create or probably other tricks.

For async code we have callbacks or promises. And promises can just use the Promise class and .then(), or you can use async / await. And the promise class also has polyfills in npm if you want that instead. Or there’s tricks with generators.

Functions can be written with function foo(), or const foo = function(), or const foo = () => {…}. Or const container = { foo() {} }. Or use class methods (which have different syntax again).

Importing external code can use commonjs (require()). Or import statements. Or dynamic import. In the browser you can use multiple script tags and have scripts assign their library to a global object. In nodejs code can also change what require does.

I can keep going - don’t even get me started on bundlers. You’re probably right - the language probably still isn’t as big as C++. But it’s big enough that almost nobody knows every javascript feature. I was around in the early days of nodejs (0.4 was my first version). At the time the design of the language, and of nodejs, seemed simple, clear and cohesive. Don’t get me wrong - I love a lot of the newer features. But javascript as a language feels like a bit of a bloated mess.


There’s a 300 page book out there on on just initializers in C++.

> There are far more ways to write javascript than any of us want.

Some of the examples you cite are due to JavaScript being minimalist though. For object creation there are a few different syntactic methods but it is straightforward how they compare semantically - they are basically equivalent. C++ has numerous methods to do similar things but they each have their own numerous rules and exceptions. Ironically in C++ there is often only one way to do something a certain way, as a similar syntax for initialization may (not will) do something completely different depending on external context - such as merely putting parens around a set of braces.

The diagnostic output of the compilers alone when you misplace a symbol is longer than many JavaScript libraries.

> But it’s big enough that almost nobody knows every javascript feature.

I don’t think this is true. It just isn’t that big of a language. The examples given certainly don’t paint a picture of immense complexity - a few things have accreted during the years, it’s not outside of simply just learning them in a few weeks.

It’s not just about the length of the spec (which is much shorter) but the complexity of those specified features within the system as a whole - JS as a system just isn’t relatively that complex.

> the language probably still isn’t as big as C++.

For anybody that does modern C++ and JavaScript professionally (as opposed to those that are content continuing to write C++ like it’s CFront) this is a coffee spitting understatement.


C++ is this generations C++, it hasn't gone anywhere (especially with WebAssembly). JS isn't even a tenth of the insane complexity of C++ (I say as a fan of C++ and JS)


For me:

JavaScript === C

TypeScrit === C++

You can shoot yourself in the foot writing vanilla JavaScript. There should be a book "TypeScript: The Good Parts" though: the language brings a lot of stuff that is better not to use.


> Less that 10 years ago, JavaScript sucked bad. It had no imports, no classes, no async, no arrow functions

No classes in JS was much better than with. As someone who used and contributed to CoffeeScript, I was initially excited by them but in retrospect, they've been a huge negative IMO.

Douglas Crockford saw it immediately: https://www.youtube.com/watch?v=PSGEjv3Tqo0&t=300s


> No classes in JS was much better than with.

I think you experienced a different JS than I did. JS has always had classes, they were just "harder" to build/use and every "Framework" had a different mixed bag of "utilities" and patterns to work with it and they weren't always compatible. (Mixing jQuery style classes and Dojo style classes was "fun", for two random examples. I could go on all day about the long tail from MOO Tools to YUI to Backbone to…) ES2015 class syntax just standardized already common patterns and increased interoperability and cleaned up a lot of footguns regarding Prototype-style inheritance along a "garden path".

The class syntax garden path is much nicer than the weed-filled hedge maze it mostly replaced.


I got quite used to the prototype inheritance style Javascript and really liked it. But I don't think it scales across teams as well as modern JS or Typescript. But for a small project with just myself or a few other skilled developers? I'd prefer old-school style JS semantics.


Yeah, I have some fondness for it myself, even despite listing some of the headaches I recall from past efforts. The fun/interesting/good news is that it is not technically an either/or in JS. Prototypes are still the underlying driver below the class syntax. There's absolutely still room for doing really interesting or cool things with prototypical inheritance, even doing things that aren't entirely possible with the class syntax, and then wrap them up in a cool library and make them interoperable with class syntax for all the downstream users. (Interop with the class syntax is still a useful design target.) The hardest parts of such "cool" library ideas is just likely getting the Typescript types correct with them. (Typescript doesn't quite model all the possible intricacies of prototypical inheritance, in my experience.)


Agreed, I still use it when I'm writing JS for personal projects. But at work, things have to pass code-review, be easy for someone else to modify in the future or write a bugfix for if I'm on vacation when the report comes in, etc... But I'll never fully give up that old-skool JS.


> The class syntax garden path is much nicer than the weed-filled hedge maze it mostly replaced.

I agree. Honestly I don't understand the obsession some people in the JS world have against classes.

React components with state made more sense with classes than hooks. And yeah some people argue hooks are composable yada yada but if you need a React expert to write a useInterval hook to use a fundamental language feature, then maybe the model is not a great idea to begin with.

https://overreacted.io/making-setinterval-declarative-with-r...

Of course I know I'm in the minority here.


It's because they have been bitten by inheritance issues. Classes are great as long as you limit or avoid inheritance altogether. They work so nice with typescript.


Relatedly, it's also because of multi-inheritance issues specifically. React built hooks in part to handle cross-cutting concerns that needed some form of multi-inheritance (mixins and "higher-order components" which themselves were often something of a hack around the existence of strong JS mixin libraries/standards/best practices/meta-programming). The best hooks are an improvement over their HOC counterparts (and many of their mixin counterparts): better Typescript types, fewer footguns, fewer composability limits (HOCs had stack problems where stack them in the wrong order and they broke or interfered with each other), easier to reason about (even given the weird learning curve of hooks in general, as black box "units" they have simpler mechanics and APIs than HOCs ever did).

To be fair, you can build a lot of React components without ever feeling a need for something like an HOC and never deal with some of the inheritance problems that Hooks were built to solve so some of that "classes are a better way to write components" feeling is that one has never quite before had the multi-inheritance itch to scratch that Hooks solves for. It's obviously hard to judge a tool when you don't know if you've had the problem it solves for or not.


I was talking about classes as a design pattern, not just react classes.

That said, I don't miss higher order components, but I do find myself reaching for renderprops sometimes. I think it's still a great pattern.


I'm so sick of these paradigm religious wars. There's nothing wrong with object oriented programming. There's nothing wrong with functional, either. You use them for different purposes. These people like Crockford who talk about "Java programmers are stuck in this inferior way" are the ones who are stuck and not all that educated on programming.


There's also a lot to be said for having fewer footguns. One reason I liked CoffeeScript is that it actually removed JS footguns such as "with", ==, etc.

I'd rather either Clojure or Java to using Scala and having all the possible complexity and interactions between paradigms it makes possible. Sometimes less is more.


Wait until you have to maintain someone else's overly crufty, inheritance-based JS framework.


There's nothing wrong with inheritance, even in JavaScript.


They weren’t criticizing OOP per se. Before the class keyword, JavaScript had much more powerful OOP semantics using metaobjects.


The class keyword is just syntactic sugar. JS still uses prototypal inheritance. Nothing has changed. Check out objectplayground.com for details.


Not ‘nothing’ has changed. Classes are supposed to be syntactic sugar over constructor functions, but the later could be invoked as well as instantiated with the ‘new’ keyword, whereas the interpreter will error out on you if you attempt to invoke a class. That is fine though, I don’t care for constructor functions. I was talking about using metaobjects, a different concept altogether.


Okay, I think I get your complaint. JavaScript doesn’t have a metaobject protocol, but there were a variety of user-land approaches to OOP that added one. Although they’re still technically possible, the class syntax formalized a non-MOP approach to OOP, and those third-party tools have all fallen by the wayside.

It’s not so much that you can’t use a MOP in JS, so much that people don’t, and will look at you funny if you do.

As a lover of simple and straightforward code, I never used the MOPs—I hand-coded “class.prototype.method = function()” like God intended*—and I’m happy the standard uses that more traditional approach. But I can see how someone who did use a MOP would feel that the class syntax is a step backwards.

*that’s a joke.


Yes, this is it. The MOP approach basically involves using ‘Object.assign’ to instantiate new objects from the metaobject. It is quite straightforward in my opinion, but that is relative I suppose. I don’t know if this is true but I’ve been told that Brendan Eich intended for this exact approach to be the one and true OOP in JS, but was persuaded by his boss to implement constructor functions to make it more like Java.


That'd be a little weird if that was Eich's "original vision" considering `Object.assign` didn't come out until ES6. Which was also when the `class` keyword was introduced.


Good catch. It’s been a while since I’ve been thought the ways of old JS so I’m misremembering. It’s all apocryphal anyhow.


It's not apocryphal if I'm the source. I wanted Self-ish prototypes and cloning but "Make It Look Like Java" orders trumped my wishes.


Yeah, I write all my new stuff in JS (React frontend, Node backend) and have never felt the need for defining my own classes. Wasn't actively avoiding them either. React was fully centered around classes and they ditched all that in the new hooks system.

I also don't understand the big deal with arrow functions. Yeah I use them, but they're basically regular functions except slightly shorter to write. `async` was a big improvement, though.


Arrow functions have less-incomprehensible semantics of what "this" means. Though that's less important if you're not using the classes.

Most users just use arrow functions as syntactic sugar. But it's really good syntactic sugar.


That just described how I feel about Typescript - created by Java programmers so that they can feel comfortable and not have to learn how to program in Javascript. I was a Java dev for a decade. It's so much more tedious and less fun than programming in Javascript. I get Java recruiting emails and I shudder.

I accept that in gigantic apps worked on by multiple teams, and libraries shared with 3rd parties, Typescript makes sense. But 90% of the time I see it used it's with a smallish node app or SPA worked on by a few people, and all Typescript does is slow things down.

I feel like I can count on one hand the number of times I've gotten burnt by a run-time JS bug that a compiler would have caught. I just don't see that as a strong use case for the overhead and development drag of TS. I only see sharing lib-ish code across teams as a net benefit of TS.

99% of the time when the TS IDE complains over something that a JS linter wouldn't have caught, it's just because something wasn't defined properly in TS, not because it's an actual error in the code.


Typescript's type system is vastly different from Javas, and if you're using it that way you're missing most of the good parts.

The great thing is it's powerful enough that you don't lose JS's dynamic features, but your code becomes much more self documenting and clearer, and your IDE has a much better idea how to support you. I would never go back to vanilla JS, typescript saves me way too much time and from too many headaches.


> That just described how I feel about Typescript - created by Java programmers

Close! C# programmers. :)


> created by Java programmers so that they can feel comfortable and not have to learn how to program in Javascript.

Well... C# .Net developers, as Microsoft found, correctly, that you can't build complex products easily with a lack of types.

I also don't think many program in vanilla Javascript; it seems everyone is using JSX.


> I also don't think many program in vanilla Javascript

I enjoy coding in vanilla JS - my canvas library is 100% vJS, with a hand-written .d.ts file in the root directory in case anyone wants to import it into their TS project.

That said, I also enjoy jogging along cliff edges and sheltering under trees during storms so I'm not the sort of person who should be offering programming advice...


Are you really trying to say people couldn't build complex apps before TypeScript? I know of hundreds of examples that were made before TS...

Complex apps still had lots of tests, which basically solve the same problem as TS is trying to address, without having to write a different language than what gets run by the browsers.


How would you compare the overhead of writing tests un JS to the overhead of doing proper TS?

Obviously tests are still useful in TS, but not as many I think. Also, the feedback loop of a static type system is, IME, much faster than with tests only.


Speaking as someone who’s done both, you write the same tests either way. The main benefit of the type system is for IDEs, which have better code completion and automated refactorings when they can statically analyze types. Types also make type-related errors easier to debug: your tests will probably trigger the bug, but you’ll have to do some digging to figure out why.

On the flip side, the TS type checker is painfully slow, the code is noisy, and you’ll waste a lot of time satisfying the type checker.

For me, the sweet spot has been dynamic (runtime) type assertions in JS. Fast feedback loop, no transpilation hassles, good error messages when type-related errors occur. Downside is that now the editor can’t statically analyze types.

Lately, I’ve been experimenting with using swc to transpile TypeScript without typechecking it. Now there’s a fast feedback loop and I use the IDE to discover type errors. (And the integration build checks types too.) I’ve just recently started this experiment, so jury’s out on whether it’s better than runtime type checking.


I end up having the same amount of tests in JS as in TS. I'm not really testing that the types are correct, but that functions work correct. So just because you're writing JS, doesn't mean that everything you would assigned types to in TS, you now write a unit test for itself.

And my editor does the autocomplete thing seemingly just as well as the autocomplete I get from TS, even when I just write JS code normally.


> Are you really trying to say people couldn't build complex apps before TypeScript?

I said easily. Types remove whole categories of errors.

I think the industry has generally found dynamic typing to be a mistake. Most dynamic languages are now trying to retrofit types.


Jsx is really a templating language, not a replacement for JS. React still involves writing a lot of JavaScript code, and typescript helps quite a bit both with the js and the jsx.


Many other comments have touched upon other unusual aspects of the Javascript ecosystem, but there's another major aspect in the ecosystem at quite a precarious position, yet of which, I see very little discussion on, namely, the debugger.

Chrome DevTools is the de facto debugger of Javascript, which becomes apparent once I have to take advantage of Javascript's capability of moving beyond the browser, on alternate runtimes. To debug node.js for the server and Hermes for my apps, in both cases I need to use the Chrome DevTools debugger which uses the Chrome Debugger Protocol. In the case of Hermes, the Chrome DevTools that comes with React Native doesn't even come from your local copy of Devtools, but is dynamically loaded from https://chrome-devtools-frontend.appspot.com/.

As far as being a protocol goes, I have yet to see another viable implementation of a Javascript debugger. To profile my performance or check my memory usage, I need to use Chrome. Even worse, both node.js and Hermes have strange issues pop up with the debugger connected. In the case of Hermes, it is acknowledged that the Javascript runtime is not fully compatible with Chrome DevTools Protocol, whereas node.js occasionally exhibits segmentation faults with the debugger connected, or falls into non-terminating computation when connected to certain complicated programs (such as npm...)

It worries me greatly that to debug my code, not only must I have Chrome installed, but I must be connected to Internet and trust that some particular domain, controlled by presumably Google, maintains it. I struggle to understand why no alternative debugger for arguably the world's most popular language exists, or at least a local, independent copy of the debugger that is untethered to the whims and desires of an entity as trustworthy as Google.

I guess I'll be having to whip up at least the latter option (which seems feasible enough, if a little tedious; with ungoogled versions of Chromium available by some kind souls as a starting point) when have a bit more spare time, to keep my sanity checked.


WebStorm and VSCode both have OK debuggers, but in my experience they are even more finicky than the Chrome one, which as you noted does have issues. Firefox and Safari are likewise fine, but not as good as Chrome.

More importantly though, if you are that distrustful of Chrome, you probably should not be using Node because it is based on v8, the Chrome Javascript runtime.


There are basic things to be desired with the current state of affairs, beyond the trust of Google, such as:

1) ability to debug locally, without an Internet connection.

2) ability to debug reliably, without fear of debugger features becoming 'updated' when one needs it most.

The fact that no independent debugger, without the Leviathan that is Chrome, exists, only hides this aspect even more, hardly doing justice to the importance of debugging in the practice of software.

Regards to the Firefox and Safari debuggers, they do not seem to be viable in practice with the alternative Javascript runtimes mentioned, both very popular and widely used, which is the reason that I claim Chrome DevTools to be the de facto 'Javascript debugger'. Neither do the two tools offer a debugger independent of the browser, as far as I am aware.


Have you tried VS Code or WebStorm? They are both independent debuggers. They are quite good for debugging in my experience. I don't know that they offer profiling capabilities.


@qazxcvbnm I don't understand: you don't want to use the chrome debugger but also don't want to use an IDE debugger... it's not clear what would meet your needs and wants, you're rejecting all the main options.

Here's an overview of some of the tools in case that's useful: https://sequoia.makes.software/debugging-nodejs-talk/#55


I reject the main options for the reason that the main options are unsatisfactory.

Your link lists the Chrome debugger, IDE debuggers, and the node inspector.

The node inspector is essentially deprecated. IDE debuggers more or less piggyback on the Chrome DevTools protocol, and although I mentioned I have not given them a fair try, but they definitely seem less official, featureful, and well-supported compared to the Chrome debugger. The fact is, this aspect of Javascript seems to have, unceremoniously, already fallen into Google's sole leadership, direction, and discretion, by force or by will.

The Chrome debugger, as mentioned, exists and is probably the most well supported of all debuggers, and is what I use in practice. However, as I mentioned, even 'the best', which is Chrome, does not work very well, exhibits usability regressions per the cadence of Google (e.g. blackboxing used to work, but is very broken today), and moreover compromises basic functionality and freedoms, which comprises my dissatisfaction.

In a better world, we would have something that is native to the language (not a browser), versionable, free, featureful (e.g. profiling and memory debugging), and accessible from the shell (e.g. other languages have gdb, pdb). It would be a good thing for a protocol to actually have multiple implementations.

Something that may at least recover basic functionality from the Chrome DevTools would be to degoogle it for hermetic usage, and separate it from the browser proper. As I mentioned, I am looking forward to make that happen.


I confess that such IDEs and their plugins are not my cup of tea and have not given them a fair chance. Though I am skeptical, with the many inconsistencies that runtimes present even for Chrome, perhaps they do work and I may give them a fair try.

Still, unwilling tight coupling with an IDE is still quite unsatisfactory.


It's not really a tight coupling at all in VSCode's case. Open your folder, let it generate a small launch.json in a hidden dot directory, and that's basically all there is to it. It's not like some heavy Java/C++ kind of thing where you need some massively complicated build system and project file.


I think Firefox's debugger is still extremely viable for web development. The Firefox Developer Edition even puts the Dev Tools nicely at hand in the toolbar and other places.

It can't help enough with Node or Hermes, but those are too tied to v8 and thus Chromium internals to start with. (Which definitely leaves some questions about the current JS monoculture.)


I am a product of a coding bootcamp from awhile back, so JavaScript is really the only thing I’ve ever known in my career (outside of writing some apps in Visual Basic around 2001).

Maybe it’s because it’s the only thing I’ve ever known, but… I like it?

I guess if I hack around on a side project and want to use vanilla JS, it’s the Wild West and there’s no rhyme or reason for anything (and everything looks gross).

But working inside various frameworks have been pretty enjoyable for me.

Side note: there’s also this hilarious video about the… delightful nature of JavaScript from 2012:

https://www.destroyallsoftware.com/talks/wat


JS itself is perfectly fine and quite a nice language when you stick to all its modern idioms that you learned and use today. I think what rankles a lot of people is going through the history of JS when it was terrible and confusing, then basically just jQuery, then the explosion and confusion of server side/node and drama with the company behind it, and finally confusion and drama with moving to modern ES modules.

For the longest time doing the most simple thing in any programming language, putting code in a separate file and loading it to execute, was nearly impossible in JS and required learning and picking sides in an opinionated loader battle. It was confusing and pretty bad for newcomers.

Nowadays all that drama is settled and the core of modern JS is quite nice. I like it more than python to be honest.


> and finally confusion and drama with moving to modern ES modules. (...) Nowadays all that drama is settled and the core of modern JS is quite nice. I like it more than python to be honest.

Using a mixture of old, deprecated versions of Webpack, Angular, Babel, and Typescript, and a very big pile of code with plain bad (if not plain wrong) type annotations I wish that statement applied to me.

Constantly attempting to keep all this nodejs stuff without vulnerabilities while migrating the least ammount of stuff at once is a daily challenge.

And that comparison is pretty low bar, everything involving say pytorch is a flaming pile of bad waiting to explode.


The problem with JS these days is not that what's there is bad. It's that there's not much there. Anything beyond the basics requires you to roll your own or go hunt for a library.


Very true, it's why I really like deno for server side since it's trying to plug that gap with a nice out of the box standard library. Client side it does feel like something like lodash is the new jQuery and just mandatory to use everywhere.


And then of course you have to pick between lodash and ramda (I'd say "whichever your dependencies use" but every time I've tried to use that as a deciding factor the answer has turned out to be "both").

It's all a bit of a cambrian explosion but it at least means you run into "this awful API has been baked into core and now we're stuck with it" less often.


Anecdote: when using Metalsmith and a sampling of plugins to build my fairly minimal static site, I ended up with 18 direct dependencies and 200 transitive dependencies, including 6 different file name matching libraries.

I now prefer comprehensive standard libraries.


As in, there's not much in the standard library? What other options are there beyond "roll your own" or "use a library"?


Don't use?


I always think back to this talk when I come across a WebAssembly Text file, annotated by .wat. Highly relevant to the author's prediction about the future from 2014 as well: https://www.destroyallsoftware.com/talks/the-birth-and-death...

https://developer.mozilla.org/en-US/docs/WebAssembly/Underst...


I appreciate the summary of the changes in the javascript ecosystem over the last decade+; all of that happened after I had kids and I didn't have the motivation to keep up with it, so it's a complete blur in my mind.

I've tried at various times to get caught up, but it seems that every time I find articles / blogs that talk about How Things Are Done at the time they're written, with only the briefest nod to how it's better than The Old Busted Way (probably because the authors, being steeped in and surrounded by javascript for years, think that their readers will also be similarly up to speed).

Meanwhile, I feel like a historian in the year 5000, reading recipes from 2023 and wondering whether people used dog milk or cat milk (because those were the two kinds of mammals that most households had available).

Does anybody know of other resources that go into more depth on the evolution (and specifically the Whys) of the javascript ecosystem?


"Modern Javascript for the Impatient" does a good job for the language itself. It doesn't try building on non-existent prior knowledge. It assumes you program, but in other languages.


I think there's a small but growing group of people in the JS ecosystem that are beginning to explore a more "platform native" approach to front-end development, which removes the need for bundlers and transpilers and embraces the fairly capable feature set of most modern browsers.

As the OP points out, a lot of what happens now is an artifact of the history of how these things have developed, and about which things were prioritized over the years. Many of these choices made sense at the time but may no longer be necessary, and some things were definitely lost in the process.

When we were developing Cappuccino, which includes its own transpiled to JS language (possibly the first such general purpose language), one of our important goals was making sure the compiler could run in the browser itself so no external build tools were needed; everything worked just dragging index.html in the browser and writing code in <script> tags if you wanted. Security changes in how browsers handle file: URLs made this harder to do, but anything that simplifies the process of actually running code is very welcome.


> Nobody Writes JavaScript Any More

This is how "delightful" it is, and is the reason I'm waiting for it to die.

Every couple of years we decide on the 'no no, definitely this time we have it all figured out, trust us, just use X' "solution" to the problem of JavaScript. We have the definative 'this is how you do it', until the next one.


> I'm waiting for it to die

I'm there with ya, but I wouldn't hold your breath. I'm trying to minimize my JavaScript exposure by using streaming, and it's going well enough with a minimal JavaScript "runtime". However, I still find myself with thorny edge cases like "I need a better date/time picker", "color picker", or a drag and drop calendar planner.

I find myself frustrated with the ecosystem, and I'm debating how large the set of exceptions are to my ideology.


I don't know enough about WASM to know why it can't be exposed directly to the DOM, since in theory the DOM should be a language-agnostic interface. If that were to happen, I think the floodgates would really open on WASM and we'd finally start to see JS die.


Exactly what I thought a few months ago.

The DOM and the HTTP api (or pretty much all browser APIs for that matter) should be interfaces that can be implemented in WASM code. I have no idea why this hasn’t been proposed let alone implemented. I mean, why give us the ability to use other languages if we can’t implement the (browser) APIs?


If having access to all browsers API had been a prerequisite to getting WASM on the browser, we’d still be decades away from having that, and we’d still be debating what the APIs should like in WASM. I’m grateful that people went for the pragmatic approach.


Sure but what I’m curious about is why? I looked it up after I made my original comment, and it has something to do with the fact that several DOM APIs are specific to JavaScript. I can see why that would be difficult, but not “decades” difficult.


The only real problem with Javascript is people's lack of understanding of it - and it's not even that difficult.


This. It fucking sucks. I just waded back into it and I hate everything about it. VSCode barely copes, Visual Studio doesn't even try and Rider was the only thing that worked which hasn't helped my mood.


I think this is pretty much all of programming.

Or life in general.

There’s plenty good and plenty bad. It’s no use fixating on things you can’t change. Focus on what you can do.


Javascript is not going away anytime soon, probably. Personally, I'm waiting for React to die.


As much as I love React and it has been a positive part of my career, I'm starting to think there really are better alternatives. Its staying power may just be the sheer number of people supporting its ecosystem and competent enough to build things with it.

I'm content to keep working with it, and I'm so familiar with it that for small tasks it's kind of my go-to. If I was building something I wanted to be long-live a future-friendly, I might be hesitant to run with React at this point. To be honest though, I'm not sure what's better than would be a clear contender for having similar staying power. I wouldn't complain if that turned out to be Solid.


LoL, and so it begins ...


I must be the only person left not writing TS at this point.

Once EcmaScript adopts optional static types or some kind of standardized type annotations [1] I will probably use those. At least in Node, where I have more control of the runtime version.

[1] https://github.com/tc39/proposal-type-annotations


I'm with you. I do not want my code transpiled. I wrote vanilla JS and use Typescript only as annotations (https://www.typescriptlang.org/docs/handbook/jsdoc-supported...)


You're not the only one. I'm sure Typescript is nice / better, but I don't feel like having yet another bullshit language foisted on me. Also I dislike Microsoft.


Typescript is just Javascript with more features. Why would you not embrace that? There's nothing taken away, only added.


I'd barely call it a new language, it's just javascript where you actually document the allowed structure of your data.


typing saves so much time. Especially since the flexibility of its optionality does not restrict, and allows for really nice autocompletions.

Especially with esbuild which has made this simple and fast, one could even say it has saved javascript.


I have ample experience with typed languages like C++, C#, Java, Kotlin, Go, AS3, Swift, etc.

Maybe I just have exceptional memory but I rarely encounter a problem that would have been solved by using TS.


It's about big codebases and team use, not about you.


Yep, they're a communication and documentation tool that happens to have pretty-good machine readability and correctness-checkability. Sometimes the person you're communicating with is your future self, is all. Sometimes it's just yourself five minutes from now, even.


They didn't mention big codebases or working on a team, though. Also, you can just use JSDoc.


Even in a solo project, you import libs from others. Never felt the need for those libs to have types.


Every use case is different.


Typing wastes time. Teammate and I tried switching a backend project to TS, and I kept a mental note of time spent defining types vs time saved not debugging type-related issues. The result was some high number vs 0. Also messed with the toolchain, making things like Node profiling not work.


If you already have an existing, functioning codebase, adding types is not saving you time (right now). It's akin to adding a lot of unit tests. You gain time later, and often indirectly from others not making mistakes your types would prevent.


Ample time passed, we added more after we were already on TS, and it wasn't helping. In fact it was a constant burden on new code.


Alright, good luck out there. I strongly prefer types


Is it a solo project? The time savings of typing is really a function of project size and number of collaborators. For a small, solo project it’s either neutral or a negative.


It was team-sized. So, not writing open-source libs used by multiple companies or something, but ~10 people were looking at the code.

At my current job we do have a lot of untyped Python used by tons of people, and it's fine. People can read the code without it asserting in every line what each variable is. You just make sure any widely-used APIs are documented properly, which typing doesn't really help with. Also anything modern is more microservice-oriented which comes with nicer boundaries, and everything has tests (which again typing is no substitute for). Typing seems like a mostly outdated thing for application-level stuff.


Believe it or not, autocomplete is still possible without typing, as any user of any dynamic language could tell you. Seems like a poor reason to add a another full language to the abstraction ladder of your application.


I'm still using Javascript and jQuery. In combination they work just fine. I took the time to learn TS, but I never felt the need for it.


I started writing a small static site generator for myself using JavaScript and QuickJS by Fabrice Bellard[1]. QuickJS is not quite complete, and there are some cross-platform inconsistencies, but overall I found it pleasant to use and its libc wrappers to be powerful enough. I also found that JavaScript is actually pleasant to use when I'm not using classes, or dealing with metaprogramming/Babel, or implicit globals. Dependencies are just pure .js files I keep in a /lib directory and import.

I still think JS is a nice language although I tend to side with Crockford (before he started promoting the "next" language) in that JS has some good parts, and you can write clean and powerful software with it if you ignore most of its warts (even if you're using Node). My best advice is be very careful with what dependencies you choose; and also, don't feel pressured to be at the bleeding edge all the time. The Node/React world is a constant hype machine that flip-flops on best practices every 6 months. Be very skeptical of them, and don't let them spoil JS for you.

[1] https://bellard.org/quickjs/


what's the use case for quickjs? can it be used for a light-weight runtime for JS on resource restricted embedded devices?

by the way, comparing to angular and vue2-vue3, react is actually the one without python2-python3-alike breakages over the years to me, I would say it's the best out of the 3 options(angular,vue,react) so far, which could explain by market share that it remains to be dominant.


Not OP, but I experimented with QuickJS for my SSG and, on my super slow laptop, it started up about 200ms faster than Deno, but ran about 5 times slower overall (and the binary was much, much smaller).

My original motivations were: Deno doesn’t support Raspberry Pi and I was running lots of short-lived processes to support incremental rebuilds using a Makefile. In the end, my requirements changed, so I’m not using QuickJS, but it was very easy to pick up and use.

So: portability, startup time, and small code size seem to be the advantages of QuickJS.


Yeah, the QuickJS interpreter is less than a megabyte compare to Node/Deno's >60MB or more install. My use-case was that I wanted something lightweight that I can run on lower-end hardware or in a CI pipeline to generate my site. At first I looked at bash, but I find bash gets unwieldy for more complex operations. I like JS as a scripting language, and QuickJS seemed to fit my YAGNI approach.

Indeed, React the library is generally stable. But React the ecosystem is not; best practices change every 6 months. Libraries gain popularity and then are abandoned, or people just realize the cost of using them. SSR vs SPAs? Wait you're telling me CRA is basically deprecated now? etc etc.


I can't help but cringe when looking at the dependency count when using some javascript framework to write client-side code. I think the frameworks and the ecosystem is overly complex and the same could be accomplished by embracing minimalism. I do like things such as babel and webpack though, but those are dev-dependencies which is unrelated to the contents of the final bundle and I can live with few dev dependencies.

For my last project I wrote just plain old javascript without any frameworks, but I did use dev dependencies such as the ones I mentioned above. It was a breeze to implement things, but I do understand that the benefits of frameworks like React become clear in larger more complex projects. So all in all I don't really know what should I think about the current state of the ecosystem, nor am I really on the edge of the wave of progress, but the kind of feelings I often get is in the lines of 'is this dependency x really needed here? what does it do? oh it does this small little thing, why is it here??'...


Vanilla Javascript is comfortable. I think I've pretty much given up on the JS ecosystem. I've been going back to web frameworks like Django / Rails / Laravel. Obviously not the solution for all things but most projects really don't need to be SPAs.


Wish we had something simple like jQuery


I mean you can still use jQuery, no one's stopping you. They're still releasing new versions with updates, the last one came out two months ago if I'm not mistaken.


Just use mithril


Weird? Absolutely.

Delightful? Try managing a monorepo with internal dependencies and multiple target platforms and you will immediately and firmly say 'no'.


Good article. There's of course editorial decisions about what to mention but still the in the Nobody part the JS-as-compile-target coverage seems a bit selective. There's of course ClojureScript, Elm, Scala.js, ReScript and TypeScript (the latter is mentioned in passing).


So what was weird exactly? react is not JS. nextjs is not js..... same way spring boot is not java. JS is the way it is. Most of it complainants has issues as they usually come from synchronose language and when JS (its true power) uses its async nature, they can't comprehend it and think its weird, why would it do so. If your rational is that its slow, you should probably use assembly to write the most optimal code. If you want a high level language then JS brings most paradigm than competing languages. If you argue to want all features high level, low level and speed go for C++.


> nextjs is not js..... same way spring boot is not java

does spring boot bring it's own dsl and compiler?


Kinda, as usual within Javaland, there's a lot of reflection involved into making annotated interfaces (a kinda of standard Java reasonably limited dsl capabilities) pop up as singletrons connecting to your database/OLAP/LDAP/REST-endpoints/websocket-clients/whatever.

Same thing for serialization things, you define interfaces, the actual classes often just pop into existence by generated bytecode.

It's also not unknown to bring JSP/EL (literally requires a Java Compiler embedded in your server to compile servlet objects for you on the fly) or some other, on purpose less fully featured template things with their own DSLs like Thymeleaf to do the same job.


> When a bundler/transpiler encounters an import statement, they don't necessarily presume that the file being imported is JavaScript or even any of the variants mentioned above. If configured properly and you want to import a CSS or PNG file, it will happily do so for you.

This is what I like to nickname "WebpackJS". Code that is simply invalid JavaScript and requires a carefully configured composition of webpack plugins in order to be used. I occasionally run into npm packages wanting to "import" a CSS file when I use them from ClojureScript, and it's always a pain. The good news is that these ar rare encounters, but it's still behavior enabled by people assuming you're using the exact same framework as them with the exact same Webpack configuration made by said framework.


Oh I hate that shit. It feels so broken. Someone creates "a library" in CRA or webpack, and then you can't just import it in your project easily.


I wouldn't call it delightful, I'd call it diaherra


Sounds like you haven't worked on a production javascript project yet.


>"Nobody Writes JavaScript Any More"

I code single page apps that talk to business backends using JSON based RPC. All in plain JavaScript with some domain specific libs when needed. No problems so far.


I wonder how much of this can be blamed on JS being a relatively gentle and forgiving codegen target.


I suspect that if some accidents of history hadn't left JS as the only language you can use to script a Web browser, it would have died off long ago.


I want to disagree, but I think you are right. Java and Flash were the only alternatives to javascript that ever gained a foothold, and both of them were second class citizens. Circa 2001 I tried to use Java to interact with the DOM and ran into a browser bug that iirc took about a decade to fix. If the technology had ever been usable things might have turned out differently (or it might have turned out the same, who knows).


I've been wondering about that lately. What is the rationale for making it necessary to run WASM binaries through JavaScript? Seems like a missed opportunity to not be able to just point a script element at a WASM blob, but I'm sure I'm overlooking something.


It is one of the many things being worked on. The truth is that no part of the web standard bodies has WASM as a priority, so it moves slowly.

Anyway, on practice all that means is a bit of lost performance on the DOM interaction. It's a big deal if you do a react-like framework, but the DOM has bad performance anyway, so people tend to not create react-like frameworks.


When I last looked, it seemed like WASM blobs just take arrays of numbers and return arrays of numbers. No objects, strings, or DOM elements, so I think it'd be tough to do web dev in wasm as it stands. And you need javascript glue if you want anything in the way of side effects.

There is, however, quite a bit you can do in it. TeX has been compiled to wasm[1], it's about 600kb uncompressed 90k compressed (the memory image with latex loaded is about 6MB compressed though - latex is a beast). I think anything computationally intensive would be a good candidate for wasm (it has int64).

1: https://github.com/kisonecat/web2js


Right, yes, that's how WASM is now, but what I'm asking is why didn't we give WASM access to the DOM? We could have, and we just didn't.


Sounds good to me, I was disappointed when I learned that wasm didn’t do this already. (It’d be nice to have tail call optimization too.)


Google already tried the blob with Native Client, but I recall Firefox decided not to support it.


I don't think that's true. I find Crockford's argument compelling that js is misunderstood and that the core of the language is a diamond in the rough.

https://youtu.be/47Ceot8yqeI?list=PL7664379246A246CB&t=3792


What else was there, besides VBscript, or whatever Microsoft was calling it then? Even if we're only talking hypotheticals, at what point would anyone have attempted to release an alternative?

Everything was mucked up well into the 2010s with everyone chasing IE compatibility. And not even 3 years later, Chrome had taken over the world. That's a really brief window for anything to happen.


What else was there? Plenty of stuff! It could have been a lisp, it could have been a flavor of pascal, python was around even if it wasn't popular yet. Thank heavens we didn't end up with a flavor of BASIC, although as you point out it could have happened.


js is pretty lispy. Crockford is pretty compelling that the reason js survived (and beat Java which was the heir apparent) is because of the attributes it inherited from Scheme.


The idea at the turn of the century is that Java Applets would be the way web applications would be developed. That was a disaster for security, ux, etc.


I think what makes it a popular codegen target has more to do with

- The places it can run

- The ecosystem it can interop with

Not that it's a bad codegen target otherwise- it's high-level but performant for being so high-level, it's garbage collected, first-class functions, low-level primitives are available for optimizations, etc. But these on their own don't make it super unique


How is it a better codegen target than any other language? That's not intended with an argumentative tone- I'm genuinely curious as to what you mean.


Hum... A lot of people is working on JS codegen, so there are all kinds of knowledge bases, libraries, and standards for it. Also, JS itself got some changes to support it better.

So, yeah, it's a better target than most general purpose languages. It's surprisingly simple to generate, much simpler than to write on. It is also a worse target than most languages specialized on being generated.


It's only a half-informed thought. I work on a project that compiles a domain specific language to C and C++. When I think about JavaScript as a codegen target, all I can see is all the problems I wouldn't have.


Javascript benefits from the major efforts put into its JITs. No other scripting language really has that.


So JS is delightful because we are still not actually writing JS, but stuff that looks like JS? Huh.


It's weird how JS is the only ecosystem entirely designed around the premise of avoiding direct contact with the language you're developing in at all costs.

Like, even C programmers are willing to actually write C.


Rust has a far more powerful and widely used macro system then JS but I don’t think that means rust devs are trying to avoid writing rust at all costs


The C macro language is technically a different language (though today they are specified together, they originated once as different compiler tools) than C and lot of DSLs get written in it because C programmers are trying to avoid actually writing C.

There's also a lot of C programmers that prefer to use C++ compilers in C++ mode for their C code to avoid direct contact with C specification bugs or some C standard libraries.

(Plus, early C itself was designed to avoid direct contact with Assembly languages which was designed to avoid direct contact with Machine languages some of which were designed to avoid direct contact with Microcode languages most of which were designed to avoid direct contact with TTL logic and TTL logic was designed to avoid direct contact with the useful properties of transistors for computation and so forth. Programming is turtles all the way down.)

(Also there are quibbles to be made about "at all costs". JSX is still a superset of JS syntax with a little bit extra added in. Typescript is built to be a superset of JS syntax. You can't write either without a lot of direct contact with JS. Neither seems like "at all costs" avoidance to me.)


That is not what the author said. They said the JS Ecosystem was delightful. He then goes on to describe that Ecosystem. For some people that ecosystem is indeed delightful. They love the sheer complexity it takes to deploy a JS application these days. There is certainly a lot of choice and power out there for it.

I personally am the kind of person who tries to ship my stuff as a single statically linked binary that I can just drop in place so I look as WebAssembly as a way to participate in the browser ecosystem while avoiding the whole NPM/JS Tower of development tooling complexity. I don't begrudge others from wanting to play there though.


I've avoided JS/TS almost entirely, and shown contempt toward it a bunch in the past. I'm now at a place where TS seems like a reasonable language for prototyping backend stuff: JS has a GC, big package ecosystem, sum types, static typing, good tooling support.

Only thing that ticks most of those boxes (IMO) is Kotlin. Anyone been down this road before (skeptic->using in prod)?


Dart appears to tick some of those boxes, but probably not the big package ecosystem and sum types boxes. I'm considering building something with it at the moment, but I'm hesitant to commit much brain power to something Google has a lot of influence over. Yet, Go has been awesome and I don't regret learning it. In some ways, Dart looks a bit like what I wish TypeScript could be, though not exactly.

Something I use a lot in Rust is exhaustive matching and sound types, which Dart now has. It's a somewhat specific thing, but I like designing finite, well-scoped systems which can be handled and tested almost completely. Doing this in TypeScript is kind of possible but can be incredibly verbose and difficult to navigate for less experienced programmers. While the design patterns aims to simplify and eliminate errors, the type system can easily complicate it and introduce mistakes.

That's such a drag in my experience. For example, stuff like this can happen in TypeScript: https://www.typescriptlang.org/play?ts=5.1.0-beta#code/GYVwd...

However, TypeScript has come a long way and it gets better in this regard all the time.


I used to avoid JS then tried it for backend stuff, finding it actually the easiest way to do web backends. Most off-putting thing was the "callback/promise hell" erroneously recommended in tutorials until I realized you're actually supposed to use async-await. Then React Native instantly converted me from the horrible native iPhone dev, then got me into React (web). So I'll do new app projects fully in JS.

I also gave TS a serious try and found it pointless. Complicated the toolchain, made default stuff like the Node profiler not work anymore, and wasted tons of time on defining types that didn't actually catch any mistakes. Went back to JS. Turns out part of its strength comes from not caring.

Before that had used Java, Scala, C, C++, Erlang, Python, Swift, ObjC, Rust, PHP, and a little Golang.


> Most off-putting thing was the "callback/promise hell" erroneously recommended in tutorials until I realized you're actually supposed to use async-await

Async/await's pretty new, is probably why you're seeing so many tutorials that don't use it.


Yeah, but even new documentation sometimes uses promises, particularly anything related to Google like https://firebase.google.com/docs/auth/web/custom-auth


The page has a 2023 last-edited on it, but the code snippet (if you follow the GH link) hasn't been touched in two years.

If their JS docs are anything like their Android docs, Google's terrible about updating examples.


async/await is still pretty old by now. Maybe they wanted to be consistent with even older examples. I dunno, every single thing Google-related uses promises, so I'm thinking they're partial to that for some reason.

Another example from 4mo ago: https://github.com/kubernetes-client/javascript/blob/master/... (the catch at the end is a promise catch)


There's a tiny benefit of the doubt to be given here that while async/await is several years old, support for "top-level await" was only more recently standardized and took too long for common LTS versions of Node to also support it.

All of these examples appear to be top-level and perhaps they didn't want to write them as async functions or IIFEs, especially for error-handling code.


That makes sense, someone copy-pasting async code into a JS console would get errors not too long ago.

There's nobody to blame for this but myself, just wish I discovered earlier on how async/await works, along with other modern JS stuff that you won't see everywhere because it's new.


> deliberately misuses the JavaScript label syntax

Eh, deliberately repurposes. I don’t think “misuses” is the right word at all.

> abuse of the bundler

This also feels too strong a wording—though the fact that these are at least .js files (unlike .svelte files in the other case) makes the term “abuse” less unreasonable.


I think it is a big plus that the JavaScript community embrace code generators.

I mostly write C++ for a living, and I use code generators all the time. Generating C++/Java/Typescript/SQL/… from high level declarations.

Code generators are great tools for automating away the necessary but no-thinking-required parts of a typical app. I am typically able to code generate more than 90% of the application code needed to implement a new client/server business system. So why not use it?


I find this like saying you are actually writing binary code, what you code is not any language at all.


Hmm, it's a shame that Little Javascripter is not mentioned: https://www.crockford.com/little.html That is really the only positive reason to use JS.


> The mind bending parts of this presentation are where he first utilizes use server to implement a client side form action, and then later launches a client side alert from the server using use client. And he closes by saying that this requires new generation routers and new generation bundlers.

No, it just requires a basic websockets implementation and a normal HTTP server. If anyone else like me loves JavaScript but thinks the above line of thinking is bananas, join me on the lifeboat [1].

[1] https://github.com/cheatcode/joystick


The JS ecosystem also relies on npm, which is owned by Microsoft. Having a corporation control package management is pretty weird.


Well, now that Microsoft has embraced and extended open source, I think it's time for us all to let our guards down, because it's not like they have some kind of "third step" to their business plans.


Something something pnpm, yarn, jfrog


I believe they don't have registry or independent mirrors. Which CLI tool isn't that important.



Controversial opinion rant below:

I think the weirdness is a cycle kicked off and perpetuated by how accessible web development it.

It's a good thing that it doesn't take a comp sci degree to build a completely functional, professional looking and/or profitable JavaScript powered application.

In addition to the exclusivity of JS in the browser - the ease of becoming productive has been a large driving force of its widespread adoption. The cost effective nature (cross platform, ease-of-development, abundance of skill) has played a large part in its ubiquity.

This large number of developers has resulted in a large market for tool makers.

Tools are difficult to profit from, so toolmakers adjust their business models and marketing to suit.

As a result, a lot of developers write self promotional blog posts sharing "best practices" and plenty of impressionable decision makers dive head first into well marketed trendy tools/technologies that _may_ offer a benefit but often not proportional to their cost (vendor buy-in, additional complexity/reduction in project maintainability).

For example, front end projects tend to prematurely optimise with huge foundational features like SSR - without considering their use case, the performance trade offs (caching, amongst others) and other more ergonomic/cheaper/more effective, optimisations.

Despite not requiring it, developers tend to highly _highly_ couple their presentation logic to their application logic to the point where throwing away and rewriting an application is not an unreasonable sounding endeavour. People don't write an application that uses React, Vue, Angular - they write a React/Vue/Angular application.

The current meta has moved away from boring obvious procedural circuits to dense, clever, fancy functional circuits which I (controversially) find difficult to grok, modify, and debug. I certainly use functional code (like functional components are nice for simple use cases and .filter/.find are nice shortcuts), my feeling is that deep functional chains are perhaps overemphasised now and difficult to mentally simulate when reading (which you must do inside-out, holding each step in your head).

Testing is also a huge pain point. Developers tend to make extensive use of features like module mocking (`jest.mock('./filename')`) and avoid any form of dependency injection (not talking about DI frameworks, just simple property injection). If there is a hell, module mocks were sent to us from there. So many times I have made changes to a file where module mocks prevented tests that would otherwise have failed from failing. They are hard to track down, fail at runtime and... cries

Today, when I consider joining a new company and hear a project uses React, NGRX, Redux, Next.js, SSR, and a few others - I can almost immediately assume it's going to be a contribution and maintenance nightmare.

I still love front end even though it is an endless source of headache-inducing eye rolls watching people shoot themselves in the feet while confidently claiming it's the best way to run faster.


I moved away from JavaScript because of the same reason I moved away from PHP.

An originally decent idea gone terribly wrong.


IMHO JavaScript is neither a good OOP language not a good Functional language.


Unfortunately I think the opposite. JS was a great prototype-based language, but very few understood those and tried to fit it into functional or OOP mindsets.

When they started talks about adding classes to the spec I knew I had to run away.


> JS was a great prototype-based language

Maybe it's just me, but everything distinctive about prototypal OO falls firmly in the category of "please never actually use this in a codebase I have to work in".


Well, I agree if your experience was around codebases that tried to fit JS in the OOP category.


Well, then you don't think the opposite. JS is a bad OOP or functional language, but a good prototype-based language. Bad thing that no one wants such language.


I can't disagree with the "no one wants" part unfortunately, no matter how good my counter-arguments can be.


Don't blame you. Hard to disagree with that. Ever since JavaScript became important (famous web 2.0 yay) everything in the JS ecosystem was about making it more like Java style OOP and recently more functional style.

There were so many shims to emulate that style of OOP.


How do you build web applications?


I don't. I build backend services now.

But to be fair, I still maintain a relatively popular Chrome extension in old-school JS and that's still a pleasure to work with.


There are plenty of ways these days to build rich web applications without writing much JS. LiveView, Hotwire, Reactor, LiveWire, Blazor...


Not really against JS as a language, everything against the current state of its ecosystem


Not sure I fully follow where your response is aiming but if I understand correctly, I don't hate JS but I don't like using it for business logic. I feel these frameworks (I use LiveView) let me use JS what it's good for: a DSL for complex DOM manipulation. Everything else, including simple DOM mutations, is handled by LiveView and I can write business logic in a nicer language.


Well, that's one way to put it.


not sure I'd call it "delightful" in any way, but it certainly is weird.


That would be a polite way to put it yes.


I stopped reading after the typo “JavasScript” and then the juvenile tone of “Less that 10 years ago, JavaScript sucked bad.”

I have a positive impression of fly.io overall, I mean they admitted they are still figuring out how to build tech at the level of their ambition and have it be reliable enough, but I might like to be a customer one day.


> the typo “JavasScript”

You may be interested to know TC39 makes the same "typo" at https://tc39.es/ right in the biggest header on the page.

> Specifying JavaScript.

Hm, maybe it's not a typo?




Consider applying for YC's Summer 2026 batch! Applications are open till May 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: