Hacker News new | past | comments | ask | show | jobs | submit login
Today’s Javascript, from an outsider’s perspective (verou.me)
319 points by llacb47 on May 26, 2020 | hide | past | favorite | 224 comments



I had a similarly frustrating experience when I first set up Python to use Django. The complete mess that is the Python 2/3 split (thankfully somewhat better now after many years), trying to figure out what the hell pip and pipenv were (this was before I was familiar with package management).

However, I initially learned some Python in university and I liked it then. We just installed Idle and ran some simple scripts, and everything worked. That's the right way to learn a language. If you dive straight into JS package management, you are attempting to learn multiple things at the same time:

* Node.js environment

* Browser environment

* JavaScript syntax

* 'running a localhost'

* JavaScript modules

* NPM package management

You need to tackle these one by one. If you do them all at once, even with prior experience in other languages, of course you're gonna have a bad time.

Really what I take away from this post is that the author is a bad teacher, although the experience of her student is probably similar to what many people experience when trying to learn by themselves.

There are many improvements that could be made to the JS ecosystem, but this post does not do the current state justice. What it highlights, if anything, is a problem with the available of a standardized learning path. But I'm not sure what the solution to that would be.


IMO this is a symptom of a larger problem with the entire web 'ecosystem' (HTML, CSS, JS primarily). It all tries (or tried, anyway) to be simple and easy and forgiving - which means that simple things are easy, and moderately complex things are insanely difficult.

I honestly think the only real solution is re-doing all of it 'from scratch', to make everything (a) stricter and (b) more normal/consistent.

(I think the extant transpilers/preprocessors tend to try to be too 'thin' of a wrapper around CSS/JS: they do give some nice quality of life features but still don't really clean up the mess that is JS and the DOM.)


It actually it is (mostly) as easy as it can be if you think about how the web lets one run third part code safely, not only as a sandboxed in the host environment but also from different domains. I've seen this space evolve since the days of DHTML and the best way to create dynamic content is with document.createElement. Actually I use the crelt[1] util, and the code is shorter and faster then any React/Vue virtual-dom templating system. It like finally riding a bicycle a without training wheels after 15 years of practice.

[1] https://github.com/marijnh/crelt


If you push down the front of the learning curve, the back gets steeper.


That depends on how much of the front of the current learning curve is composed of things people will need to know later.

A person can be a successful programmer for decades and do millions of HTTP operations without knowing the distinction between TCP and IP.


I've been learning Vue this year (I'm new to anything JavaScript so that means I also had to learn JavaScript, Node, NPM, We pack, etc.). I'm getting a lot better, but it has been a pretty frustrating experience. There are so many different layers and they are constantly changing what they do and don't use in another layer.

I've been working in Python for the last several years. There's definitely a learning curve there, and I get frustrated with things all the time, but the whole JavaScript ecosystem seems like such a mess compared to Python.

One of the things I miss the most about Python when working in JavaScript is the documentation. And I mean the core documentation from Python.org. The Tutorial is amazing [0]. And you can download the entire documentation already in PDF. Maybe I'm one of the few, but when I'm learning something new it is such a better process if I can leave my computer and read through a tutorial and mark it up.

[0] https://docs.python.org/3/tutorial/index.html


When I learned Vue, I just inclued the library with a script tag, and started writing plain JavaScript around it.

That was about 3 years ago, and I just started using modules. Even then, I use the native browser modules, no Webpack. With HTTP2, there is little cost to requesting many small files.

Likewise, I don't use a CSS preprocessor in any of my projects. They aren't that complicated.

Those projects have no build process. What you write is what you run (WYWIWYR?). If the project is small enough I'll serve its root directory with Python's SimpleHttpServer. Later, I might have nginx do it.

This allows me to get a project running in a minute. I add tools when they are needed, because then I have the motivation to learn them and set them up properly.

Such tools are required if you must coordinate the work of multiple developers. Their cost is divided by the number of devs, and their benefits multiplied.

If you're just a home gamer toying around, you can do without them.


if you are learning vue and new to javascript ecosystem, would it not be better to start with index.html using Vue from a CDN, and switch to advanced workflow (node, npm, webapack, etc) later?

of course, if you are new, then this approach may not be obvious


I completely agree!

I started using Vue from a script tag a year ago (not that hard). But when I started building an SPA, things got complicated very quickly.

I found myself longing for a really good tutorial similar to Django's [0], rather than the thousand variations of "Today We'll Build a To-Do App in Vue!" that are so common.

