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.
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).
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.
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).
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 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.
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.
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.
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
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.
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.
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.
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
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".
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.
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.
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.
"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.
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.
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.
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.
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.
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.
> 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.
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
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.
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)
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".
> "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 basically more granular code splitting combined with a smart loader. We were already doing this ten years ago, just manually without a compiler.
> 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.
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.
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.
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.
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 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.
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.
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
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.
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.
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.
> 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.
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 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.
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 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.
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.
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.
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.
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.
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:
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.
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.
> 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 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].
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++.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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, 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.
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.
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.
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.
@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.
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 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.)
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).
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??'...
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.
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.
> 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.
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.
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.
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.
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.
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.
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.
> 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...
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.
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.
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.
> 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.
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 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.
245 comments
[ 2.9 ms ] story [ 242 ms ] threadThere 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
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.
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.
https://youtu.be/47Ceot8yqeI?list=PL7664379246A246CB&t=3792
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.
- 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
Like, even C programmers are willing to actually write 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.)
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.
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.
https://www.reddit.com/r/ProgrammerHumor/comments/621qrt/jav...
* `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
Looking at the book now, I still like some sections like "Curry" and "Memoization".
where do I find these insane 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?
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.
You'll able to accomplish exactly the same with both, so why create yet another way? Seems bit wasteful..
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.
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 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.
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.
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.
Note: I'm a moderate JS dev so correct me if I'm wrong.
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.
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 === 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.
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".
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.
https://qwik.builder.io/docs/concepts/resumable/
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.
[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.
It's always getting better, and always has opportunities to get better
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.
Before long that "actually good" is lumped in with the time when it was bad... but now, of course, it's actually good!
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
But anyhow, boy oh boy, look at what we have today.
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.
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.
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 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.
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?
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.
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.
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.
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?
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
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.
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.
I now prefer comprehensive standard libraries.
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.
https://developer.mozilla.org/en-US/docs/WebAssembly/Underst...
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
does spring boot bring it's own dsl and compiler?
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.
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
Especially with esbuild which has made this simple and fast, one could even say it has saved javascript.
Maybe I just have exceptional memory but I rarely encounter a problem that would have been solved by using TS.
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.
An originally decent idea gone terribly wrong.
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.
When they started talks about adding classes to the spec I knew I had to run away.
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".
There were so many shims to emulate that style of OOP.
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.
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.
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.
Still, unwilling tight coupling with an IDE is still quite unsatisfactory.
Here's an overview of some of the tools in case that's useful: https://sequoia.makes.software/debugging-nodejs-talk/#55
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.
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.)
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??'...
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
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.
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.
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.
Most users just use arrow functions as syntactic sugar. But it's really good syntactic sugar.
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.
Close! C# programmers. :)
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.
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.
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.
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.
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.
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...
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.
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 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.
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.
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.