A comparison of npm link
and npm pack
to test your linked Npm package after an update
Often we will find the need to update/change some Npm packages that we develop from time to time. This is especially true when some of our projects depend on these packages, e.g. a general project B depending on a reusable component library project A (your to be updated npm package).
Maybe we need to overwrite some styles in repo A, or to add a few more elements to make it more compatible. Anyway, we have made the changes, and tested locally in repo A, so what’s the next step?
An intuitive approach is to go ahead and just publish the change to npmjs.org, then update it in your project B.
This might not be a good idea. You better wish it works as expected, otherwise you have to go back to make changes in project A again and go through the same process to publish it and pull it…
Lengthy process and time inefficient… not to mention this left your package with unsuccessful versioning that doesn’t mean anything.
Obviously you only want to push to npmjs.org only when you are confident about the change you made.
So what are the alternatives?
Npm Link
Npm link, as it name suggests, links two projects, so the changes made to project B will be available to project A.
Behind the scenes it’s done by symbolic links:
- It first points a link from project B to global Npm node_modules directory, and,
- Then points a link from the global directory to project A’s node module directory.
How does this work?
So in your project A (npm package), run:
//root directory of project A
npm link====>you will see something like:/Users/elfi/.nvm/versions/node/v10.19.0/lib/node_modules/@project_A -> /Users/elfi/project_A
Now go to your project B and run:
//root directory of project B
npm link project_A====>you will see something like:/Users/elfi/project_B/node_modules/@project_A -> /Users/elfi/.nvm/versions/node/v10.19.0/lib/node_modules/@project_A
Now you can just test run project A in project B as usual. Make changes back in project A if needed and the change will be immediately reflected in project B!
Seems smooth, right?
Well not always. While this is an ideal approach, the option also comes with a few concerns:
- Since it doesn’t go through the normal publishing process, when a package becomes a tar archive with configuration about how it should be packed, it leaves uncleared doubt about the packaging configuration.
- A more common and serious issue is the discrepancy of module resolution in file trees, as a symlink has its own file tree. So when e.g. project A in project B loads
React
, it checks its own file tree for anode_modules/react
, not the one that project B loads. So you will see errors likeCan’t resolve ‘react’ in ‘/Users/.nvm/versions/node/v10.19.0/lib/node_modules/project-B/dist’
A better alternative?
Npm Pack
This command will create a .tgz
tar ball file that is the same file if you go through the publishing process and be uploaded to npmjs.org.
How you do this?
//root directory of project A
npm pack====>you will see a new file added to the directory like:project_A-0.0.0.tgz
In project B root directory, you need to change the package.json file the location of package A to something like:
//package.json of project B"dependencies": {
"@project_A": "file:[path to project A]/project_A-0.0.0.tgz
....
}
Then don’t forget to run npm install
afterwards. This would unpack the tar ball file in project B’s node_modules.
Be noted that since npm pack
goes through a publishing process and packaging the original project A, any new change you make after run the npm pack
will not be reflected in project B. In order to have the new changes, you need to do npm pack
and npm install
again — just like a mini version of npm publish.
But I prefer it to npm link
, since it avoid hassle of syncing the file trees and gives me confidence by running through similar process of npm publish
without the worry to over bumping my package versions.
Well, in the end, when you are happy about your test result, just :
Run npm version on Project A using semantic versioningRun npm publish Go to npmjs.org to check the new version is been publishedUpdate the package.json file in Project BRun npm install in Project B to pull the new version of Project ARun all tests againGood to go!