How to specify local modules as npm package dependencies - node.js

I have an application which has the usual set of dependencies on third party modules (e.g. 'express') specified in the package.json file under dependencies. E.g.
"express" : "3.1.1"
I would like to structure my own code modularly and have a set of local (meaning on the file system I am currently in) modules be installed by the package.json. I know that I can install a local module by running:
npm install path/to/mymodule
However, I don't know how to make this happen via the package.json dependencies structure. Using the --save option in this command is simply putting "mymodule": "0.0.0" into my package.json (doesn't reference the filepath location). If i then remove the installed version from node_modules, and try to re-install from the package.json, it fails (because it looks for "mymodule" in the central registry, and doesn't look locally).
I'm sure the is a way of telling the "dependencies": {} structure that I want it to be installed from a file system path, but don't know how.
Anyone else had this problem?
Thanks.

npm install now supports this
npm install --save ../path/to/mymodule
For this to work mymodule must be configured as a module with its own package.json. See Creating NodeJS modules.
As of npm 2.0, local dependencies are supported natively. See danilopopeye's answer to a similar question. I've copied his response here as this question ranks very high in web search results.
This feature was implemented in the version 2.0.0 of npm. For example:
{
"name": "baz",
"dependencies": {
"bar": "file:../foo/bar"
}
}
Any of the following paths are also valid:
../foo/bar
~/foo/bar
./foo/bar
/foo/bar
syncing updates
Since npm install <folder> adds the package in the directory as a symlink in the current project any changes to the local package are automatically synced.

See: Local dependency in package.json
It looks like the answer is npm link: https://docs.npmjs.com/cli/link

I couldn't find a neat way in the end so I went for create a directory called local_modules and then added this bashscript to the package.json in scripts->preinstall
#!/bin/sh
for i in $(find ./local_modules -type d -maxdepth 1) ; do
packageJson="${i}/package.json"
if [ -f "${packageJson}" ]; then
echo "installing ${i}..."
npm install "${i}"
fi
done

After struggling much with the npm link command (suggested solution for developing local modules without publishing them to a registry or maintaining a separate copy in the node_modules folder), I built a small npm module to help with this issue.
The fix requires two easy steps.
First:
npm install lib-manager --save-dev
Second, add this to your package.json:
{
"name": "yourModuleName",
// ...
"scripts": {
"postinstall": "./node_modules/.bin/local-link"
}
}
More details at https://www.npmjs.com/package/lib-manager. Hope it helps someone.

You can just add to your package.json file in your project
"package-name" : "path/to/package"
and then run npm i in your project

At work we have a common library that is used by a few different projects all in a single repository. Originally we used the published (private) version (npm install --save rp-utils) but that lead to a lot of needless version updates as we developed. The library lives in a sister directory to the applications and we are able to use a relative path instead of a version. Instead of "rp-utils": "^1.3.34" in package.json it now is:
{
"dependencies": { ...
"rp-utils": "../rp-utils",
...
the rp-utils directory contains a publishable npm package

use install-local
I had issues with conflicting react installations from the local dependency.
I solved the error by using install-local npm package. This package does not create symlinks, which solved my issue.
Steps:
run npm i -g install-local
run npx install-local --save <local-path> inside the target repository to install the local dependency
Further reading: https://www.npmjs.com/package/install-local
The error I received, when trying to install the local package with npm install --save <local-directory>:
Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
You might have mismatching versions of React and the renderer (such as React DOM)
You might be breaking the Rules of Hooks
You might have more than one copy of React in the same app

If it's acceptible to simply publish your modules preinstalled in node_modules alongside your other files, you can do it like this:
// ./node_modules/foo/package.json
{
"name":"foo",
"version":"0.0.1",
"main":"index.js"
}
// ./package.json
...
"dependencies": {
"foo":"0.0.1",
"bar":"*"
}
// ./app.js
var foo = require('foo');
You may also want to store your module on git and tell your parent package.json to install the dependency from git: https://npmjs.org/doc/json.html#Git-URLs-as-Dependencies

Related

How to interactively test the executable of an NPM Node.js package during development without constantly reinstalling the package?

Consider a simple sample module like this one.
The package exposes a dummy function something like:
index.js
const uniq = require('uniq');
function myfunc() {
return uniq([1, 2, 2, 3]).join(' ');
}
exports.myfunc = myfunc;
Then, an executable uses the function:
browserify-hello-world
#!/usr/bin/env node
const browserify_hello_world = require('browserify-hello-world');
console.log(browserify_hello_world.myfunc());
The package publishes both the index.js and the executable with:
package.json
"bin": {
"browserify-hello-world": "browserify-hello-world"
},
"dependencies": {
"uniq": "^1.0.1"
},
My question is, how to test the browserify-hello-world executable interactively during development?
If I just clone the repository and do:
npm install
./browserify-hello-world
then it fails with:
Error: Cannot find module 'browserify-hello-world'
because as documented at https://docs.npmjs.com/cli/install install does not install the current package itself under node_modules.
I got it close to working perfectly with:
npm link
npm link browserify-hello-world
./browserify-hello-world
which runs correctly because:
npm link:
creates a symlink from the global package install: ~/.nvm/versions/node/v10.15.1/lib/node_modules/broserify-hello-world to the source directory
runs npm install on the source directory, which creates node_modules with all dependencies
npm link browserify-hello-world creates a symlink from node_modules/browserify-hello-world to the global directory ~/.nvm/versions/node/v10.15.1/lib/node_modules/broserify-hello-world
which works well because everything is done with symlinks, so that updates to the local package are immediately visible to the executable.
The only downside of this method, besides the inconvenience of typing all those commands after install, is that afterwards during development, if I need to install a new dependency into the project, e.g. with:
npm install vaca
then that breaks by symlinks for some reason: node_modules/broserify-hello-world is gone, and I am forced once again to do:
npm link
npm link browserify-hello-world
Note that doind just npm link browserify-hello-world above does not work and fails with:
Error: Cannot find module 'uniq'
because the dependency of our package, uniq, was also removed by npm install vaca.
Is there a way to avoid redoing the link process after every new install?
The npm-safe-install module might exist to address this problem: https://github.com/UD-UD/npm-safe-install but when I tried it with:
npm install -g npm-safe-install
npm-safe-install vaca
although it did keep my node_modules/borwserify-hello-world symlink, it still removed the dependency uniq. I asked about that at: https://github.com/UD-UD/npm-safe-install/issues/4
Related threads:
https://github.com/npm/cli/issues/533
https://stackoverflow.com/questions/59357144/npm-package-development-run-executable
https://github.com/npm/cli/issues/2380
https://github.com/npm/npm/issues/1573
https://github.com/npm/npm/pull/8501
Tested with: npm 6.12.0, Node.js 10.15.1 installed with NVM and npm-safe-install 1.0.0.
Your issue has been resolved and changes are published with some added features. Changes are available in npm-safe-install#1.1.0. Hope it resolves your issue.

Package that is linked with npm link doesn't update

I have two modules - my main project and a component library - where I want to link the lib to the main project. Both is working with webpack and react. So I did:
In comp-lib dir:
npm link
In project dir:
npm link comp-lib
The package is showing up in the node_modules folder, but when I work on the component library the changes are not reflected in main project. What am I missing out?
I couldn't really find something about this issue on Google and the npm link doc just says about the example: "Now, any changes to ~/projects/node-redis will be reflected in ~/projects/node-bloggy/node_modules/node-redis/."
Had similar problem with linked package - npm link dep was picking up old version of "dep".
Running npm link (again) in "dep" folder solved the problem. Theoretically it should be called only once, but for some reason it gets out of sync sometimes.
Thus in order to reliably update linked project, execute these steps after each change:
Rebuild linked project
run npm link
In host project run npm link dep
I don't remember exactly what problems I had and I am also not sure if all of that is necessary but for me it works great.
I added the following mini script to the package.json scripts list
"scripts": {
"clean": "if exist dist ( rd /S /Q dist)",
"updateLink": "npm run clean && tsc && npm rm my-lib -g && npm link"
}
(Replace "my-lib" with your package name)
Then simply call npm run updateLink whenever you change something in the lib.
What it does:
npm run clean deletes the dist folder. Useful if you have renamed files and the typecript compiler does not delete the old files but builds new ones in parallel
tsc to compile ts->js to the dist folder
npm rm my-lib -g && npm link to remove your lib and add it again from the global modules folder. I don't remember why I had to remove it first but it solved some problem I guess.
Make sure that the Node versions of the main project and dependency project match precisely.
If you use nvm to manage multiple projects on multiple node versions, the npm link will produce the symbolic link only in the node version that npm link was initiated from (i.e., the dependency project).
It might be that you bumped version on your component, and forgot to increase the version on your main project.
Then, any npm operation will download the version indicated in the package-lock.json: the outdated version, thus removing the link set up by npm link.
My issue was that my module/package in this case was exporting the build files. I didnt fix it because we export multiple files from multiple components but if you run into this issue, change main (and exports in my case) to whatever file exports your modules
"main": "./dist/shared-lib.umd.js",
"module": "./dist/shared-lib.es.js",
"exports": {
".": {
"import": "./dist/shared-lib.es.js",
"require": "./dist/shared-lib.umd.js"
},
"./style": "./dist/style.css"
}

`npm link --save` does not update dependencies on my package.json

I am using npm link package --save to create a local link to a globally installed package.
It correctly creates the link to the package (and would install it globally in case it were not already installed); but it fails to update the dependencies in package.json.
What I am missing here?
According the npm docs, npm link is not intended to change your package.json. It creates symbolic links on your file system for a package.
This allows you to still reference a module by name, but have it pull from your local filesystem:
cd ~/projects/node-redis # go into the package directory
npm link # creates global link
cd ~/projects/node-bloggy # go into some other package directory.
npm link redis # link-install the package
If you actually intend to insert a file path in your package.json, use npm install instead:
npm install --save /path/to/package
Then you'll see a reference in package.json file:
"dependencies": {
"local-package": "file:/path/to/package"
}
Though I highly recommend you use npm link instead, as it makes your package.json more portable. If you commit your changes with local file paths, it may become invalid on another system, or if you move around the files.
Update: Use npm-link-better
I created a little tool for this: npm-link-save
npm-link-save
npm-link with --save (or --saveDev) to save the linked dependency in your package.json.
You can also link multiple dependencies with this.
Install
npm i -g npm-link-save
Usage
npm-link-save express
# or
npm-links express
npm-links -D express // links in devDependencies
npm-links express morgan // multiple links
You're not missing anything, it's just not possible (yet).
There's an open feature request on the npm issue tracker (https://github.com/npm/npm/issues/1166).

How to install customer node.js binary module globally?

So I've made my own module with C++ and node-gyp. Things go fine after node-gyp configure build and I've got under build/Release everything I need.
Now, in my other project where I'm using this module, I don't want to add it like
var a = require('../../mylib/build/Release/mylib');
but instead
var a = require('mylib');
after defining dependencies in package.json. So how do I use npm or something else to achieve this?
You can add the entry point to your package to the main field in your package.json. This is what will be called when you do require('yourpackage').
See these links:
at end of section 8.1 http://book.mixu.net/node/ch8.html
under section main in https://npmjs.org/doc/json.html
sudo npm install --global /home/nhaa123/mylib/build/Release/mylib (if that is the folder containing your package.json) documentation: https://npmjs.org/doc/install.html
You don't want to install the module globally – project dependencies are meant to be installed locally (in the project's folder). The only thing you install globally are npm modules meant to be run from the command line.
Instead, just add the path to the folder containing your module (assuming it has its own package.json) to your project's package.json.
{
"name": "My Project",
"dependencies": {
"express": "3.1.x",
"mylib": "/home/me/mylib"
}
}

configure custom module for Node.js project

I create my Node project (npm init). In this project, i want to use Node REST Client from git hub https://github.com/dchester/node-rest-client.
update package.json with dependency:
...
"dependencies": {
"rest-client": "*"
},
...
create dir node_modules in my project
Copy the rest-client into the directory 'node_modules'
Run 'npm install' to install this dependency, however it doesn't.
What am i doing wrong? how to properly install dependency that is not from npm central repo?
Thank You
It looks like you'll have to do it manually for every module. However as the accepted answer in How to install a private NPM module without my own registry? by Mihai points out, npm knows about git:
npm install git://github.com/visionmedia/express.git
furthermore, besides going into the directory and typing npm install there it is possible to specify the path as argument:
npm install path/to/somedir
There's another useful answer in How to install a private NPM module without my own registry? where you can see you can also specify a url pointing to a tarball. I suggest you take a look at that thread.

Resources