Properly configure NPM package which depends on local packages
Asked Answered
O

4

6

I have this three local npm packages: C:\projects\A, C:\projects\B and C:\projects\main. Main is React app which is built with Webpack. Main depends on A and B, also A depends on B. We have our own "global" package manager which guarantees that packages will be located in same parent folder.

I want to suit these:

  1. Node's (and webpack's) require will resolve local packages

  2. I don't need to npm install in Main every time I change A or B

I did this in Main's package.json:

....
"dependencies": {
    "A": "file:../A",
    "B": "file:../B",
    "react": ...
    .........

But ran into strange problem: npm doesn't install all packages in A's and B's node_modules, so Webpack build fails. And I need to run npm install each time.

I googled and found linklocal, which replaces all local packages as symlinks. But ran into another problem:

linklocal does not install dependencies of linked dependencies, as such you typically end up installing dependencies of linked dependencies twice: once during npm install, then again after linklocal

So I ran linklocal and then npm install again in postinstall script. But npm@3 didn't do anything with symlinked folders:

npm WARN update-linked node_modules/A needs updating to 1.0.0 from 1.0.0 but we can't, as it's a symlink

Then I decided to modify postinstall to go to every symlinked module and run npm install from there. And it worked at first sight: installing ran well, as well as webpack bunding. But Webpack started bundling two copies of React (which is prohibited).

How to configure my packages properly?

Omor answered 20/10, 2016 at 18:12 Comment(0)
A
1

I personally use npm pack to package my dependencies and then install them in my main project using `npm install ./path/to/pack/result.tgz as detailed here

It avoid to publish every changes made to A and B but does not prevent you to

npm install in Main every time I change A or B

Angelenaangeleno answered 25/10, 2016 at 10:11 Comment(0)
R
1

In package A and package B you can have a preinstall script that execute webpack. This should resolve all the dependencies.
On your main package you should link to the dist(build) folder of package A and B.
Also check this library wml, it can help you to keep in sync your local dependencies.

package.json:

"scripts": { "preinstall": "webpack" }

Raposa answered 30/10, 2016 at 20:41 Comment(0)
M
1

If you do not need to build Main in other machines you could just do something like that in your project/Main

let C = require('C:\projects\A\index.js')

Or you could have a branch with

require('C:\projects\A\index.js')

And another with:

require('C')
Michalmichalak answered 31/10, 2016 at 12:42 Comment(0)
O
0

You can use npm link locally to maintain symlinks to your local development versions..

So, reset the package.json in Main to point to wherever the published packages will actually live:

 "dependencies": {
    "A": "<PUBLISHED_PACKAGE_REPO>",
    "B": "<PUBLISHED_PACKAGE_LOCATION>",
    "react": ...

This ensures that your project will always build on CI / other machines etc.

Then, navigate to your "project A" directory and create a link:

cd projects\A
npm link

This will create an npm specific symlink that points to C:\projects\A.

Then do the same for the B project:

cd projects\B
npm link

You now have both project links created, and just need to actually link them to your Main project:

cd projects\Main
npm link A
npm link B

If A also depends on B you simply need to link those projects too:

cd projects\A
npm link B

When you're finished developing and want to use whatever is specified in package.json just unlink and install:

cd projects\Main
npm unlink A
npm unlink B
npm install
Oid answered 24/10, 2016 at 10:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.