learning golang. so they have optional feature called `vendor`. so basically they reinvent the `node_modules`.

the weird thing is that it supposed to work by committing dependencies to git. but unlike node_modules, vendor directory wouldn't be massive since they come with assumption that the community wouldn't fuck up the libraries ecosystem.


  • 0
    Populating vendor directory and installing a bunch of node modules is not the same though. While package.json has a say in what dependencies get into production ("dependencies" object) and what not (all else), actually *vendoring* them should be done outside node_modules - to clarify, it's somewhere that's not going to be wiped and put through the charade that package management for Node.js is, by default. It's copying dependencies prematurely so that production machine won't need to harass repositories and be dependent on them.
  • 1
    Golang packages don't tend to need hundreds of Golang packages to work, unlike.... Mr node over there in the corner.
  • 0
    @C0D4 but isn't that a logical consequence of having packages and an ecosystem around them? As long as it's just an "install <package>", every popular language will have a huge mess of an ecosystem. See php, js, ... And it happens/will happen to golang too.

    Offtopic: php made it even more fucked up, as 2 versions of a dependency cannot coexist. Dependencies are a tree, not a circle.
  • 0
    @nitwhiz it's not fucked up at all in PHP.

    Multiple versions of one package is fucked up. Deeply.

    This is the reason why NodeJS is a nightmare. From any point of perspective.

    Any sane package management system was and is based on the concept of single version per package.

    Except e.g. NodeJS.

    Don't make the bad example look good.
  • 1
    @IntrusionCM why?
    In my eyes, it makes way more sense to keep a package and it's dependencies isolated from another package and it's dependencies. What a package depends on is managed by the package, not by the dependant.

    Otherwise, what are your options if you depend on package X and Y, but X and Y are different versions? Of course, I know what you're going to say: X or Y need to update. Sure they have to, but your whole development process is now halted until the dependency is updated or you had to do the classic PHP thing: reinvent the wheel and implement the dependencies functionalities yourself, creating the problem all this tried to solve: unmaintained legacy source code everywhere.

    It may not sound like it, but I'm open for discussion: Why only one version of a package? And if only one: which one? The most recent or the one the most packages use? How would you manage keeping up to date with all dependencies dependants to always keep your constraints ins check?
  • 1

    Usually dependency resolution works exactly the way you described it:

    A pulls dependency B in V0.1…
    C pulls dependency B in V0.2....


    When you pull now for each library each version, this is what happens:

    A pulls dependency B in v0.1
    C pulls dependency B in v0.2

    But the dependency resolution is not finished now.

    In a nutshell, the dependency resolution now needs to happen for each package with a full dependency graph.

    You need to resolve all dependencies of A, including it's transitive dependencies (e.g. B) etc.

    This is why Node is incredibly slow.

    Plus the resource consumption, cause every dependency graph needs to be stored. Even with deduplication, this is pretty gory.

    Security wise, you even have a bigger problem.

    You cannot update one single library. It doesn't work that way.

    You need to update multiple versions of a single library in case of an security flaw - as we have multiple dependency graphs, you now have to make sure that you catch them all.

    The update problem, that you "solved"…. Has now grown exponentially.

    It's not solved.

    It's just delayed and grown.

    If you really never want to deal with the PITA of library updates.... Then get a disconnected machine away from the internet.

    Otherwise you will have to update.

    Which is the saner approach, no matter how much you try to frame it as "bad".

    Not updating libraries means, security aside, that you never update your tech stack, you never upgrade any environment (node / base distribution etc.).

    So you simply refuse any form of progression, cause you have to spend time to work on it.

    In my opinion, that's the worst one can do....
  • 0
    @IntrusionCM I see.

    You should look at PNPM, it only saves every version a single time ever on your disk and is extremely fast.
    Just to answer the speed/resource-argument.

    But with everything you said, I wouldn't call one way "saner", they are both equally stupid, as they both more or less create the same problems in the end, when it comes to security/resource usage/interoperability, just in a different way.

    I'm not trying to frame anything btw, I'm trying to tell you what doesn't make sense about it in my opinion.

    So the right way to do it would be to keep only one version of the package: the latest.
    There is no real semver, packages always use the latest master and it has to be backwards compatible. As soon as you're going to break BC, release a different package with the major version in the name (or something like that). That way, you keep old major versions and can phase out without stopping anything/staying on old versions systemwide.
Add Comment