Probably the worst thing is that the standard library with Node Javascript is tiny. Therefore, you have to pull in a pile of NPM packages to do pretty much anything. The package ecosystem is rather messy for the same reason - there's a mountain of tiny packages doing a few little things because somebody needed to do just a few things and didn't want to pull in some massive library that does a ton of stuff including the thing they need to do. Which then leads to a lot of bigger and more useful packages having huge dependency trees of tons of little packages, all at poorly-managed versions that usually can't be shared with any other big packages. So a program that needs, say, 3 major packages to do something useful might end up with thousands of dependencies taking up hundreds of megabytes, often with 3+ copies of the same package at different versions.
For example, I have a little webapp that I built with create-react-app with typescript and redux. Very convenient overall admittedly. It's not very big, maybe 1k lines of code total, and 3 fairly minor packages added to do various things. The node_modules folder has over a thousand items in it, and takes up 350MB. The yarn.lock file alone is half a megabyte. Ahem, what the hell? At least the built artifacts are pretty small.
This might be seen as just a problem with create-react-app. But in my experience so far, pretty much everything in the Node world does this. Seriously, has anyone managed to do something useful in the Node world without ending up with a thousand packages?
Any professional java developer will tell you exactly the same thing about java.
Professional java developers use a maven file which is similar to a package.json file. And it lists dozens of dependencies.
Even though java has default collections (so does javascript by the way), most developers also want Apache Commons (which could be compared to lodash)
And by default java has no DI and IOC, so most of them will install Spring Boot. The thing is, spring boot isn't just 1 dependency. There is actually a spring boot initializer website to help developers pick their dependencies. On top of that the names of Spring dependencies change between releases, sometimes they move things around.
And about persistence. In java you would need a JDBC library for ms sql server for instance. However, there are different ms sql server jdbc libraries depending of the version of the database, and depending on the version of your JRE. And in some cases you need additional libraries to add security protocols. (e.g. "bouncy castle")
And then there's JAXB which used to be included in the java framework, but has been removed since JDK8. Talk about backwards compatibility.
And what about portability. If you want to make a setup utility or installer for your software, then often they will include a copy of the Java runtime inside the installer. After all, you can't expect users to have java pre-installed. That does mean, that every installer has a footprint of 400MB+ (~the size of a JRE).
Every time you commit, package-lock.json is different. And when it is not, then I have 26 new vulnerabilities to be fixed by “npm audit fix”. I have zero trust in my build being reproducible, or even working one year forward.
If your package-lock changes every commit (I'm guessing this means it changes after every `npm install`) then you might have some issues within the team in terms of consistent npm/node versions, or perhaps with the registry you're using if it isn't the public registry.
In my previous role we constantly ran into issues with the integrity hash changing which was an unfortunate side effect of both the issues I mentioned above, an Artifactory npm registry and inconsistent npm/node versions
TL;DR though, it's not normal for the package-lock to change all the time.
> Every time you commit, package-lock.json is different. And when it is not, then I have 26 new vulnerabilities to be fixed by “npm audit fix”. I have zero trust in my build being reproducible, or even working one year forward.
In some of the nodejs projects I've worked, we had allu dependencies with pinned version numbers, and each week we created a ticket to track work on upgrading them. This typically involved a single commit updating package versions and running all tests. More often than not it took no work at all.
If a project just lets their dependencies change randomly and does not invest any work updating them, of course there's bound to be pain and suffering.
I do a agree with you, but we should also keep in mind that there's a distinction between dependencies and dev dependencies.
Building and bundling for the web platform (where you have multiple browser, environments, users on different versions) is a real challenge and you actually want to have good tooling for this.
With NPM, you just bundle all of the tooling along with the dependencies you need for your actual app.
I think that's still a big improvement over projects where you first had to setup your dev environment in very specific ways just to get started (I remember this could even take days to get right for some projects I worked on).
Although I would really wish for a better standard library, or at least some "core NPM modules" which are officially agreed upon, promoted and security checked as an almost-standard-library.
Clearly you have a very shallow knowledge of the Node/NPM ecosystem. The very thing you mention as a downside is what empowers you to achieve the solution to the problem you want to avoid. Instead of going for the one-keystroke create-react-app, you can cherry-pick the packages you need and use that. Also packages tend to include other non-javascript files. I'd suggest you dive a bit deeper before drawing up wrong conclusions.
Can't agree more, after spent 3-4 years with nodejs on and off, I am not going to adopt it for any future projects.
a strong 'stdlib' is a must, no other code will pull in who-knows-what packages hundreds of MB at least. Just like javascript is badly design, so does nodejs.
Node's tiny stdlib invites the question - which compile-to-JS language has the best standard library? Dart? Clojurescript? Strange how Typescript missed the opportunity to fix this.
Small composable packages aren’t a bad thing IMO. It’s nice to pull things together how you want without having to reimplement the same logic multiple times. Just encapsulate smaller bits of useful code into their own mini packages
Like if there’s some string manipulation thing I need, instead of copy pasting some snippet, I can pull in the micro package that already does this
I'm going to have to disagree with that. Micropackages may seem nice at first, but they're a nightmare to manage longer-term mostly due to low-skill project management. Many such packages make breaking API changes, sometimes without obeying SemVer standards. Some are effectively abandoned, and don't get updates for regular bugs, security issues, etc. Sometimes the lone developers responsible for them may delete them in a fit of pique (left-pad anyone?). Sometimes they get taken over by malicious entities who might add obvious or subtle malware to it. I'm pretty sure all of these have happened already.
That's not even what's important though. What's important is, how can you ensure that none of these things happen to any of *your* projects dependencies? It's virtually impossible when there's a thousand of them. Are you going to audit that string manipulation micro package when you first add it, and then for every version update from now on, to ensure that nobody slipped some subtle malicious code into it? And do the same for every other micro package in your project, including all of the ones that the big ticket packages depend on?
All of this would be much less relevant if it had a more fully-featured standard library.
makes sense in some situation but people seems to forget left pad fiasco. And the small package which you say sounds good in theory but what we get is bloated things that depends on multiple semver package. And many developers don't even have a clue whats happening which algorithm it is using and thats fair if you get millions package in nested dependencies.
However in Rust I find these packages managed properly which npm should learn.
The thing is, many other modern ecosystems have these included. You don't need a pile of dependences because you are guaranteed to have the functionality you need. Of course you will still need modules for more specific things but since the most often used functionality is already there you end up with ten packages, not a hundred or more.
I know that ecosystem fairly well, and have found it pretty effective to develop in. Compared to that, we have vanilla JS, which is okay for a thing or two, but awful to make a full SPA in. Or probably like 20 other web UI frameworks, all of which probably do the same thing as far as dependencies and have a learning curve for how to use them.
And what do we mean by "enterprise" here? The issue is the dependency chains and the maintenance issues that causes. If it was really "enterprisey", you'd think they'd do a better job of having a manageable dependency chain.
They may not need it now, but they choose this technology for a reason - maybe because they plan to develop it much more in the future. This does not mean they can't criticize its obvious flaws (which are a bit at odds with the "enterprise" part btw).
Usually, when you make a little project, you use the tools you know the best because you don't want to spend time coming up with something from scratch.
Also, it's a safe bet in case the project grows beyond the initial scope. You don't want to spend most of your time refactoring, do you?
Redux alone contributes a lot of boilerplate to state handling. Why is it needed? It has no benefits in small apps, it’s easy to abuse to destroy performance if a future dev isn’t cued in to the way Redux state needs to be normalised, and a React useReducer state handler is trivial to refactor to a Redux one later, if needed.
The same goes for TypeScript—how many interfaces does that app really have? Is it used in strict mode or just to type the most critical things?
For example, I have a little webapp that I built with create-react-app with typescript and redux. Very convenient overall admittedly. It's not very big, maybe 1k lines of code total, and 3 fairly minor packages added to do various things. The node_modules folder has over a thousand items in it, and takes up 350MB. The yarn.lock file alone is half a megabyte. Ahem, what the hell? At least the built artifacts are pretty small.
This might be seen as just a problem with create-react-app. But in my experience so far, pretty much everything in the Node world does this. Seriously, has anyone managed to do something useful in the Node world without ending up with a thousand packages?