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?
Professional java developers use a maven file which is similar to a package.json file. And it lists dozens of dependencies.
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).
Node.js isn't that terrible now, is it?
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.
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.
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.
Sounds like a bad choice of tools for a person who's is concerned that much about the disk size.
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.
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?
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?
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
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.
However in Rust I find these packages managed properly which npm should learn.
More like "which the JS/TS developers should learn from"
npm is just a package manager, it's not its fault.
I also don't particularly care for "async everything" by default. It makes your program more difficult to reason about. Rather than dealing with concurrency in a subset of your application, you now have to worry about it _everywhere_. There are only a few classes of software where the async-everything approach even makes sense.
Throw in the fact that the ecosystem is an absolute dumpster fire and you have more than enough justification.
You just write code, and the system figures out how to break things up.
However the OP and I, are talking about async everything as a programming methodology and not as a fundamental part of the base system.
Wish the UI components would just render regardless of whether or not an async call was finished, rather than have to write conditionals for the components to display based on returned promises, populated states/context... I've grown to really hate react these last few months
Electron embeds a web browser, which is a highly complex asynchronous application which is written in C++ by one of only a handful of super high tech companies. It is notorious that efforts to make web browsers with other runtimes (e.g. Hotjava) have failed.
I looked at what the options were for cross-platform guis written by applications programmers and they were not pretty, had serious warts, and all went out for long lunch breaks.
What more complex games do (simplified) is put file IO on one thread, network IO on another, and use async (worker threads with jobs) for the rest.
 - https://godotengine.org/article/why-does-godot-use-servers-a...
What's the browser got to do with it?
For every node.js server there are probably 100 CLI programs that get run by the way.
My conspiracy theory is that this phenomenon partly created the need of microservices within the web community and by that creating entire new set of problems that needed to be solved.
I understand your complaint.
Just to add some historical background, Node.js creator Ryan Dahl deliberately architected it that way. He thought threads to express concurrency had flaws. (Especially for i/o tasks instead of cpu-bound tasks). An excerpt:
>“Node was originally born out of this problem — how can you handle two things at the same time? Non-blocking sockets is one way. Node is more or less the idea, or exploring the idea: what if everything was non-blocking? What if you never waited for any IO to happen?”
It's interesting that around the same time, a JVM-based competitor called Vert.x adopted the same philosophy. An example discussion on HN where some favor async by default:
Although JS has problems, it did already win so Node.js is useful in that sense. But async everything is nutso and requires lots of gating and checking mechanisms in order to get back to synchronous, imperative behavior which is what you normally want in a scripting language.
The setup/versioning and dependency hell issues of Node are absolutely bonkers. I work on a monrepo of 400,000 lines of code at work and I think most of the Node stuff is "just guessing" when people run it. Secret incantations that don't make any sense and have to be copy/pasted. All of Node is like this.
In what way did it "win"? People use JS because it is in the browser, do you have any data that JS won anywhere except the browser? Pretty sure it isn't even the most popular solution for web backends.
What common problem suffers the most solved in js? Preferably something without hope for improvement.
There probably isn't much benefit to different languages if you're just manipulating the DOM (which is probably why that model failed, having more than one language doing the exact same thing is needless extra complexity) but using the browser as an application runtime opens up the possibility of making any software written in a supported language accessible and executable from a URL.
The "JS as bytecode" model got us surprisingly far, but it was a disgusting hack, and Java applets and Flash had their day in the sun, but Webassembly is probably what's going to make the "multiple scripts in the browser" model eventually feasible.
It could not be required to run the script. For example require the visitor has his own website and have the script interact with specified tools installed there. Or
a very limited language that disables js for security.
It could be a highly readable DSL, for example something to write interpreters in.
Or something narrow like interact with a rich text editor or data visualizations.
Perhaps a basic game engine.
I think its awesome :D
Oh well, I learned I never want to touch Node again.
Tests can be written properly and in a very reliable way in any platform, and a mess can be made in any platform too.
I used to apply for JS jobs, and the interview would have questions like "What do you dislike about JS?" I couldn't find much to dislike and never got those jobs. Maybe it's a sign of proficiency when you're good enough at a language to hit its limits.
I'd say the other effect is when you join projects built by experienced but non-senior people, it tends to be overengineered. Overengineering shows the ugly side of a language. Everyone assumes that this is normal behaviour for the language, when it's frequently not.
- the sense that I never really can be sure where the code is executing at a glace;
- the (compared to Python) cruft-laden syntax
and unlike these other languages there s not usually one or two ways of doing things. there's so many different frameworks, build tools, countless stacks beyond measure. when someone is force converted onto node they're more likely than not to have poor footing, be unable to make the typical sloe steady grind into proficiency they would with a less diverse language like python or ruby.
And in a negative way as well :-) Ask me how I feel about php.
This is, though, a very excellent point.
Negative views about PHP is completely justified :)
You wouldn't make this statement if to compare bogosort and quicksort, would you?
Programming languages have evolved. We know how to do better now.
I hate Python and could go on all day about what's wrong with it, but it doesn't suck. I use it when it is appropriate for the task at hand, but find it is rarely the best language for the job - given what I know and what I prefer.
Most people that hate a language also avoid it and, therefore, tend to not have made their peace with its shortcomings, so don't have an honest reckoning.
It is unfair to completely disparage a language until you have fully figured out how to understand and work with it, warts and all. Frankly, until then, you aren't yet informed enough to make a summary judgement. You are just cherry-picking your dislikes.
I have rarely heard a criticism that did anything but highlight the critic's lack of knowledge. For example, there is a common criticism about the lack of a standard library. Well, that is how the ES or Node ecosystems are structured. It is not a flaw - it is just a different approach. If you work intelligently within that paradigm, it is actually quite nice. If you hold onto your expectation that a standard library is a part of any respectable ecosystem, you're going to be perpetually dissatisfied with ES/Node. It may not be what you like or expect, but it is not inherently wrong or lacking.
Parenthetically, anyone who makes the standard library complaint about Node just doesn't know Node. It has a very complete set of functionality natively, for its purpose. It is not going to offer much in the way of math operations, sorting algorithms, etc. That is not its purpose. If you want those things, you can add them.
If you think that a given dependency is too big, too small, incomplete, or poorly managed, write your own, and publish it like many have done.
But be warned - if it gets popular, there will be no end of complaints about what's wrong with your library because ... well ... it is actually developers who suck. We have opinions and are quick to convince ourselves that those opinions are fact and anyone who disagrees is not as smart as we are.
The lack of opinionated defaults has some benefits:
- It gives you a ton of flexibility
- It makes it easy to learn the framework, since there's no magic.
- It forces the team to really understand what the application does from first principles, again since there is no magic.
The other side of this coin is that flexibility often leads to architectural chaos, and working with Node can feel very slow, since you're constantly reinventing the wheel.
The reality is that 80% of the things I'm building basically just need some variety of MVC with a reliable and predictable way to connect to a SQL database, and Node doesn't feel like the right tool for that job.
Rather than comparing with Django or Rails, one should instead compare it to Python and Ruby. There are several server side web framework for NodeJS also (Meteor, Sails, Express).
It's possible you may have confused Node with Express, as I see that happening very frequently, but Node is used for all sorts of other workloads like desktop apps, microservices, and other general computing tasks.
EDIT: To add a more constructive comment: Don’t worry too much when people hate on a given language and don’t try to make a decision based on what tool or language people are complaining about. Every tool has its usefulness and its drawbacks.
EDIT: It was Steve Yeggie, back in 2007: https://steve-yegge.blogspot.com/2007/02/next-big-language.h...
I literally don't think I've ever seen anybody try to argue that js is a good language. I can't conceive of anybody trying to argue that such a pitiful standard library is a good idea. Why in god's name would you choose to use it server side when you could be writing something less excruciating like perl or php or assembler or brainfuck?
To be fair, they never really picked it per se, it was just the only thing that was kinda-sorta standardised enough that you could write code and kinda-sorta-almost get it to run on most browsers without installing some horrible plug-in. I think a more appropriate question is why it never got replaced with something not-awful.
One person’s opinion of Python’s good parts would be equally small and any opinion would be very small compared it to the entire official documentation.
That said, I have found that the .NET ecosystem is an agreeable way to build the kind of software I need to build. I don't think my product would be infeasible in a Node.JS ecosystem, but it would certainly be more painful for reasons that are specific to our problem domain.
If I had to take a shot across the proverbial HN language war deck, I would say that dependency management is the biggest reason I would prefer to avoid Node.JS on future projects. I have a very complex .NET code base which uses 3rd party dependencies you can count on one hand. Our customers really enjoy that kind of thing.
- lots of people don't like V8
- the guy who made Node.js (Ryan Dahl) doesn't like it either
- programmers think anything without thread support is a toy
It is dominated on the server because Java, C#, Elixir, Erlang have a concurrency and parallelism story and node doesn’t.
For most scripting work it is hard to beat Python even if Python is slow.
Sometimes I think compiler and tools writing for node might be fun (boy the world needs an ISO common logic implementation that isn’t hets and Haskell) but compiler and tools writing in Java is fun too, particularly in JDK 16. (Think ‘Haskell the good parts’.)
I would love a more in-depth exploration about this part of your message, if you have some time. I didn't explore the compiler/tools ecosystem for Java for some time, would love to know the advances it got that prompted your message.
With sealed types, var, and similar features, pattern matching, it is getting better all the time in small ways.
I recently wrote a dsl in Java that lets you write a Java AST , transform it as a tree, write Java source code, compile it. It is not quite as simple as doing the same in LISP and you have to mangle names a little to unerase types, but the IDE helps you find the names.
Apropos of nothing...
I find Python to be unreadable. I have a moderate reading issue and Python just looks like random letters to me. I actually wish I could process it as there are some very nice tools that I see people make that use Python.
It has some flaws sure, but unless you’re going out of your way to use poor practices or using node for a task it isn’t great for, that’s kinda on you right?
Used node for many things, including services currently in use by many millions of users. It’s just a tool in the toolbox, so use it like one where it makes sense.
Go's standard library comes with a lot of the same batteries built in and while I write more code in Go, the compiled binary is small (good for container management) and I use less dependencies.
So that last sentence is the key. When I was writing a lot of Java, I learned to curate my dependency graph carefully. When writing in Go, I've become even more careful to only use widely-adopted packages though I'm a bit more lenient with test-only package.
I've predominately stopped using Node.js because it's dependency graph is simply unmanageable. Node.js itself provides a facade of multiprocessing as well as other niceties you'd expect to find on the server-side but to do anything substantial you either need to code it yourself or you adopt a huge dependency tree. Downstream security vulnerabilities and bugs mean you're continuously updating versions and it's not always pretty.
Now that I've adopted the write a bit more code and use fewer dependencies mentality, perhaps I should try another project in Node.js. I have to admit that Typescript (and even some of the EMCA improvements) also make it more attractive.
If you design a tool (or DSL) you must tailor it to the problem it needs to solve. It must not be overly generic while still covering the entire scope. This is extremely hard and it usually takes a few versions for a language to get it right.
Then we take the DSL and implement it in an entirely different situation(????) Look, I can use my wrench to hammer in nails!
What to say? The nails are indeed going in. Massive structures are erected. They are structurally sound but it just doesn't look professional to people who are used to hammers. I'm going to be using a hammer until end of time. I tried holding the wrench over the nail but I just couldn't bring myself to hit it.
(with hammer I mean PHP)
The early perceived coupling with MongoDB didn't help.
In my experience, the entire JS ecosystem does not respect robustness, stability, backwards compatibility, correctness, testability, and learning from other ecosystems. It continues to erode itself with emojis in the package manager, childish schzophrenia of frameworks, complete disregard for proven methodologies and extreme indifference to maintainability.
First of all:
1) I'm a self-taught developer
2) I spend last year building my app on MERN stack
The question really is:
- Is .NET or any other framework so called "battery included" ? or I also need to add hundreds of dependencies i.e. authentication -> password hashing, jsonwebtokens etc..
- As .NET or any other framework requires more code vs Node.js -> does it pay off later on during refactoring? Means is it more productive vs any JS framework?
I'm really considering to spend next year learning C# with .NET because being solo dev it's really time consuming constantly monitor what did change and what needs to be refactored. JS stack doesn't help with maintaining the project in a long run (or I have limitted knowledge) it is really time consuming stack tbh
I agree that creating a simple CRUD app for web course it is easy but if you need to do something more advanced...
Should I start learning C# ? or .NET also require thousands of depedencies i.e. file upload (multer docs!!! Man I know them almost by heart now...)
BTW, learns at least 2-3 languages in your career. This will give you a perspective many lack.
Basically every other web stack is "battery included" compared to node.js. It is the only framework having this problem as far as I know. Rails, Django, the java frameworks, net etc, all of them have basically everything you need out of the box.
I don't use it for full applications so I don't have some of the same issues that @ufmace mentions (ouch!) and those are clearly a problem.
I suspect that a lot of the hate comes from people that would like a better Node.js so they could use it but resent that it isn't available
Whereas... I had worked with php, python, R, and once I got to NodeJS I fell in love with it. Then picked up ReactJS
And man, so glad I went this route. I never have to apply to jobs again, given the hunger of recruiters for full stack JS devs
Doesn't PHP run like 70%+ of the web?
Do you have any evidence of that? I've written quite a few new PHP apps in my time.
Being popular means you get a lot of criticism. Same happens to java, PHP, and any other popular language.
I think this is self evident but maybe someone else will care to list some usage statistics.
I wouldn't say it's popular; it's ubiquitous. It is the only language available for development on one of the most used platforms in history: The Internet.
Also, I'd wager there's more than just a few of those very noisy people.
I get it, it has the shitty parts, but it also evolves, becoming better and better. And most importantly - it's one standard. No branches, no perlisms. Just one organism evolving. It's really great when you come see it through the prejudice.
Most arguments, even in this thread already, are just wrong. Obviously they have never had any experience with the Node.js ecosystem and another.
What makes them obviously wrong? To me they sound like sound arguments by people who actually use(d) it.
> node does not have a concurrency and parallelism story
> standard library is tiny
Also claims like "async makes your program more difficult to reason about" without any explanation.
I hereby claim that goroutines and mutexes make your program more difficult to reason about.
> the ecosystem is an absolute dumpster fire
I am super curious which ecosystem that person would consider better.
> no threads
Worker threads are a thing since Node v10.
Also, I like the single thread concurrency, it makes state management easier (since there is no race condition).
You have sockets, http(s) (even http2), multiprocessing, readline, streams, timers, promises, JSON, etc...
They want String.capitalize()? They would complain about the implementation being bloated because it handles edge cases like other alphabets, etc...
> async makes your program more difficult to reason about
That may have been true with the callback hell before async/await. But now, it's just non-sense.
Ironically, for an ecosystem based on the philosophy of "Don't reinvent the wheel", there are a lot of packages that does the same thing.
There is the leftpad fiasco, the colorette/nanocolors "scandal", the is-odd/is-even packages, ...
But as I said in this thread, this is not Node's fault, nor npm's fault. This is the developer's fault.
Cargo (rust), Mix (elixir), pip (python), they could all serve such an ecosystem.
It's up to the developer to be careful about his dependency tree. For example, if I need VueJS which depends on a specific library, I'll avoid installing another library doing the same thing.