5 ms·
Very few languages operate under the same constraints as js. When you ship js you can't guarantee the version of Ecmascript that the client will be running, or
by Vaguely2178 4y ago
Very few languages operate under the same constraints as js. When you ship js you can't guarantee the version of Ecmascript that the client will be running, or the standard library of DOM functions that will be available (which differ slightly from browser to browser), so you end up transpiling your code to the least common denominator.
You also have completely different performance requirements compared to most other languages. If I ship a python app I don't have to worry about reducing the length of variables names to shave off a few bytes, or bundling multiple files together to reduce the number of http requests. Other languages don't need to dynamically load code via http requests, they generally run under the assumption that all of the code is available before execution.
The closest comparison outside of the browser would be to the container ecosystem, which also runs code in an environment agnostic way, and there's plenty of complexity and volatility there (podman, buildah, docker, nerdctl, k8s, microk8s, k3s, k0s, nomad, docker swarm, docker compose, podman compose, et cetera).
- ashishb 4y ago> The closest comparison outside of the browser would be to the container ecosystem And as someone who has worked on both, I can tell you that the container ecosystem is way better and way more deterministic. `Dockerfile` from 10 years back would work today as well. Any non-trivial package.json written even a few years ago would have half the packages deprecated in non-backward compatible way! There is another similar ecosystem of mobile apps. That's also way superior in terms of the developer experience. > Other languages don't need to dynamically load code via http requests, they generally run under the assumption that all of the code is available before execution. And that's not what I am objecting to. My concern is that the core JS specification is so barebones that it fragments right from the start. 1. There isn't a standard project format 2. There isn't a single framework that's backward compatible for 5+ years. 3. There isn't even an agreeement on the right build tools (npm vs yarn vs pnpm...) 4. There isn't an agreement on how to do multi-threaded async work You make different choices and soon every single JS project looks drastically different from every other project. Compare this to Java (older than JS!) or Go (newer than JS but highly opinionated). People writing code in Java or Go, don't expect there builds to fail ~1-5% of the times. Nor are the frameworks changed in a backward-compatible way every few years.
- hobofan 4y ago> `Dockerfile` from 10 years back would work today as well. I highly doubt that any Dockerfile from back then would work if it runs `apt-get` (as many do), as the mirrors for the old distribution versions aren't online anymore. Dockerfiles can be made to be quite deterministic, but many use `FROM` with unpinned tags and install from URLs that can and do go away.
- Vaguely2178 4y agoExactly! Dockerfiles are not deterministic. The build artifacts that they produce (images) are, but the same could be said of js build artifacts (which would be a set of compiled and bundled js files).
- Vaguely2178 4y ago> And as someone who has worked on both, I can tell you that the container ecosystem is way better and way more deterministic. `Dockerfile` from 10 years back would work today as well. Any non-trivial package.json written even a few years ago would have half the packages deprecated in non-backward compatible way! As I wrote elsewhere [1], Dockerfiles are not deterministic. The build artifacts that they produce are deterministic, but that would be comparing a build artifact to a build system. > There is another similar ecosystem of mobile apps. That's also way superior in terms of the developer experience. Mobile app users have different performance expectations. No one bats an eye if a mobile app takes several minutes to download/update, but a website that does so would be considered an atrocity. > And that's not what I am objecting to. My concern is that the core JS specification is so barebones that it fragments right from the start. JS is actually really well specified by ECMA. There are so many languages where the formal specification is "whatever the most popular compiler outputs". > You make different choices and soon every single JS project looks drastically different from every other project. The same could be said of any other moderately complex project written in a different language. Look at the Techempower benchmarks for Java, and tell me those projects all look identical [2]. > 1. There isn't a standard project format 2. There isn't a single framework that's backward compatible for 5+ years. 3. There isn't even an agreeement on the right build tools (npm vs yarn vs pnpm...) 4. There isn't an agreement on how to do multi-threaded async work A lot of the complexity you're describing stems from running in the browser. A server-side js project that returns plain html with a standard templating language is remarkably stable. Express has been on version 4.x.x for literally 9 years [3]. Package.json is supported by yarn, npm, and pnpm. As long as you have a valid lock file and install dependencies using npm ci, you really shouldn't have too many issues running most js projects. I'm not sure what issues you've had with multi-threaded async. The standard for multi-threading in js is web workers (which are called worker threads in node). The js ecosystem is not like Scala or Rust, where's there's tokio and akka. JS uses promises for concurrency, and workers for parallelism. [1] https://news.ycombinator.com/item?id=35002815 https://news.ycombinator.com/item?id=35002815 [2]https://github.com/TechEmpower/FrameworkBenchmarks/tree/98441d39e7e95c5a96e1c6b76b78d13beb4e4041/frameworks/Java https://github.com/TechEmpower/FrameworkBenchmarks/tree/9844... [3] https://www.npmjs.com/package/express/v/4.0.0 https://www.npmjs.com/package/express/v/4.0.0
- edflsafoiewq 4y ago> When you ship js you can't guarantee the version of Ecmascript that the client will be running, or the standard library of DOM functions that will be available (which differ slightly from browser to browser), so you end up transpiling your code to the least common denominator. Isn't that the same as shipping native binaries? You don't know what version OS or libraries it will run on. That's why you do stuff like link with the oldest glibc you want to to support.
- Vaguely2178 4y agoThe main difference between shipping a binary and a js file, is that users don't expect binaries to be small, which means you can usually ship an entire runtime with your binary. If you shipped every single js polyfill with your website performance would tank. You also generally differentiate between downloading a binary and running it, and users will tolerate a loading spinner while a massive binary downloads. Webpack will emit a warning if any of your build artifacts are larger than 244KB, whereas a 244KB binary would be considered anemic.
- justinclift 4y ago> users don't expect binaries to be small That seems to only be a "modern times" thing. Prior to that, minimising the size of shipped programs (binaries, images, doc files, etc) has been important part of release management.
- Vaguely2178 4y agoBinaries were definitely leaner in the past, but there's always been that dichotomy between downloading software and running it. In the browser, users expect software to be available instantly, and that constrains how you build webapps. Users will tolerate the google maps app taking a few minutes to download, but they won't accept the google maps webapp taking several minutes to load in a browser.