denoland / deno

A modern runtime for JavaScript and TypeScript.
https://deno.com
MIT License
97.84k stars 5.39k forks source link

NODE_MODULES not created in sub projects #26743

Open irbull opened 1 week ago

irbull commented 1 week ago

Version: Deno 2.0.4

When creating a Mono repo (with "nodeModulesDir": "auto" set in the deno.json), the deno install command doesn't create node_modules in the sub projects. There is only a single NODE_MODULES at the root. After a few discussions on Discord, this seems to be a bug.

I've created a basic mono repo [1] that follows the layout described in [2].

[1] https://github.com/irbull/deno_mono_repo [2] https://docs.deno.com/runtime/fundamentals/workspaces/

Steps to reproduce:

  1. Clone this repo (https://github.com/irbull/deno_mono_repo)
  2. type deno install
  3. Notice there is only a NODE_MODULES directory at the root (not in any of the sub projects)
dsherret commented 1 week ago

This specific example seems to be fine. Deno doesn't create a node_modules folder in workspace members unless there's a conflict with something at the root.

irbull commented 1 week ago

That's fair. This particular issue came from two different places:

  1. I was trying to migrate the Deno Astro Adapter away from pnpm and use deno install directly. The current design of the repository requires a complete installation below each sub module. This is used so that the sub modules can act as integration tests and replicate a fully installed adapter. All the dependencies need to be accessible at paths below the sub module in their own node_modules directory. It sounds like this is not what deno install can do, so we are stuck with pnpm for the adapter.

  2. @bartlomieju mentioned that he noticed some strangeness with sub modules and asked me to file an issue with the problem I was having. It seems that the issue he was having and the one I was having are not related.

Since this doesn't actually represent a problem with deno, I suggest we close it.

nathanwhit commented 1 week ago

I've been thinking about this, and I actually think we might want to consider always creating node_modules dirs for the workspace members.

The main reason I changed my mind is that right now, you can effectively end up with shadow dependencies. If one workspace member doesn't depend on a package, but another workspace member does, since they're using the same node_modules dir it would still successfully resolve for any member of the workspace at runtime.

It shouldn't be too expensive, either, since you're just symlinking the top level dependencies from the workspace root's node_modules/.deno

irbull commented 1 week ago

pnpm goes a bit further here too. It can actually package up other projects in the mono repo as dependencies in a sub package's node_module directory. It uses hard links for this.

To be super concrete, if add had a dependency on main, after running install you would be able to:

add/node_modules/main/add/node_modules/main/add/node_modules/main/add/node_modules/main/add.....

after running pnpm i on the deno-astro-adapter I can run:

ls test/fixtures/basics/node_modules/@deno/astro-adapter/test/fixtures/basics/node_modules/@deno/astro-adapter/test/fixtures/basics
/node_modules/@deno/astro-adapter/test/fixtures/basics/node_modules/@deno/astro-adapter/test/fixtures/basics/node_modules/@deno/astro-adapter/test/fixtures/basics/node_
modules/@deno/astro-adapter/test/fixtures

and that works :).

Obviously that's a silly example, but the point that dependencies (including peer & parent ones) become hard links means each sub project can be run as if it's completely standing on its own.

andersbc commented 18 hours ago

Version: 2.0.6

Another use case:

I have a monorepo setup like:

- backend/ (pure Deno)
- webClient/ (Vue)
- shared/ (pure Deno) - imported by both backend and webClient  

I want backend and webClient put in two different Docker containers.

My expectations when I run deno install --entrypoint main.ts in backend is that I get a node_modules or some other local cache inside backend, ONLY including the dependencies of the backend workspace.

What I get instead is a node_modules at the parent level, including dependencies of all three workspaces, bloating my backend docker container with unused dependencies from webClient .

It seems to be the same topic (apologies if I am not parsing the thread correctly)

The docs (https://docs.deno.com/runtime/fundamentals/workspaces/) were not helpful on this topic.