For the projects that I work on, I use the same pip/virtualenv setup that I've used for years. Can't imagine that happening with Webpack (Side note: it might be that I could use the same Webpack setup for years, but the unstable reputation around the JS ecosystem makes me think I couldn't).

[0] https://docs.djangoproject.com/en/3.0/intro/tutorial01/


That's an unfair comparison.

Javascript runs directly on the browser. That automatically makes it much more complex because:

1. There are some packages written for browser and some for Node.

2. There are transpilers, abstractions layers, bundlers, etc to make packages run on both environments.

3. Browser based packages need to have all sort of backward incompatibilities in mind (from IE6 to now)

Multiply these 2 and 3 together and you'll see why it's a mess of an ecosystem...

Yet, it only takes a little bit of knowledge and experience to get something working. It's hugely productive.

I mean honestly considering the hand dealt with it (decades of backward incompatibility required), I think the js ecosystem is holding up real well.


I haven't done the tutorial specifically but https://developer.mozilla.org/en-US/docs/Web/JavaScript is very good these days.


"Really what I take away from this post is that the author is a bad teacher"

No she isn't.

This entire thread is full of the generic excuses one has come to expect from this profession when people struggle with programming setup and running programs. Always a defence of the (broken) status quo.

Something has gone wrong? You didn't read the documentation (the incomplete or non-existing documentation). Or it's actually simple, all you need to do is x, y, z followed by a, b, c - how could you not know that? (Often implied in these responses: you're clearly a clueless noob).

This is quite simply a profession that wouldn't recognise 'simple' if it came and bit it on the arse (or ass).


Javascript is the ONLY language where people think they can just pick it up and use it with ZERO education first. Sure, they spent years learning to program in language X or Y, but even a couple days to learn Javascript is just too much effort.

If you think learning NPM is hard, try telling a new dev how to setup a Java or C# build by hand. If you think webpack is hard, try teaching someone the intricacies of make.

What about babel? Other languages make breaking changes and dictate that the new version of code just won't be compatible with older stuff. Python 2/3 wouldn't be a blip on the radar if the same option to transpile between versions existed. Those famous "update your .Net version to whatever" warnings simply wouldn't be needed. Instead, people complain that learning a few lines of config is too difficult.

If people put half the time into learning JS that they put into learning the other languages and build tools they know, there would be almost no complaints because the tooling these days just isn't that bad.


> Javascript is the ONLY language where people think they can just pick it up and use it with ZERO education first. Sure, they spent years learning to program in language X or Y, but even a couple days to learn Javascript is just too much effort.

The problem is not one of putting the effort in, it's even knowing where to go.

If I want to learn about how to use some new JS library/utility/webpacker, I can probably find about 30 good-quality-looking blogs/articles/documentation pages on how to do it. Most of them won't work, because they'll be out of date. This is hugely frustrating, because you don't know if it's not working because the documentation is wrong, or because you're holding it wrong.

> If you think learning NPM is hard, try telling a new dev how to setup a Java or C# build by hand. If you think webpack is hard, try teaching someone the intricacies of make.

Make is actually a brilliant example of something that's complex and daunting, but ultimately rewarding. It's easy to put the effort in to learn it because the maintainers don't change their minds every 2 minutes about what the Makefile syntax is, so learning how to use it is pretty straightforward. And once you know it, you can understand makefiles written both yesterday and decades ago.

Give me make over webpack any day of the week. I'll put money on which dies first.


How did you come to the conclusion that the author is a bad teacher?

Sometimes I am in the same boat. Thinking, this should be easy, ending up yak shaving.


And so I use create-react-app anytime I need to start a front-end JS/TS project, even if I am not using React at all. Basically avoiding dealing with troubleshooting the soup of build time dependencies and mismatching package versions, which unfortunately comes with the modern JS (or node) ecosystem.


Using Parcel.js (https://parceljs.org/getting_started.html) or Snowpack (https://www.snowpack.dev/) would give you the same benefit without pulling in the React things that you're not using.


I was going to use Django for a project, but ended up not doing so, as I was literally not able to set up my Python project correctly.

For all Python's ease of use language wise it‘s ecosystem can be utterly inscrutable.


Yeah, I almost gave up. I'm glad I didn't though, because, occasional hiccups with pipenv aside, Django is great to work with.


Coming from a language that didn't need virtualenvwrapper, I can't say I was a fan of needing to learn how to use virtualenvwrapper.


I’ve been using django since v1 and never, ever used virtualenvwrapper.

Python3 -m venv env. That’s all it takes.


A lot of people make the mistake of including the point release in that command. It's not necessary, specifying Python3 will do it.


That's what I do too. Never understood why I should use something else.


Yeah I used it fairly late and installed everything globally. It was a mess but stuff still worked.


> the author is a bad teacher

She wasn’t helping one of her students, she was helping a friend who is a computer scientist. The closing thought was if this person, with so much existing knowledge and some assistance, can’t make one “simple” thing work in a reasonable timeframe, what hope do actual novices have?


Novices don't need any of this - Babel and webpack are for pros who need to support IE9. I have in my team 19 year old who knows all this stuff to implementation detail, so it's not that hard to learn - speaks more about this friend.

Novices should be referred to preset codesandbox.


The article didn't mention Babel or Webpack, the first attempts to use the module were with Node, not in a browser.

There's blame to go around but I mostly blame npm for being full of hot garbage while obscuring what is garbage and hot.


I’m pretty sure the author isn’t teaching anything but is instead pointing out the unfortunately common pitfalls when having someone new start with the JS ecosystem.


"Quickly" using the JavaScript tooling is somewhat akin to watching one or two episodes of the 6th Game of Thrones season without watching anything else. You really need to watch season 1-5 to understand what's going on.

The other day I wanted to publish a little script I've been maintaining for years as a module easily usable by WebPack and whatnot, and that's much easier said than done. I published it on npm and put some UMD magic thing in there, and I think it should work now ... but I'm not really sure to be honest (still need to look at this and confirm).

Just searching "publish JavaScript module" and trying to make sense of the WebPack isn't really all that helpful, not for me anyway, as I'm joining half-way through season 6.

I have no opinion on the tooling as such – I lack experience to have an informed opinion – but it sure is confusing to "quickly" do something for people who are not heavily involved in it (i.e. me)


> "Quickly" using the JavaScript tooling is somewhat akin to watching one or two episodes of the 6th Game of Thrones season without watching anything else. You really need to watch season 1-5 to understand what's going on.

I disagree. In both cases, you really only need one or two episodes to know that the story is not going anywhere. It will only get more complicated and convoluted without ever rewarding you, you will realize that no thought was ever put into it, and you will only stay for the ride because of sunk costs.


That's nice and all. Unfortunately, (to stay in the metaphor) the PM has arranged to quiz you on the main plot points of season 6 three days from now, so your best option is to find a good plot summary for seasons 1-5 on Youtube somewhere.


As time goes on the breath of questions increases so necessarily the depth must decrease, due to all the history of the language (JS, C# or whatever). You are not a code now you are an archaeologist. It was so much easier in the year 2000!


> The other day I ... put some UMD magic thing in there

Whoa. That's a name I haven't heard in a long time.


I was under the impression this was still the best way to do it for maximum compatibility ... but perhaps that character got killed in season 3 and I missed it


UMD was a way to do AMD (which died years ago), CommonJS or script tags (also dead for modules).

These days you'd just add the right bit to commonJS to say this is an ES6 module.


>UMD magic thing

I use rollup for libraries and webpack only for fullblown frontend projects for precisely this reason.


I don't use it at all, but others do and I think my little library is neat enough for others to benefit. Unfortunately, I can't get any of thus UMD stuff to work, so for the time being I just "window.imgzoom = function(..) { .. }" it shrug.


> just run it in the browser

Yikes. I really do not think that was the solution to this problem and only added a ton of complexity.

JS is in a unique position because it can run both code in a browser as well as a server-side/scripting language. In order to do that with any level of success, tooling is required. This tooling (dev server, webpack) builds on other tooling (node, babel, typescript) which is where all this complexity lives.

Furthermore, some packages are not worth installing and if you run into issues with that package, then try something else. We have no information about the package they tried to install and since the JS ecosystem encourages people to publish to npm for virtually anything, this is one area where you really have to be careful.

The lesson here is the same lesson with installing something like left-pad: be careful what you install and read the source code to understand what it is doing. Most of the time, these packages can be inlined easily. Just because a library exists, doesn't mean you should use it. Most of the time for JS I'm reading the library's source code to see if I can a) inline it or b) use it as inspiration to build specifically what I need.


> JS is in a unique position because it can run both code in a browser as well as a server-side/scripting language. In order to do that with any level of success, tooling is required.

Mind that this was not that much of a problem back in 1997 with Netscape Navigator and Netscape Enterprise Server. I think, the real issue here is that the JS ecosystem is targeting an abstract implementation, rather than a real world one. Much of the tooling is just about turning the abstract implementation into a real world standard and, in a second step, about packaging (i.e. linking).


> Much of the tooling is just about turning the abstract implementation into a real world standard and, in a second step, about packaging (i.e. linking).

So long as you have browsers in various states of compliance and paying customers using those browsers, this will always be a problem.


The challenge of JS is and has always been finding a productive corner of all the possibilities of what you can do with it, and optimizing within that corner.

Usually that means picking up a subset of well supported frameworks that you like and find works well in the domain you’re in. It also means learning what language features not to use, or at least abstract away their use. People coming from highly opinionated languages with a large standard library tend to shoot themselves in the foot because they don’t understand this, and nobody really tells them. And inevitably a discussion turns into an argument with different sides becoming Balkanized because they use different parts of the possible language/library set.


> be careful what you install and read the source code to understand what it is doing.

That’s the reason why I started to love pika.dev ‘s package search. Webpack still sucks and will ruin your day with hours of unnecessary configurations and fixes.

On the other hand, when setting yourself a rule to use plain ESM only without any build system, coding has been a joy.

The only thing that still sucks is UI frameworks, because all major frameworks still require a shitty babel workflow in one form or the other. Vue.js has an ESM module which is useless without babel (due to the .vue file format), and Angular/React are still in the lets-invent-our-own-language fatigue.


Lately I've been developing with a JS workflow that's finally made me think "hey this is fun!" again:

Chrome target, native ESM modules, VS Code with JSDoc annotations for types. All libraries (chosen preferentially from microjs.com) are copied into vendor/, and the front end is written in preact.js using htm [0] for native JS tagged html strings, leading to code like:

  import ImageView from "./image-view.js";
  render({ trail_item, selector }, state) {
    /** @type {LinkItem} */
    let link_item = trail_item;

    let title = this.render_title(trail_item);

    let favicon = this.render_favicon(trail_item);

    let img = html`<ImageView src=${favicon} />`;

    return html`${img}${title}`;
  }
There's a VS Code extension which formats html`` strings as actual HTML, and the Typescript checker built in to VS Code gives me advanced types and autocomplete, all with a workflow that's as simple as "refresh page".

Granted, not every project can afford to target just evergreen browsers, but for my use case it works perfectly and I finally feel like I have the perfect blend of old-style web dev (in terms of refresh cycle) with modern language features and typing. The overhead, both in page-weight and cognitive load, is as small as I can make it.

EDIT: Modified my code sample to show how you can use Preact components in a JSX-like way.

[0] https://preactjs.com/guide/v10/getting-started/#alternatives...


Yeah, the microjs approach is much nicer than the Node approach.

I think the mistake of modern JS (and many other languages) is conflating source files with libraries. A better model is combining many source files into one library file, which provides one toplevel name when imported. A good example is how Three.js, which has a complex internal structure, gets distributed as one file and provides one toplevel name THREE. And of course there are many examples in C-land, where a large library can live behind a single header file. A project should only depend on a handful of those, and there should be few dependencies between them, so package management becomes easy enough to do by hand - just drop a file in your project's vendor/ directory.

As a bonus, this fixes the problem of having many fine-grained imports. If done right, your project's source files might not need any import statements at all. Anything inside the project could be available without ceremony, as if it was all one big file, and external libraries live in a handful of big namespaces which are also available without ceremony.


I don't know enough about Three.js to say if that works well for them or not, it probably does, but I don't think a future where all libraries would do this would be very bright. If the library is big, you'd end up shipping a whole lot of unused code to the client, making the end user bored and angry while waiting the page to load (especially if they are the sort of person who hangs around in Hacker News). In fact, the direction has been the exact opposite in recent years! Look at how lodash has moved to exporting one function per one file so you can include just as much of the library as you need.


I was mostly talking about how things should look to the programmer. The compiler could still tree-shake the final version.


Sure, it's just that the person you were answering to--and this whole thread really--seem to be advocating for just importing module files without any sort of build step. Without a build step I also assumed tree shaking wouldn't be an option. Tools that handle tree shaking, like Webpack and Rollup, aren't really the simplest of JS tools anyway so if we are talking about simplicity of dev experience, I'd argue that multiple direct file imports--how inconvenient it may be--is still _simpler_ to get right than "single namespace import" + tree shaking.


> The only thing that still sucks is UI frameworks, because all major frameworks still require a shitty babel workflow in one form or the other. Vue.js has an ESM module which is useless without babel (due to the .vue file format), and Angular/React are still in the lets-invent-our-own-language fatigue.

The pain is real. Create-react-app will dump 250 MB+ of files in node_modules

however, newer approaches are emerging and (hopefully) will be stable soon. few noteworthy ones are:

1. SnowPack[0] (in early access) 2. Vite[1] (from author of Vue.js) . It is in experimental phase. but is quie good. 3. Unnamed project by Author of Preact.

[0] https://www.snowpack.dev/ [1] https://github.com/vitejs/vite [2] https://twitter.com/_developit/status/1264062182326710273


A lot of UI Frameworks need webpack, I had been looking at web components...

You can build Vue applications without bundler... file is JS extension, you use

const template =` <you html stuff here> `


React has no invented language. You’re thinking about jsx which isn’t needed. It is recommended, however.


> It is used everywhere, however.

Fixed that for you.

React without jsx components is just as useless as Vue without .vue files. If you cannot use the ecosystem of a framework in practice, your framework isn’t a framework anymore.


> React without jsx components is just as useless as Vue without .vue files.

It's not useless at all. JSX in React is just an alternate syntax for React.createElement calls.


Wrong, you can still use VueJS without the vue extension...

https://dev.to/arswaw/create-a-lightweight-componentized-spa...


Is it me or is the real problem that someone wrote a package and quickly wrote use “import ...“ instead of writing “const x = require(“...“

Node works fine out of the box from the command line, modules just need to have the correct instructions for the README.


That wouldn't have helped anyway. The file was written in TypeScript. Node would have barfed immediately.


Libraries with TS codebase almost always have a prebuilt bundle.


The module syntax inconsistency situation is atrocious but we're gradually making the transition. Now that we have a clear destination, I suspect it will be a non-issue in a few years. Projects like Deno and Pika are accelerating/papering-over the transition.

I've been working in JS for years and I've never encountered a module containing a typescript file with a .js extension... That was extraordinarily unfortunate. I don't think I've encountered a module containing Typescript at all. Correct practice is to build to JS and include the optional type declaration files. In my experience people are pretty good about that.


Now that I think about it, it was probably a Flow[1] file, they look a lot like TypeScript but have a .js extension.

[1] flow.org


Ah, yeah. Flow files do, unfortunately, stick with the .js extension by convention. However, it's still terrible practice to publish a node module that doesn't include a plain JS version of everything.


It was definitely flow. It was the first thing that came to my mind, because I've never seen anyone writing TS in .js files, but I've seen flow in just plain .js files - a lot.


I just don't use Javascript, for precisely this reason, ever. Nothing is worth the hassle - no fancy libs to do spacing, or anything.

This is not progress - as someone who has been professionally programming for 30+years, this state of affairs is atrocious. Its the equivalent of buying a 5-bedroom house for your kids to grow up in, only to go in to your kids room after 20 years and realise they are insane and should be committed.


You could have a similar experience with virtually any other language/platform. “Someone who doesn’t know anything about C had a lot of trouble running some arbitrary C code they downloaded” wouldn’t raise a single eyebrow.

Turns out your kids actually manage to use the tools they built just fine.


> You could have a similar experience with virtually any other language/platform.

I'm sorry but I don't believe the issue is as bad in other environments.

I've managed to pick up and make small patches/enhancements to projects written in Java, C, Ruby, Python - none of which I use regularly beyond the bare minimum I need (usually to patch some tool I'm relying on).

"Modern" javascript is just a huge pile of WTF with "Are you fucking crazy?" frosting to my eye.

> Turns out your kids actually manage to use the tools they built just fine.

The kids have a "new tool" every week because the "old tool" from last week has some problem. That's hardly a sign of "just fine".


It is quite easy to pick pick up and make small patches/enhancements to projects written in JavaScript with minimum knowledge. When you are at the point when you are patching tools you rely on, you already know a lot. It is also much easier when you are starting with properly set up existing project.

The situation in article is equivalent of trying to add maven dependency to raw java project without maven, because you dont know maven exists and then wonder why other dependencies are missing or project is not imported correctly to eclipse. That is literally John from article.


> When you are at the point when you are patching tools you rely on, you already know a lot.

I think you misunderstood. I am talking about making patches/enhancements to tools written in languages I do not regularly use. So I didn't "know a lot" about the language or environment or toolchain involved, I generally knew nothing (from a dev POV) about it. The small exceptions there would be a Java project (StanfordNLP) and a C project (the PHP language/runtime), where I had use the language in question to write 'hello world' type programs as a student, as part of my Network Engineering diploma, close to 20 years ago.

> The situation in article is equivalent of trying to add maven dependency to raw java project without maven, because you dont know maven exists and then wonder why other dependencies are missing or project is not imported correctly to eclipse.

The first command "John" runs in the article is: `npm install packageName --save`, as recommended by the package’s README.


> The first command "John" runs in the article is: `npm install packageName --save`, as recommended by the package’s README.

Likewise, java library would have "add this dependency" in its README followed by xml snippet. It would not start from "create maven project" nor explained how you get pom.xml. It is assumed you know what maven is.

> I am talking about making patches/enhancements to tools written in languages I do not regularly use. So I didn't "know a lot" about the language or environment or toolchain involved, I generally knew nothing (from a dev POV) about it. The small exceptions there would be a Java project (StanfordNLP) and a C project (the PHP language/runtime), where I had use the language in question to write 'hello world' type programs as a student, as part of my Network Engineering diploma, close to 20 years ago.

That is exactly what I am talking about. You do not need to know a lot. In java world, you need to know about maven existing and that maven dependency means you have to have maven project.

In JavaScript, you are expected to know that npm dependency means you have to have npm project.


The kids have a "new tool" every week because the "old tool" from last week has some problem. That's hardly a sign of "just fine".

The old tool(s) will actually still work just fine, and plenty of people use them. Kinda like Python 2 and Python 3. You're not forced to use the absolute newest set of packages. I'm not as familiar with Java and Ruby but the I know the C/C++ ecosystem has gone through many changes over the decades. Perhaps the situation with JS is currently overwhelming and maybe it will settle down over time, but I don't think it's a bad thing that lots of people are motivated to keep iterating and improving the tools. Personally I find the JS development experience very smooth and enjoyable, and I know many of the people building all these crazy new things do as well.


Can you give some examples?


Examples of the WTFs or examples of other projects I was able to work on with little experience?


The WTFs


The biggest WTF for me is you want to solve problem X. Great someone has written some code in a library to solve X. You want to understand it. Cool, let's look at the source. It uses source transpiler #2 of the big 4, bundler #1 of the big 5, ui library #33 of the big 50, and oh yeah it uses proxies to make everything return a promise so g'luck debugging that.


>left-pad

That is all.


Did you ever search has or is prefix on npm?

You are in for a treat.


Yeah, its just not something I believe I should be promoting, as a developer, as a solution to anything.

Its like .. Sure, meth might be fun, but I definitely don't think I wanna hang out when all the people in the room are doing it.


And yet, we didn't have these issues for the first 20 years that JS was around. It was only when all these things started being created around JS (babel, webpack, node, npm, typescript, etc.) that all the complexity and insanity was introduced. In what I still consider to be the good old days, any JS code would just be in an external JS file and you would just link to it. No transpiling needed. No build process needed. No module repository needed.


I used to work for a company that developed a JS widget people could stick on their site with ease (and not just little sites either, this was on microsoft.com, nfl.com, starbucks.com...)

As such I got to deal with getting our code to play nicely with the dozens of other scripts that inevitably existed on these sites as well. Being a third-party on a site with not just first-party code but also other random third-party code was truly a hostile environment.

Nobody was doing anything correctly like loading scripts in a way so that they'd never interfere. Some script would load the version of jQuery it wanted, which would shadow the version some other script wanted to use, and stuff would break (but only sometimes, because it depends on timing).

This was before anyone was using webpack. Bundlers thankfully solved this issue (unless you really go out of your way). I'm sorry to say what you consider the good old days were in fact quite bad. If you're making a personal website for yourself? Sure, all this seems like overkill. As soon as you introduce anything third-party? You need lots of tricks to be bulletproof. So from my perspective, things are much improved.


Its almost like Javascript begat a developer eco-system which then required further tooling and ancillary applications in order to keep it all in order.

What a pity this was done within the browser-as-OS context rather than OS-as-OS, as a thing... What you described is just like the good ol' days of DOS were: you could write some code, sometimes, that would work on everyones machine - but then of course there were special cases and developers had to take into consideration other members of the ecosystem - standards had to be proposed, formulated, and met - competing players needed to play nice together, and so on.

The trouble with Javascript today is that precisely NONE of the lessons learned in any of the other places where PRECISELY these issues were experienced, have been applied - even less, paid any attention. And, especially not, by any of the so-called 'new school' of developers who think such disasters as the left-pad fiasco are Just Fine™.

The cognitive load of Javascript today is equivalent to that of, lets say .. assembly on DOS in the 80's. "Anyone" can do it, and no doubt there will be great advances in applications for the user - but don't come screaming when the big ball of mess starts costing you more than if you'd just written it properly in the first place. That means, packaging and abstracting things properly. It means putting the modules in a place where the world will find them over time. It means having release planning procedures that work, and aren't in the hands of a mindless entity. This was how it was on DOS, and then Windows, and now the Web .. less so on Linux, because Linux has always had great solutions to the kinds of problems Javascript is now manifesting.

I blame the OS vendors, personally: Apple, Microsoft, et al. If they hadn't had such a hard-on for removing basic compilation capabilities from a default OS install, we wouldn't have all been corralled into the web, and thus relieved to 'finally' have a dev tool for the common man available to us, in Javascript.

The cognitive load is the same. The ecosystem is a disaster, however. I'd rather just be writing plain ol' Linux apps, producing binary-file based installers, personally .. the tipping point for the effort to invest in Web development is there. I just need users willing to run real operating systems, and who realise that the web isn't just about the browser. I feel that is a more worthy investment of the intellectual capital of developers, today.

Of course, none of this matters to the billion-dollar Javascript churn industry. The customers don't need to know how bad it is: as long as they feel they're getting the user base they need/deserve for having paid so much/little for a bit of Javascript hackery ...


C has much more of an excuse to be difficult & fragile. It's surgical. Web tech is designed to be abstract. If your abstraction introduces too much fragility or complexity or cost or overhead then it isn't worth it. Abstraction is a tax, it has a cost. Save the disrespect, in my experience greybeards understand that a lot better than we do.


Nope, I was able to lear C with 18 years, make cross-compilation from a PC to Dreamcast and some basic OpenGL stuff with 20 years (dial-up internet days, no youtube tutorials/platforms).

I was able to pickup PHP-Mysql with 22 years or so, and move from that to Python/Django, even some Ruby in-between.

Javascript? I just can't wrap my head around it. And I've tried.


The rapid pace of change present in the javascript ecosystem (and related developments like Typescript, coffeescript, etc) definitely make it hard to grasp. What might have been relevant years ago may no longer be relevant.

If its hard for people who already have a background in programming and some basic computer knowledge to learn and pick up, I can't imagine how hard it would be for someone with no experience.

The moment you go beyond making a simple website like you might learn in a beginner javascript class (using just basic javascript embedded in an HTML document) you become pretty lost


Ermm, no.

C has its problems, and in many ways has avoided this hell hole by solving them in clever ways, but they are nowhere near equivalent to the burning trash pile that is the modern Javascript developers stack and tooling.

If all you've ever done is become a professional Javascript developer, I'm sorry: you still have a long way to go before you'll match the style, elegance and productivity of basically any other language. Javascript dev is an atrocious mess, and anyone who has done anything productive in any other language or framework should know that by now.


It could be worse. I could be any other language / dev env. Trying getting a C or C++ open GL app to compile. the first hits are often 20+ years old NeHe tutorials. Every few years the libraries change, the dev environments change, and unless you're already an expert in them you have no idea what you need to change in the project to get them working again.

I've run into this issue in every language. Nothing special about Javascript here.


20 years later, I can still write an SDL app using just the SDL repo and my C compiler, with GL features and all the other bells and whistles that made me choose SDL in the first place. Its there, it builds, it runs.

There isn't a single Javascript project I've done in the last 10 years that I can return to and run again - they've all been borked by the eco-system. I dread the idea of even opening a package.json file to see what's wrong...


Couple of weeks ago had a customer cross compile a project written in C. That was last compiled 8 years ago. Compiled perfectly with gcc 9.2


Try targeting Windows Script Host (i.e. cscript.exe) for your next project - it's still there and mostly unchanged since Windows 98. :)

The language supported is ECMAScript 3 with some minor COM-related quirks, but with a few utility functions it's not too bad for simple scripts.


>I've run into this issue in every language

What about C#? One could argue it's pretty much the most bullet proof in terms of "just working" without any issues.

Open up visual studio.. start a project.. run it. There really isn't anything to break like everything else you are discussing.


> Its the equivalent of buying a 5-bedroom house for your kids to grow up in, only to go in to your kids room after 20 years and realise they are insane and should be committed.

Yeah, if you lock your children up for 20 years, they will go insane no matter your intentions.

Javascript is in this state for a number of reasons, but the fact of the matter is that it's here now and it's the lingua franca of browsers whether you like it or not. Maybe someone should have checked in on the kids every once in awhile so they didn't go insane, but it's too late to make more kids so love the ones you've got.


Javascript devs ARE locked up in a shit-stained room covered in trash and detritus from previous occupants, and what's worse: they seem to crave that condition.

The only justification for the disaster of modern JS 'development' is: job security. Make this argument and all I can do is agree with you: its a hellacious mess because otherwise, it wouldn't be so profitable.


> The only justification for the disaster of modern JS 'development' is: job security.

You could also explain it by a succession of well-intentioned-but-ultimately-unsuccessful attempts to reign in the insanity. At least for things like TypeScript and CoffeeScript.

Combined with a culture of high speed delivery of business value, which doesn't value going back and removing the earlier failed attempts.


As a computer scientist who learned JavaScript this year, I strongly agree with the sentiment here. I feel like I often spend more time debugging module errors than my actual project.

Granted, once I understood the ecosystem more, I gradually began to grasp the reason these issues are around. But still, it does make it incredibly frustrating as a reasonably decent coder getting started in JavaScript.


As a programmer who has been using JS heavily since the late 90s and now doing mostly React and Node.js, I would say that finding the right modules and patterns to use has always been a big part of the job. It takes a lot of searching, experimenting, learning, judging code quality and reading the tea leaves on package stability and popularity.

Things have largely gotten much, much better for JavaScript though ever since Node and NPM came along. It's easier to find the right modules to use or at least the right ideas to borrow. Package overload paralysis still happens at times, but I'd personally always rather have more, rather than less choice.

The constant rate of change does make me feel like I'm always re-learning a new way to do the same old job, but luckily for me - learning potentially better ways of doing the same old thing continues to be enjoyable.


Like many others, I'm chiming in with a me-too... IMO the biggest problem is that if you come back to JS after a hiatus, it's very likely that most of what you thought you knew would probably have changed in the interim.

I mostly work on the backend.. However, I've done a decent amount of JS too. In fact, back in 2015, even built a lot of the core parts of an SPA using a mix of knockout & requirejs with minified bundles and dynamic loading and so on. Given that it stuff put together from scratch, I though picking things up after a couple of years away from js would be easy. Oh how wrong I was...

In 2017/18 sought to write a starter boilerplate with vue 2, Typescript and .NET Core. I would have probably spent an order of magnitude effort more fixing build issues and warnings than on the project. Once you hit bugs/issues with 3rd party webpack modules (which is almost a given), it is not fun at all.

I recently had to put up a one page visualization and was not looking forward to it. Surprisingly, create-react-app just worked out of the box. Not much of a data point - but still a pleasant experience.


> Surprisingly, create-react-app just worked out of the box.

create-react-app is the only thing I've used in the ecosystem that hasn't catastrophically broken for me due to some years-old issue.

Except for monorepos/yarn workspaces, that still doesn't have first class support[0]

[0] https://github.com/facebook/create-react-app/issues/1333


Totally agree. react starter is awesome, never need to look back how to do that require import again :)


The worst node module import issue I’ve encountered is with bootstrap react Navbar component. It runs fine locally but wouldn’t build in ci, and after an hour of troubleshooting it turns out that the B is capitalized (NavBar)... so WTF it works locally?...


Running on Windows machine vs Unix based tends to highlight issues regarding case sensitivity


It's become easier to build with hard-compiled languages than with interpretive ones. Interpretive ones shouldn't need "building", but they seem to acquire build systems anyway. Compile and link systems at least diagnose what's missing during the build process, not during execution.


I don't know why people do this. In more complex areas of programming the code and tooling are simpler. It seems like any ecosystem just fills up to the certain level of complexity regardless of the complexity of the original task at hand.


If web programmers had the choice to install an arbitrary language's runtime in users' browsers, they would. But users have disparate browsers with disparate JS implementations, so if you want to code in a sane language with consistent behavior, you'll need to transpile and polyfill it.

You can't just distribute arbitrary binaries to users on the web, so web developers have to deal with a layer of complexity that other programs don't have to. That said, maybe WebAssembly will change this story.


> web developers have to deal with a layer of complexity that other programs don't have to

yep, other programs totally don't need to deal with different OS, graphics APIs, GPU driverstacks and hardware architectures.


Those are all runtime concerns. They don't affect the literal syntax that you write, as is the case with JavaScript. You can't feature-detect syntax. Instead your entire program will just fail to parse.


So like shaders?


Since you mentioned complexity, past a certain level of application complexity, you realistically can't do a linear list of Javascript files that you import on the page in order. When you have hundreds of views, you don't want to manually go and figure out what each of them needs as prerequisites. Circular dependencies are annoying when you do it by hand but practically trivial with a packer as long as they're logically sound. Inversion of Control. On-demand loading. These are all problems that have been previously solved by hand, but when you don't want to solve these prerequisite problems before your actual business (or hacking) problems, you build tools to do it for you.


"Can't do a linear list of Javascript files that you import on the page in order" - sounds like a problem that a BCPL developer has stumbled upon 50 years ago while writing his include directives.


Are there other languages that suffer from this? I think Python, Erlang, Ruby at least seem to have escaped the fate so far.

The upside of the JS transformation into just another compiler target is that there is little reason to use JS as the source language, IMO. These JSVM languages do suffer from the same problems to varying degrees.


A major difference is that JS developers have little control over the runtime of their users, while all these other languages and especially compiled languages do. JS is a special case because it's the sole supported language of browsers, which all implement it differently—that comes with a unique layer of complexity.


Python has "eggs" and "wheels" and many headaches involving them.


They most of the time work though. Except for a python environment + python version, not much is required to work with it.

There is no package.json, typescript, flow, javascript mix, with tens of things configured which change frequently.

Also continuing to work on a python project after a year often is not much of a hassle.

That being said: virtualenvs still seem to be complex matter, especially when you are a beginner.


I totally agree with the author here, but also would love to give some context since we have lived something like this before on Javascript IMHO:

Callback hell around 2015. It used to be that if you wanted to do something async you'd have to create a new callback. This led into callback hell[1], which was specially bad back then on the backend.

Luckily after a migration that has taken many years, now most of the libraries use async/await instead of callbacks. There was some time where this was extra difficult because some code was using callbacks and some other code was using async/await, but it's almost totally solved in 2020.

Which brings us to the article on hand. This is probably one of the biggest issues, and a fake promise in Javascript right now: reuse code on the back-end and front-end. The front-end side has been using `import` for almost a decade with Webpack and friends but this was not easy on the back-end, so there was not a practical way of reusing the code in a project.

Luckily since last year Node.js supports import/export, and React supports it in libraries. It took a while because it was not an easy issue. I expect that more and more libraries will start to work only with import/export, and hopefully in 1-5 years this will also be a non-issue.

[3] http://callbackhell.com/


> Luckily after a migration that has taken many years, now most of the libraries use async/await instead of callbacks.

Is that true? I was looking to port one of my C# projects to TypeScript/Node and it uses gRPC and it's not async/await compatible. That's a pretty major library in my opinion.

In the end I didn't end up porting my project because the lack of elegance compared to the C# version was too depressing -- the C# code made heavy use of async and porting without that was just too messy. I'll take another shot at the project once this problem is totally solved.


Well, it's true for libraries that were using Node-style callbacks ('nodebacks') which had an upgrade path to promises[1] and from there to async/await. If some library was doing a completely different style of async, then unfortunately it won't get that easy migration path but it can probably still use the Promise constructor[2] to wrap the async operation in a promise.

[1] https://nodejs.org/dist/latest-v8.x/docs/api/util.html#util_...

[2] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...


I don't know which library you were looking at, but if it wasn't https://github.com/protobufjs/protobuf.js, it probably should be. That one uses promises, so is async/await compatible (JS async/await is just sugar over promises) and I've seen it work well enough in production use to have no reservations in recommending it.


I googled "grpc typescript" and worked through the first few pages of links. That particular library never came up. I'll take a look.


Yes, I said most and not all, there are still some older libraries that haven't been updated. These are fairly rare, and you can still util.promisify, but sure it's definitely not ideal.

Please note that not all callbacks can (or should!) be converted to promises, e.g. events like `on('click', ...)` don't have a clear way to be promisified since a promise can only be resolved once and stays resolved.


observables come handy in such cases


You can usually promisify the functions that take a callback via util.promisify (although I've done it manually myself as well).


actually not the gRPC functions, since they have options argument with `onEnd` key with callback. So you need to promisify those manually.


If you don't want async/callbacks you are using the wrong framework. Serial code is much easier to deal with. And async/await just hides the complexity under the rug, hoping you'll never get backpressure and other issues. Callbacks take a while to grok, it took me about a year to learn how to juggle all the async calls in my head, which a multi threaded language will do for you. Both have their pro et contra though, with multi-threading you'll be dealing with locks.


What experience DOES john have? I've had far worse experiences with ruby, python, scheme, clojure, java and C.

If you want a language that requires zero learning to use, I am sad to say that they are very far and few between. Sure, we have a clusterf*ck of a module ecosystem and interoperability issues between preprocessors but it isn't like that is a particularly novel problem either.


I think JS gets shit on the most because its both the largest, most popular, visible and relatable. Imagine trying this same exercise with a C++ library you found

>The cmake build is doesn't work without -GNinja (you do have ninja installed, right?)

>No actually use Bazel/Buck/Pants/Meson

>Oh you installed $DEP, but not the right $DEP with $DEP-X support

>pkg-config can't find $DEP-X

>Pre-build $DEP-X was built with GCC N, and you have GCC N-1, try building from source

>GOTO 1 for DEP-X

I'm embellishing here, but I feel like I always do some version of this song and dance when trying to build a C++ project. And then after all that is done you somehow still end up with linker errors in your final project.


I think one difference is that this is usually abstracted to quite some degree. Most devs rarely (if ever) have to deal with C/C++ build systems, as package managers and whatnot deal with that.

For most people installing some C/C++ library it's just "apt-get install libfoo" (and maybe libfoo-dev), and they never have to deal with ninja/autotools/cmake/etc, whereas for JavaScript you directly have to deal with the tooling by using "npm install libfoo".

The same task mentioned in the article would probably be a lot easier: install package, write some code, "c++ -lfoo main.cpp".


This is fair, but, the original article mentioned installing a random module on github. A C/C++ library large enough to have distro maintainers, is more akin to a large JS library that has UMD scripts hosted by Cloudflare. In that case, a developer could just do '<script src="https://cdnjs.com/lib.js">' in a html page.

I'm not saying JS is perfect, or that other languages don't have these issues. I haven't used Rails in years but I remember spending a day trying to get a gem installed and figuring out why nokogiri wouldn't compile. Almost every language has these problems.


Most of the C++ is curated by the package maintainers. That's the key: do not let upstream programmers do it (they adore their unique build systems and other stuff like that).

That's how you get quality user experience. It creates balance between developer of the library/tool and the user of the library/tool.


In my last C++ project (it's been a while) we ended up including many of our dependencies in source as we required different versions, different build options or small modifications compared to the packaged version.

Most of the time we would create a minimal CMake file to build the library to our specs or adapt the existing CMake file.


Now I want to see John try to build a client on another stack, like deciding between Carthage vs CocoaPods vs etc. for his iOS hello-world and running into the problems with that.

Or, hell, how about the packaging systems in Go or Python? "Yeahhh, we don't really use X anymore, go ahead and use Y."

John certainly failed the perseverance test though.


It's true that basically every language (except Rust?) has nightmarish package/environment management/tooling ecosystem problems. Why is this, anyway? It's a little nuts that it's easier to learn how to code than it is to figure out how to install a module.


Right now you can click File > Swift Packages > Add Package Dependency and let SPM handle it for you without thinking. I know not every package supports SPM yet but it's clearly the path forward and something everyones working towards. I think the other point I've found doing both web and iOS is you don't need any dependencies to get started on iOS, a hello world app is as straightforward as opening XCode, creating a new project and plugging in your phone.


I don't know. I think both of the examples you provided really require less perseverance and are more of an analysis paralyis issue.

In John's case, even after he got some help he still couldn't set up and run the project which is really frustating.


JS gets shit on a lot, but I think npm install with a package.json is kind of one of the easier setups.


Eh, yes and no- that only gets you started if someone else already picked modules for you. Snowpack and such make modern ES modules with npm bearable, but the sheer volume of modules that rely on webpack's preprocessing bastardization of the module system is really depressing. I really wish they had used comment directives or something other than the import statement for things like attaching CSS files to builds.


> Snowpack

oh look, another one


shrug it basically just copies files out of node_modules to another folder for sane browser use of module imports (no concatenation or build process). Basically, for people who liked bower but are stuck with npm.

I've used it for some personal projects, but doubt that I'll use it for anything paid anytime soon.


Well, since you mentioned ruby, I've never had - not even once! - to wipe out my gems folder in 10 years I'm coding with it. I think most ruby developers never had too.

With javascript? Well, for instance, take Expo's official release notes for each new SDK and it's right there, as the recommended practice: wipe out your `node_modules` folder and run `yarn` again every time. And good luck not having your `yarn.lock` file randomly changing versions after a while.

It's just a single silly example, but it tells how much more stable the ruby development experience is.


dude what dealing with ruby gems is like 50% of iamdevloper's schtick.


The node environment and the browser environment is a pretty unique aspect to JavaScript. It adds some complexity for novices. An hour spent trying is a bit on the light side though.


This is one reason I'm so excited about Deno. It's basically like browser, but for (ESM) modules. Solves so many of node's problems.


the python experience especially is so painful...


there is always the other python binary hidden somewhere in the depths of the filesystem...


I'm a dedicated Javascript hater, but I don't think this is a Javascript problem. This seems to be how people (not me) have decided all software should be organized now.

I don't get it. I really don't.


My thoughts are its to make something boring and uninteresting into something complex and special - the process of complification I like to call it. Maybe its to charge more to, like the old lawyers charge by the word scam.


It's the result of code reuse and modularity taken to the extreme.


I have hit a few of these myself and I have also hit similar needlessly complicated issues in a bunch of languages. This particular instance also suffers from the seam between Modern ES modules and legacy JS, which could be better.

Learning a language involves learning a bunch of non-language arcana about the environment, for no particular reason. Ideally you should be able to write the helloWorld equivalent for any platform and have a single command to turn that one file into a working program, but alas we have tool chains, configurations and requirements standing in our way. I don't think it has to be like that, but it all too frequently is. Deno seems to be making an admirable effort towards making a thing that just works.

Developing for Android or iOS makes the JavaScript experience positively direct.


I had very similar experiences with Rust and C++ lately.

In Rust, all I wanted is to play an audio file... failed.

In C++ all I wanted is to play an MP3 file... failed. With an hours of work I figured out how resources worked in Visual Studio and got a WAV file playing.

In Rust I installed a creative coding crate, it had 314 dependencies and the deps folder was 540MB. My openframeworks C++ project is 1.6GB after a bit of playing around in it :) But yeah, node_modules is heavy.

Bottom line is, when you are new to an environment and you aren't prepared to fight a battle, you will bleed out quite fast.


Python...

   subprocess.Popen(['cvlc','--play-and-exit','{filename_here}'])
(just being cheeky)


> But why do I… ok fine, I’m going to start a localhost.

Is "start a localhost" a generic term? If someone told me to do that, I would probably freeze in embarrassment -- no one has ever told me to do that in such context-independent terms. Since this was about node/JS, did John install express, or some other static file serving module? Or did he have an unrelated tool that makes this trivial?


It's kind of a weird phrase. Would normally "start a server". But yes, generally speaking, it's a one liner to expose $PWD:

python3 -m http.server


Which listens on localhost by default.


here's how trivial it can be:

https://gist.github.com/willurd/5720255 ("Big list of http static server one-liners")


Yup, I've never heard of that particular idiom used to describe the action of spinning up a local server, and it's not really something trivial as to not require some external tooling. So I don't know what's up with that.


Looks to me like a regular workflow and typical gotchas... ability to resolve this and similar is what pays the salary. Is Android, QT, Django, or Java development any more straightforward?

Anegdotally my perception is that people oftentimes think "It's just stupid JavaScript, let me paste it into HTML and run in a web browser, oh wait... why it doesn't work?!".

If you think it's confusing then add Angular to this tiny app (it's from Google so it must be good, right?).


If you think it's confusing then add Angular to this tiny app

Ironically had they run ng new followed by npm install the import instructions would have worked out of the box.

In today’s javascript landscape you have to pick the template to start your project from, because starting from scratch is way more difficult.


So basically the entire series of issues can be rooted to the fact they're trying to run TypeScript code in Node/a browser. This doesn't seem like an issue with "today's JavaScript" but rather a symptom of either not reading the docs or the module not having good docs. I wouldn't be able to compile Java code with a C++ compiler.

Also that the package is published to Node Package Manager with only a TypeScript distribution seems very odd.

I do agree that the Node ecosystem could be easier to use, especially with the myriad of transpilers and build tools. But this doesn't seem like a very compelling anecdote to demonstrate it. Unless the point is that NPM package authors should not be able to publish their package in languages other than Node-flavored JS?


One of the problems with the js community is the idea that it is a good idea to name just about anything that is js-ish in a file with a .js extension. I love Dan Abramov, but I think a large part of the blame for this can be placed on his feet for encouraging the use of js extensions for jsx. This sent a lot of people down a dark path. File extensions serve a purpose. Even more so if you don’t have a standardized header line disambiguating the contents of the file. When you rely on tribal knowledge and sophisticated build tools that rely on strange assumptions or the requirement to parse whole files with different syntaxes just to know what you are looking at you have a problem.

If the c++ community had a tendency to name their java files with cpp, would you be so forgiving?


To be honest, I don't run into much JS code that doesn't have proper extensions, but that's just been my experience for the past 6 or whatever years I've been using Node.js. If I use JSX, I use .jsx as an extension. Likewise for TS and TSX. And CoffeeScript in years past. I can't recall coming across any NPM packages that couldn't run in Node. So I can't really relate. Maybe it's confusing that there's different flavors of JS though with the same file extension: browser-flavored JS and Node-flavored JS.


I wish I could say the same, but nearly half of the teams I've worked with on web development go exclusively with .js because it's been pushed by prominent members of the React community for "ergonomics"[0] (which here is just a fancy way of saying devs can't be bothered to invest the two seconds it takes to make file extensions accurate when switching to a superset language) The trend of unreliable file extensions has lots of other nasty side effects on IDEs, build tools, and browsers (e.g. [1])

[0] https://github.com/airbnb/javascript/pull/985#issuecomment-2...

[1] https://bugs.chromium.org/p/chromium/issues/detail?id=659515


I worked in Facebook briefly, and the reason why Dan (who also is/was at Facebook) might be suggesting this is because this is the practice at Facebook: all "JS" files use the same build system and file extension. Which is to say, there's no JS, or TS, or even CommonJS APIs. It's all and always Facebook-flavored Flow (with the occasional caveat).

And perhaps this is why it didn't seem obvious for Dan (I'm speculating) that anyone would want to use multiple file extensions for things, but when you're outside of Facebook's ecosystem and you have to set up your own build tools and deal with all the pain it comes with, you realize stuff like this makes no sense. Because ya know, maybe targeting by file extension in your build system would make it easier to use the right transpiler (e.g. that's what Parcel does). But that's just been my perspective being in both worlds.


So, this doesn't seem to be an issue with JavaScript per se. The issue seems to be with the insane environment people have built up around JavaScript. Typescript, node.js, npm, etc. If the code really had been plain vanilla JavaScript that a person could use from an external JS file (just like we did for 20 years) then none of this would have happened.


My friend and I decided to start a project. This friend and I have had discussions where he espoused how libraries like Webpack, React, Redux, etc. just overcomplicate the web. I decided to humor him and do a "simple" stack of lit-html, vanilla JS and ES6 modules (since they landed in browsers). It took us maybe...a day to pedal that back? The first thing to go was doing ES6 imports in the browser. I forget the exact sequence of events but the MIME issue definitely showed up, along with maybe an untrusted source issue. Say what you will about Webpack, but native ES6 modules are definitely not here yet.


> a "simple" stack of lit-html, vanilla JS and ES6 modules

This is precisely how I’ve been building tableofsending.com and it’s been a lovely experience.

You do need some babel/tsc/etc build step to reach a reasonable audience.


Yeah I bet once you get the stack up and running, as well as smooth out the inevitable early adopter bugs of lit-html, you'll have a great experience. The subtext of this was my friend constantly telling me easy and simple it'd be versus React. When in fact each stack has its tradeoffs and incidental complexity.


lit-html has been used in production for over 2 years now, on sites with billions of page views a day. At this point no one new to it would be an early adopter :)

The issue with module loading is a pretty fundamental one, though pretty unrelated to web components.

Once you understand it, there are a large number of tools that make them work. The core problem is that most modules available on npm are written with import specifiers that assume the environment supports Node's module name result. Browsers don't, so it won't load something like `import * as redux from 'redux';`

The solution is a tool that transforms package names into URLs. Webpack, Rollup, Parcel, es-dev-server, Snowpack, Vite, unpkg.com, Polymer CLI, and many more do this for you.

More and more of the ecosystem is moving to native modules and we're all going to have to understand this issue.


ReasonReact has been used in production for 3 years now, with billions of page views a day. I'd still call it immature in many^[1] regards :D

The particular point of this project was to prove that each successive simplification that my friend proposed, i.e. avoiding Webpack for native ES6 modules, using lit-html instead of React, etc. introduced its own complexity. I'm not saying that these were all bad ideas, but just that they're fundamentally tradeoffs. I'm quite sure lit-html is a great stack. But it's not "better" than React any more than React is "better" than Angular.

[1]: Lack of async/await, or its equivalent, let+ in OCaml 4.08, is a big one. Mediocre typings for browser APIs is another.


Anybody who's an outsider is going to hit stumbling blocks. It's your choice to feign ignorance or pick yourself up. A lot of languages have their peculiarities and JavaScript is no exception. Would "Today's <Language X>, from an Outsider's Perspective" look any different? Where X is a language that's at least 20 years old.


> John gives up. Concludes never to touch Node, npm, or ES6 modules with a barge pole. > The End. > Note that John is a computer scientist that knows a fair bit about the Web: He had Node & npm installed, he knew what MIME types are, he could start a localhost when needed. What hope do actual novices have?

The ones who don't give up on the first night will likely have more luck (try, try again).


Or maybe John found it less aggravating to find or create another implementation in a different language?


Well if he followed internet trends he'd try Rust next, which doesn't exactly have the most straightforward package system either.


As someone with little experience in Rust, I can say that I have had no trouble downloading, compiling, and running binaries from a crate. The only hard part for me is organizing my own crate correctly.


Rust is definitely known for having a sharp learning curve, but I'm not sure what you mean about the package system. I've onboarded several people onto Rust at my job over the past year, and the package system has never been an issue for any of them.


Or, you know, Python, Ruby, Java, Go, C#, Swift, Kotlin, etc., etc., or any number of other languages that are less of a foot-gun full of bizarre issues, poorly maintained packages, and droves of Jr. devs eager to do clever things that make the language and ecosystem psychotic.


Python is good at many things, but packaging is not one of them. The best python package manager at the moment is Poetry, and it drew most of its inspiration from npm and yarn...

Python packaging has historically been so bad that dotcloud invented docker in an attempt to make it usable.


But at least I can just download a .py file (or a bunch of files) and just import them. Perhaps the biggest frustration/pain point in this article isn't npm as such, but that you can't "just" use some JS module.



> But at least I can just download a .py file (or a bunch of files) and just import them

Unless you have a Python version locally that doesn't support some features used in said .py file...


Nothing would stop you from doing that (import thing from ‘./downloaded.js’) but it’s Just Not Done That Way and packages aren’t really built with that in mind, so it probably wouldn’t work very well in practice.


You definitely can. On the server side, you can literally do that. On the client side, you can "import" one with a script tag, and increasingly you can use modules in browsers too.


Woah woah woah, show me a Java project repo that we’re all going to be able to install here without running into an issue.

I ran into one with Go imports just the other day, and since I’m new to it, it wasn’t a 10 minute google fix.


I've played around with a bunch of languages, and Rusts' is unequivocally the best experience I've had so far. Cargo works as intended, literally straight out of the box, crates.io and the Cargo.toml was straightforward to figure out. Certainly way less frustrating than figuring out how to use Python virtualenv when I was first starting.


I meant how imports work within a package, since that is what was being discussed in the article.

Nested `mod`s with sometimes `pub` and then `use` for other stuff certainly seems more complex to me than `import X from P`.

Package/crate management is fairly trivial in both cases, yes. `npm i [package]` isn't exactly a difficult process either.


that's fair, but newer languages like Rust have the benefit of hindsight, and can mandate one way to do things. to be clear, i'm all for that.

i don't think it's possible to do that any more with Python, the genie is out of the bottle. but you can get close with things like Black (auto-formatting) and Poetry (nicer deps mgmt and so much more). of course, how would a beginner know this? hopefully some day tools like that will become the default answers


Cargo (Rust's equivalent to npm) is quite good.


To be fair, Rust is a dream compared to JS.


He wouldn't be the first. Speaking of which, whatever happened to Dart?


I have done close to a decade of work in js, with jQuery in 2008, all the way to react and webpacker madness.

I hope someone builds a wasm based front end framework. I did a quick search and MSFT seem to be on it with their Blazor framework. Unfortunately, I am not in a hurry to go learn ASP.NET or C# anytime soon.

Maybe we need a frontend framework in Golang that compiles to WebAssembly. I am rooting for Golang here, cause after a decade in Ruby/Python/JS, I am really enjoying going back to typed languages.

But even a python/ruby to wasm web frontend framework will be awesome. Anything that keeps me away from node hell.


WASM compiles to what is effectively a normal JS library that exports some functions. You don't need a bundler to use that in an app, but as the complexity grows you might want one. It's likely that WASM frameworks will make that a simple process, but it'll probably end up working by using something like Webpack behind the scenes just as things like create-react-app do now. Take a look at https://rustwasm.github.io/docs/wasm-pack/ for an example of what people are working on to do this.

wasmbyexample has an example of how you can do it in Go right now - https://wasmbyexample.dev/examples/hello-world/hello-world.g... - you'll need to write that index.js file yourself, and that's when you'll be back to using modern JS tooling as soon as you scale up to a real app.


Thanks for those links. I found them really educational.

Does seem like we need some more tooling to avoid as much webpack pain as we can.


This resonates so much. I support some JS packages but I often wonder how anyone gets anything done in general on the JS side, and why people seem to accept the state of affairs. I'm spending most of my time with Ruby and it is night and day.


People get stuff done in JS by sidestepping all the bullshit. If you keep your tooling simple and use a minimal amount of dependencies, then JS is one of the languages/environments with the least bloat, not the most.

The big problem JS has is the same one PHP used to have when it was top dog. Everyone is a fucking noob, including all the people writing all the advice online. I find almost every JS resource to be unbearably bad, with the sole exception of MDN. The vast majority of my learning these days comes from work colleagues who also have a decent level of mastery.

So the real answer is probably that the people getting stuff done are happy with the current state of affairs, because it works for them. And the people that are unhappy are for the most part trying to change the current state of affairs without fully understanding it, and making it worse. I think every language suffers from this to some extent, JS just has a much worse ratio of masters to beginners so the effect is exacerbated.


Seems like the issue here was a lack of documentation. Almost every npm package worth their salt details the various ways to get started with something along these lines:

- In the Browser:

  - Using Parcel/Webpack/Rollup.js...etc

  - From a CDN
- In Node:

  - Using CommonJS

    - `const funcName = require('somePackage')`

  - Using Native ES Modules
    
    ...etc


> Turns out VS Code collapses folders with only 1 subfolder, which is why we hadn’t noticed.

OMG. Decades of life in emacs (emacs!) would never have prepared me for a world where my editor would helpfully lie about the filesystem to me.

Yeah, this was horrifying to read. Obviously some of it is just normal churn, and all environments have their own oral histories and weird quirks. But... yikes.


FWIW, it tries to make it clear, underlining each path component separately, and with a path separator that sin't underlined in between.

It's nice for Java style packages that are all "src/com/company/project" before you get into the meat of any code.

I agree though about how surprising it is.


Github does this as well, it's not specific to VSCode or Javascript.


This is so shitty and sad. I wish front-end dev could be more fun, with less pain, confusion and suffering. I'm losting the hope over the years about any browser stuff. :[


HTML/CSS/JS has been stretched so far beyond what it was originally designed for.

JavaScript’s tooling will only get harder to work with as we push it to handle more.

Eventually we’ll need to find something better than HTML/CSS/JS for developing in the browser.


Yea, the original intent of js was to write small snippets of code to stitch HTML together.

The neat "software distribution system" - the web browser became very popular. The wide adoption of the browser has forced js into the realm of the general purpose languages because it was the language of that VM-browser.


I never really got the modern web app stack and Typescript/javascript compiling until I was forced to use it through Angular CLI. Then it sort of all made some sense. Having a defined structure in a complex stack helps novice people a lot.

Before that it was all open up index.html template and import my js files for my projects.

I am currently going through the same thing with Python/Django Rest Framework. Another fairly well defined toolbox that some wouldn't like - but it helps with learning good practices and you can lean on a community of developers that have thought long and hard about how things are well structured.


The most ridiculous thing is the guy in the comment section recommending deno.js.


The problem is, these are the Node team's stated goals for ES Modules:

> It is worth mentioning that many of our design decisions were made with two primary goals. Spec compliance and Web Compatibility. It is our belief that the current implementation offers a future proof model to authoring ESM modules that paves the path to Universal JavaScript. Please read more in our documentation.

Sorry guys, those are the wrong goals! Just make CommonJS and ESM be mix and match interoperatable. ESM wasn't designed to be a local disk build system. Just have CommonJS behavior with ESM syntax for god's sakes.


Today's JS ecosystem reminds me of how people used to talk about Lisp: "Extend the language however you want, just write a macro!" And in practice that means there's a million little language variants floating around there; you can have different import semantics and language features and type systems and it's all glued together with a big pile of configuration and tooling.

Obviously this flexibility has been good for progress of the JS ecosystem as whole, but I hope the next 10 years are more sedate than the last 10.


If you are on an older version of node and want ESM, but don’t want to use .mjs, you can try:

https://www.npmjs.com/package/esm

The package.json should have something like this if they are going to use import/export statements so anyone on older versions don’t have to worry about it (it’s not native to Node yet without .mjs extension).

We can blame whoever didn’t set that up, or the instructions should have been to just use require().


> it’s not native to Node yet without .mjs extension

Since v13, you can use ES modules without the .mjs extension if the nearest package.json includes `"type": "module"`.


Thank you, that’s good to know.


No offense to anyone, but this image wraps up how JavaScript, HTML and CSS looks from my (outsider's) perspective:

https://www.desktopbackground.org/download/1280x1024/2013/02...


"Lo and behold, a pile of unnecessary error conditions, cryptic errors, and lack of proper feedback.". Sounds like literally every initial experience I've had with a new language / library / framework (also, life in general tbh). Usually reduced by RTFM.


to echo others here, python ecosystem is worse imo. And compared to cross compiling C++ and C for ARM, js ecosystem seems like easy mode. You can always just write a little script to attach your module to the window, if you feel averse to webpack


I've been programming professionally a long time and had toyed with python before for small scripts, but have only recently had to write larger amounts of production code, and I was not prepared for how bad the python import system is.


I can sympathize with that. Actually I miss the times where you could just drop a script into your project and have it work and still change it if necessary without having 40MB of build time dependencies.


The JavaScript ecosystem was perfect before 2015. Everything just worked! Then either Hanlon's razor or sabotage. Instead of using the existing standard module system, a new module system was invented that was so alien to the JS ecosystem that now 5 years later it's still broken. I wish ES6 modules where reverted and removed from the JS standard. Then the standard body not only completely changed the syntax of the language itself, but it also now requires a preprocessor/transpiler...


This doesn't really seem to be specific to Javascript. A beginner in pretty much any language will have to go through these kind of issues.


As it has .js extension, beside typescript, it maybe flow.js script that require babel transpilation as well.


I feel like the tremendous popularity of node caused the development team to self-reinforce bad habits, but it’s just a theory.

I often wonder what the js ecosystem would look like with Google-working-on-Go levels of runtime and package management design discipline.

One would really think Google would do this, especially considering that Microsoft now has veto power over the npm repository and package format. Yarn was a huge improvement but is still dependent upon the same broken backend model.

AFAICT the success of the JS ecosystem is entangled with Google’s success.


The shortcomings of JS are rooted in its legacy baggage. Go had none of that. JS today is a good language emerging from the ashes of a bad one, but there are a lot of ashes, and some of them are impossible to completely shake off.


As much as I am not a fan of js-the-language, the problems TFA described and that I addressed in GP are 100% independent of the language and are 100% in the domain of tooling.

Literally nothing about javascript-the-language is why package.json is in a file format that does not support comments, or why node_modules can’t be renamed or hidden or cached properly across projects, or why any of the cryptic import issues encountered by the author of TFA happened, or why yarn had to be made because npm is (or at least was) nondeterministic.

The js packaging tooling sucks, and, more importantly, has continued to suck contiguously for at least ten years. Much like Python and Ruby (cryptographic checksums, anyone?) and Debian/Ubuntu to some extent, I think nobody gives enough of a shit (or has the skills and experience and inclination) to unfuck it, or has just become blind to it over ten+ years of it sucking in the same way (much like autoconf).

It is entirely unfuckable. No part of it is baked into javascript. Go’s was fucked, and they did an epic job of unfucking it with the module and caching system. The same could be done for JS.

It would require forking node to handle imports sanely, and replacing npm/yarn packages (as well as the backend npm package repository they talk to)—surmountable tasks.


> Go had none of that.

Side note: Go has a little bit of baggage. That community is in the process of going from multiple 3rd party package/dependency managers to one official one.


Literally my experience trying to use something to calculate distance between two points


Have you tried Math.sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)) maybe?


Even better:

    npm i pythag
    npm i complex-sqrt

    // then

    var pythag = require('pythag');
    var sqrtrt = (z) => require('complex-sqrt')(z,0);
    let x = 3
    const y = 4
    var result = sqrtrt(pythag(x, y))


I can't tell if you're joking :S


Literally what I went through as well just trying to use a distance between two points module... I wish I was a cool front end kid.... but this type of experience is exactly what turns me off from front end dev


I wish that type of experience would be uncommon, rare, exceptions... But in my perspective is the real true state of front-end today. Everything is broken from a outside perspective, so much changes happened that for me learning the overall Common Lisp specification (from 1000+ pages) it's more easy to do JS dev stuff on browser.


For years on I kept saying that Java is the worst language ever because of the tons of unnecessary boilerplate and it's "you're doing it my way or you are not doing it" approach. But over the last year I've come to realize that javascript has become much worse. A good engineer and community are identified by their ability to say "OK, you know what, this turned out to be a very stupid idea, let's start over and scrap this". However w3, mozilla, opera and every other organization behind js have turned into a full blown North Korean dictatorship and everyone who suggests that there should be alternative, they get chased down with pitchforks and never heard from again. And even if they have a constructive argument as to why everything that is going on is wrong. I'm sure that sooner or later this will bite back those organizations really REALLY hard. Basically we are in the baby boomer era of js - 30 children, 17 cars, all at least 6 liter v8's, hardly getting across the street without refueling, etc. And I'm betting that in a few years time they will be the web-equivalent of climate change and holocaust deniers.


Seems like this should be directed at the particular packaged and not the ecosystem as a whole? I do feel the pain of "I just want to try this out" and it's assumed I have webpack and all the other tooling already setup to do so, though.


All the hand-wringing over the difficulties of js just doesn't seem to track with the reality I live every day. I've been hiring engineers for years and by far the most common skillset comes in the form of contemporary js framework knowledge, especially among juniors. Ask them to debug a native app build and they panic like the output on the screen is hieroglyphics instead of a log of useful information that they can leverage to solve their problem. Many times they're so confused they won't even google the errors because they can't distinguish the error text from the compiler info logs, and that's working with swift/kotlin, I can't even imagine what things would be like if we had any c or cpp projects. This stuff just isn't that hard.


I can't really tell what you're getting at here. It would definitely track that your juniors know only this stuff, because often times that's all they've been exposed to and usually for a specific type of labour. It's not really generalized knowledge. It's also not difficult, but it's not trivial to explain or get started with, unless of course you're starting at the highest level and glossing over the details. It arguably should be, and at one point it was very trivial.


> it would definitely track that your juniors know only this stuff

It doesn't track with the narrative that it's difficult to get started with, in fact, it shows that the opposite is true since these skills are very common among novices. Native application development is much more challenging learning curve for novices.

>details. It arguably should be, and at one point it was very trivial.

Create-react-app and similar tooling make things very trivial, but the suggestion that things were trivial "at one point" and no longer so is obviously false since whatever trivialities you're referring to work just fine today as they did in 1998.




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

Search: