-
Notifications
You must be signed in to change notification settings - Fork 3k
Setup multiple local modules with npm link + dedupe #7742
Comments
Since I only use Assuming a directory with the checked-out repositories like this:
First set up global linked versions of a,b,c
link a to c,b
Then add a,b,c dependencies as links
Now - don't look at the tree. It doesn't matter how often you see underscore in the linked tree, because there's really only one version, the one installed under If you need to prove it to yourself, then go to a scratch directory, and Of course there is another approach, which is just to bump all your packages to version 1.0.0 and then increment your versions when republishing. This way you make the version dependencies explicit. |
We haven’t heard back and we’re trying to clean up some old issues. If this is still a problem, can you please reply and let us know? We’ll be happy to reopen if necessary. |
I just came across this problem as well and with a scenario that is not easily remedied by the suggested workarounds. I have 2 modules: However, since I'm developing both modules side by side, it'd really help me to use |
Same issue here. |
We've got the same problem in CKEditor. We have multiple plugins requiring each other and the core package where all this is glued together. In this main package I would like to be able to On the other hand, I understand that by default npm cannot "hoist" dependencies from symlinked modules to their parent, because they may have multiple parents. This isn't a thing in my case though, and I think that this is a pretty common case where you work on a certain set of your modules. Perhaps an option could be added to |
Has anyone figured out an easy solution for this? @Reinmar From reading several GH issues, it sounds like you are using gulp to handle some of these scenarios? How did you handle a shared common dependency like |
Same problem here. We're building a webapp that we split in multiple modules. We use webpack to bundle our app. I thought Here is my webpack-related issue: I actually can't believe that nobody faced this problem before... I'm new to webpack and managing frontend dependencies with npm in general but I was sure it was a common practice, and using npm-link to work on multiple modules at the same time seems a pretty obvious pattern. Any insights on this please ? :) |
I also stumbled across this issue (especially about the problem that It basically removes the symlinks and moves the according It only operates on one level of symlinks (so only symlinks in the |
How about creating a A common For me I am seeing Or...has anyone tried override the npm search algorithm...providing a module alias? I'm going to try it now. |
Having a script orchestrating this almost boils down to re-implementing a lot of logic that npm should be responsible for in my opinion. That's really an issue that npm should be able to fix I think but it seems kind of hard with its current design. It's in the core principles of npm to have this tree hierarchy, not a flat one. Supporting both may be hard to do but that's worth thinking about it I think, as npm is being widely used for frontend now. |
@gaelduplessix It's actually very easy. You basically hook each call to require, and use your own algorithm to return the resolved path. Webpack has this feature in I have implemented it and it works well. I have to clean it up and then I will publish it. My broader goal is that all my modules are symlinked because 1. npm install is incredibly slow, and 2. I want to be able to patch/test/publish modules instantly. This modified resolver, coupled with a git |
@vjpr are there any news on your resolve.alias solution? |
@broth-eu The solution is to add this in main project webpack config:
|
@ehsalazar Could this be reopend? It looks like you can't use |
I have released a module called live-perf that will dynamically dedupe your Node.js modules. It also provides a few different ways to benchmark the time it takes to require modules in your project, and shows where modules could be deduped. Check out the examples. Basically it hooks into the require resolver, examines the closest At the moment, the module's initialization, and its deduping logic nullifies the benefits from having deduped modules. In the examples, if two modules take 1s each (2s total) to eval, deduping will mean it would only take 1s total, but the deduping logic costs 1s. This cost grows with the number of This is something I am looking into. The slow parts are traversing up to find the I think it just needs some caching amongst other things. |
It probably wouldn't work for me then. I sadly need that in webpack projects. |
I'll have to look into webpack support. It would scan your entire tree for symlinks in |
Good news - looks like webpack resolvers are pluggable. Should be easy to port. http://webpack.github.io/docs/plugins.html#resolvers |
That sounds like a good strategy! Thank you. |
@ehsalazar I think this issue does need to be reopened. It seems like it is currently not possible to link a module locally which needs to access the dependency of the main module that depends on it. For example if I try to link a gulp plugin to another module that uses the plugin, that causes the symlink to have a nested And trying to run
It's not that I don't enjoy running |
Is there an official "right way" to work on multiple, interdependent local modules at the same time that doesn't suffer from the above mentioned side effects? |
This is a serious problem. How are you supposed to develop interdependent packages efficiently? Is there a possibility that dependencies could be installed into a parent directory in certain situations? ExampleFile structure
Package dependencies// package a
{
"name": "a",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"c": "1.0.0",
"lodash.flow": "^3.5.0",
"lodash.range": "^3.2.0"
}
}
// package b
{
"name": "b",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"c": "1.0.0",
"lodash.flow": "^3.5.0",
"lodash.range": "^3.2.0"
}
}
// package c
{
"name": "c",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"lodash.flow": "^3.5.0",
"lodash.range": "^3.2.0"
}
} Ideal solutionTo develop this efficiently, I want to
Clearly that's not what I want. I'm using the same packages, IdeaIn this case, if the versions matched up, what if
Now I only have one copy of each package, and I have Perhaps we could add a flag to mark a certain IssuesSame package, different versionIf we have the same package with different versions requirements for two dependencies it isn't going to be able to resolve them this way because one would overwrite the other. ConclusionWe need a solution for this. It takes forever when I make a change in one of my shared packages to fully rebuild it using It's only an issue for development, but developer time is very valuable and it's costing us collectively a lot of it trying to deal with this mess. |
I don't see Lerna mentioned here: https://github.com/lerna/lerna It's able to create cross-symlinks between multiple packages developed at the same time and has some other tools – e.g. it automates releasing and publishing all those packages. There are quite notable projects using it – e.g. Babel. However, it misses one thing – the ability to link those packages from the main package, assuming it requires them too. It's not a big deal, because those symlinks are easy to make on your own but perhaps such a feature could be proposed. |
@ehsalazar @isaacs, could you please reopen this issue or clarify whether having nested packages using "npm link" and "npm dedupe" is meant to be supported? |
the solution which we use to remove the duplicate is define everything as external in webpack config and then those actual dependencies will be only bundled with one main module. |
@abhirathore2006, can you provide a sample configuration? I have spent my days on this problem but the problem is not solved. |
in webpack config define externals
|
Hi everybody,
I'm trying to use
npm link
to develop multiple modules locally but it's not working as expected.I'm not sure if it's actually possible with this setup or if I'm doing something wrong.
Hopefully someone can shred some light here ;)
Let's say I have this kind of structure.
The main app
package.json
has dependencies of all three modulesThe module
a
hasunderscore
as only dependencies.The module
b
has modulea
as dependency.The module
c
has also modulea
as dependency.Scenarios
The easiest way
So if I install the app dependencies I get this
$ npm i c@0.0.0 node_modules/c b@0.0.0 node_modules/b a@0.0.0 node_modules/a └── underscore@1.8.2 $ tree . ├── app │ └── main.js ├── modules │ ├── a │ │ ├── main.js │ │ └── package.json │ ├── b │ │ ├── main.js │ │ └── package.json │ └── c │ ├── main.js │ └── package.json ├── node_modules │ ├── a │ │ ├── main.js │ │ ├── node_modules │ │ │ └── underscore │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── package.json │ │ │ ├── underscore-min.js │ │ │ ├── underscore-min.map │ │ │ └── underscore.js │ │ └── package.json │ ├── b │ │ ├── main.js │ │ └── package.json │ └── c │ ├── main.js │ └── package.json └── package.json
Now if I change something in one of the modules I have to re-install them. Running
npm i
doesn't do anything of course since npm doesn't see any change in the modules definition (e.g.: version bump).So one thing we can do is
rm -rf node_modules && npm i
. This will always work but it may be slow depending on your dependency tree.Funny thing, running
npm i -f
has a different output.You can see the nested (duplicate) dependencies in each module.
The symlink way
So npm has the ability to symlink a package folder which is particularly convenient for developing modules locally.
Let's try it then (I will remove first
node_modules
to have a clean start).So we can see the symlinks in
node_modules
, but we also see that each module has duplicated dependencies.What we actually want is
a
to be a top level dependency (since is shared between modules) and most importantly thatunderscore
is not duplicated between the other modules.Again, npm (should) come to the rescue as it provides a way to reduce duplication via the
dedupe
command.Let's run it then and see what happens:
Hmm, nothing changed.
So is this how it is suppose to work? Does it actually work with local paths and symlinks?
The text was updated successfully, but these errors were encountered: