チーズパン
チーズパン

Reputation: 2778

Unexpected behaviour with `npm install` of a local project

Scenario

For development purposes I am referencing ProjectB in ProjectA's package.json via "projectB": "file:../projectB". Basically the only files I need there are in the lib folder which is Webpack's output.

Problem

If I install this dependecy with the configuration above, npm will install the entire ProjectB-folder into node_modules. It will contain everything projectB's node_modules, configuration files, the src-folder etc.

Apart from the fact that this can't be the expected behaviour, this leads to errors. For example some of the installed @types will throw an error because they are considered duplicates. @types and other packages from ProjectA and ProjectB seem to "collide". Those packages are referenced as "dependencies" in both ProjectA and ProjectB mostly.

What I tried

npm link

If I use npm link the same (see above) behaviour appears. The entire folder will be installed into ProjectA's node_modules.

npm pack

It might be important that I actually do have a .npmignore-file in ProjectB. So when I use npm pack a projectB.tgz file is generated. If I then install ProjectB via "projectB": "file:../projectB.tgz" everything works fine. I assume that npm pack does take the .npmignore-file into account.

My problem with this solution is that I not only would have to build ProjectB every time a change is applied to it but also npm pack it.

Delete ProjectB's node_modules

I guess this is the silliest workaround. If I reference ProjectB via "projectB": "file:../projectB" again but delete its node_modules after building it, they do not appear after installation. Thus I do not get any more exceptions.

I guess this is not a valid solution either as still the entire ProjectB-folder is being installed.

Question

What is the best practice here? What is a reasonable constallation for ProjectA and ProjectB in order to install ProjectB from a local source?

Upvotes: 7

Views: 519

Answers (3)

tomc
tomc

Reputation: 1458

If projectA requires files from projectB/lib, you could configure webpack's resolver as follows (assuming webpack 4):

resolve {
  alias: "projectB": "projectB/lib"
}

If projectB is a module, it's package.json should include the corresponding entrypoint (see this page).

I would also suggest you try yarn instead of npm for package management. Yarn's workspaces feature is designed for working with multiple interdependent packages.

Upvotes: 2

Derek
Derek

Reputation: 997

You could alias projectB/lib in the webpack configuration for projectA. That will tell webpack to look in projectB's lib folder when resolving projectB modules.

Example webpack.config:

{
    resolve: {
        alias: {
            "projectB": path.resolve(__dirname, '../projectB/lib')
        }
    }
}

Also, if projectA is utility library that will be installed in another project, make projectB just a peerDependency of projectA. That way when projectA is installed, the user will get a warning if projectB is not installed or if an incorrect version is installed.

Example package.json:

{
    "peerDependencies": {
        "projectB": "1.0.0"
    }
}

Upvotes: 0

Wouter Coebergh
Wouter Coebergh

Reputation: 834

Can you try putting the following code into the package.json file of projectB?

"files": [
    "lib/*"
]

This should tell any npm install to only use the files specified in the Array. You can obviously expand these with more entries. See the documentation for more details

Upvotes: 0

Related Questions