Hacker News new | ask | show | jobs
by mkl 1682 days ago
It's holding JavaScript to its own higher standard: <script src="..."></script> is dead simple, and trivial to understand and get working.

NPM, import, etc. seem mindbogglingly complex in comparison, with an enormous number of ways to do each thing, most of which require at least one build step <script> just doesn't, and enormous numbers of third party dependencies, and if you go away for a few months and come back, there are good odds things will be different and broken.

Like Julia, I don't understand JS build systems and packaging etc., which no doubt contributes to the above experience, but I'm comparing to <script>, whose simplicity is almost unbeatable.

2 comments

> It's holding JavaScript to its own higher standard: <script src="..."></script> is dead simple, and trivial to understand and get working.

The most simple example is almost never a representative example that can be used as a standard to hold the whole language to.

In the same vein, one could say: "See how easy it is to build a C program with `gcc main.c`? Why should I have to figure out how to use make?". And the answer is simple: Most projects that go beyond a toy example have much more elaborate requirements(/whishes), like "I'd like to reuse code that another person has written in the past so I don't have to do it".

C also lacks a sane build system, so if you’re trying to make the point that JS isn’t so bad, comparing it with C isn’t the way to go. Consider that no other language needs a bundler with all of the weird stuff it supports. You might argue that it’s good that JS supports all of these things and that’s fine, but what you’re really saying is complexity is good which is also fine but incompatible with the “JS is no more complex than other languages” position.
Most languages also don't really have to worry about shipping dozens of plaintext source code files over the wire that then might get executed in an environment you have no control over that doesn't actually support the code you wrote (There are still people running old IE versions and loosing 1% of customers might be really costly at scale). I'm not saying that the current ecosystem isn't an overly complex mess but it does actually solve some problems.
I empathize with the unique difficulties of the web and I don't doubt that the complexity solves for real problems (e.g., old IE versions); however, I take issue with treating all problems as equal irrespective of how niche those problems are. The C and C++ folks make the same kind of argument to justify their abusive build systems--if the build systems made sane assumptions, then it would exclude certain niche use cases. Of course, we all agree that sane tooling excludes niche use cases, but we disagree about whether excluding ~1% of use cases for a dramatically improved experience for the ~99% is worthwhile (and we may even disagree about some of the qualifiers I used in this sentence).
Webpack sure has problems (for example speed) but most of the more niche things that people do aren't actually supported by it but implemented through the plugin system, at which point any category of niche/sane kind of flies out of the window. If you enable people to do weird things people will do weird and maybe unwise things. The best solution might be to take notes of how people tend to develop js stuff nowadays, scrap javascript completely and use something completely new that doesn't have the issues of javascript. But that seems rather unrealistic at this point.
There is no problem JS transpilers+bundlers tackled that earlier compiler writers had not tackled, better, before.

> shipping dozens of plaintext source code files over the wire that then might get executed in an environment you have no control over that doesn't actually support the code you wrote

What does "plaintext source code" or "over the wire" do to distinguish this from "compiling a binary targeting a minimum supported ABI"? Bundled JavaScript doesn't even have to deal with dynamic linking!

> There is no problem JS transpilers+bundlers tackled that earlier compiler writers had not tackled, better, before.

I'm not sure what I am supposed to do with that statement/answer? It's obviously very easy to just assume that every js developer must be an idiot but that is hardly a fruitful discussion to have.

> What does "plaintext source code" or "over the wire" do to distinguish this from "compiling a binary targeting a minimum supported ABI"? Bundled JavaScript doesn't even have to deal with dynamic linking!

Correct me if I'm wrong on that but it doesn't really matter if something is written in Go, Rust 2015, Rust 2018, Rust 2021, Zig, D or whatever else comes to mind, assuming static linking of course. I can compile it, I can ship it and the binary will work. I can't just ship typescript out, browsers don't understand it. I can't just ship modern js out as I have no idea if the users browser understands the code. Bundled javascript doesn't have to deal with dynamic linking because it is, in essence, static linking. The whole dynamic linking thing was sort of tried with CDNs shipping js libraries, didn't really work out all that well in practice, relying on some different service to be available for your dependencies is only a good idea until that service has downtime.

> I can ship it and the binary will work

In this scenario, the binary is your ES3 or ES5 or what have you.

Compiling Go to an x86 ABI, Rust to the same x86 ABI, C to the same x86 ABI, etc. is an analogous problem to "shipping dozens of plaintext source code files over the wire that then might get executed in an environment you have no control over". It's harder, by order of magnitude and on every axis, than compiling TS, ES2015, whatever, all down to some lesser ES version. And yet these compilers are faster, more effective, and easier to use.

You've missed my point about static vs. dynamic linking entirely. The point is that C compilers did "bundling" for years while supporting dynamic linking, and now you're trying to say JavaScript is tackling some way more difficult problem when it has a much simpler language-to-"ABI" translation process and doesn't even need to support that?

As you say, this maybe isn't a fruitful discussion - but it's a true one. JS tooling developers got seriously deluded about the novelty of their problems and quality of solution at some point ca. 2014, and we will be dealing with the results for another decade or more. At the very least let's start being honest about it.

<script src="..."> still works. Feel free to keep using it.
I do, but it's not well supported by a lot of packages. I dig around manually for URLs on unpkg and other JS CDNs, but most libraries' instructions just say "run npm ... or yarn ...". Maybe that complexity's worth it, but understanding what's going on is a barrier for me to use it, just like Julia describes.
I'm very sympathetic to Julia's confusion and your yarn/npm frustration. But consider whether those libraries themselves might also be part of the complexity that are not worth the cost. Julia's trying to use Vue. Vue (and Webpack, and Babel, and the entirety of NPM) nominally exists because it's supposed to improve the developer experience. If instead it contributes negatively in other ways and you have to spend so much time wading through the tangled mess that it confronts you with, what's the point?

Ignoring the nullified value proposition, there are other reasons besides (like security) to reject what the NodeJS/NPM world considers standard practice.

I mainly use big standalone ones that provide enough to be worth it, and far more than I'd build myself. Things like MathJax, JSXGraph, Plotly, and D3 when I properly learn it. Not coincidentally, those aren't too hard to use without NPM.
So far as I can tell, unpkg sources directly from npm so you don't so much dig around as 'construct the URL you want'.

I may simply have got lucky so far with that but it's worked really nicely for me for quick things where I don't care about bundling.