I have a project with multiple node_modules directories
myproj
|-->app1
package.json
|-->node_modules
|-->src
|-->origapp_reactnative
package.json
|-->node_modules
|-->shared_src
|-->app2
package.json
|-->node_modules
|-->src
When bulding app1 or app2 with webpack (from their respecitive root dirs.). I must specify
resolve.modules=[path.resolve(__dirname,"./node_modules")]
If I do not do that, then webpack will try to pull code from
|-->origapp_reactnative
|-->node_modules
Because app1 or app2 include sources from shared_src. And webpack tries to follow nodejs convention and look for node_modules in the dir next to shared_src.
So that's why I am setting resolve.modules to an absolute path.
However, that creates another problem, that I cannot overcome: webpack flattens the dependency tree within node_modules specified by absolute path. And that creates dependency problem, where modules of different versions cannot coexist.
So I am looking for a way to use, therefore, relative path
resolve.modules=["./node_modules"]
But need help to figure out how to exclude the node_modules
|-->origapp_reactnative
|-->node_modules
from webpacks consideration.
( I have tried to instruct babel loader as discussed here [1], not to look there -- but that's not enough, because compilation still will fails. )
You seem to be almost there. When you build app1
and only want to use node_modules
from app1
, you can use resolve.modules with a relative path app1/node_modules
.
resolve.modules
webpack config in app1
:
const path = require("path");
...
module.exports = {
...
resolve: {
extensions: [".jsx", ".js"],
modules: [path.basename(__dirname) + "/node_modules"]
},
};
(Assumptions: cwd
pointed to app1
's root, webpack config in app1
's root)
With path.basename
, you can make your config more independent from the actual project name, effectively having the setting modules: ["app1/node_modules"]
. If you import something from shared_src
, which on his part uses node_modules
, it will traverse via node resolution up to myproj
and from there find the path app1/node_modules
.
You could also add node_modules
as fallback, if you have additional packages only installed in the shared project:
// first entry takes precedence.
modules: [path.basename(__dirname) + "/node_modules", "node_modules"]
resolveLoader
can be set as extra property for loaders, if you happen to get an error not being able to find loaders from node_modules
afterwards.
resolve.alias
If all you need is importing a few packages from a specific node_modules folder,
you could also use resolve.alias
(for example resolve react
here from ./node_modules
):
resolve: {
alias: {
react: path.resolve("./node_modules/react")
}
}
( I have tried to instruct babel loader as discussed here 1, not to look there -- but that's not enough, because compilation still will fails. )
Babel-loader and Co. use the absolute file path that is already resolved for rule conditions, if you want to exclude something to be transformed. In every case exclude
and other filter options of loaders do not prevent your imported modules (like the ones in node_modules
) from being excluded. When modules are filtered out, it only means, they aren't further processed by Babel loader (or other loaders, where you have defined rule conditions).
Hope, that helps.