There was that time where one dev broke the internet by deleting one simple NPM package.
Or the thousands of malicious packages that are removed every year?.
The node_modues dir also becomes massive as it needs to download hundreds of repos including readmes, tests, and other cruft for what is often only a few lines of code. And it used to need to download the same libraries many times for every dependency that needed to use it (not as big a problem now that they are flattened by NPM first).
The node_modules dir also breaks sometimes needing you to just delete and recreate it.
It automatically runs install scripts when you download a package (and all it's dependencies) by default which breaks a lot of packages if you disable them.
It has improved over the years and some of these are no longer issues, but they have all contributed towards people's dislike for NPM. The overall idea for having a file tell you what deps are needed and to download those deps is not a NPM exclusive idea and most if not all modern languages do the same thing. Even older languages have started to adopt similar tooling. Some share some of the issues NPM has, though others have improvements over it as well.
But these are developer tools design for developers and build systems to use. Not really ideal for end users. Especially for compiled language. But even for NPM, you don't want to be shipping a full node_modules dir to all your end users nor do you want them to have to install your language tooling every time. It be more ok for developers that are already working in the language or sysadmins deploying to a server, but for the average desktop user it is not a good experience.