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

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).

Related

What is the optional version used for in `npm link <pkg>[#<version>]`?

My understanding of what npm link and npm link <pkg> do is basically as described in the documentation:
Package linking is a two-step process.
First, npm link in a package folder will create a symlink in the global folder {prefix}/lib/node_modules/ that links to the package where the npm link command was executed. It will also link any bins in the package to {prefix}/bin/{name}. Note that npm link uses the global prefix (see npm prefix -g for its value).
Next, in some other location, npm link package-name will create a symbolic link from globally-installed package-name to node_modules/ of the current folder.
So I am puzzled by what it would mean to specify the version as well in the second step of package linking (for example, npm link my-package#3.1.4). Isn't the version of the linked package entirely determined by the contents of the linked directory? I don't think the documentation for npm link explains this.
From what i understand , npm link also does install any of missing dependencies.
It ensures all latest versions of dependencies are linked to global folder and non latest are installed on spot , but with its deep dependencies located in its own node_modules . Installs or updates given project dependencies. If dependency version is not specified then one from package.json or latest is assumed. So if the dependency version is not specified , It will be entirely determined by the contents of the linked directory.
There is two different behaviour to know with the link command.
The first one, is when you want to test a local package, then in fact
running npm link ../../my-package will be sufficient and will determined the version from the package.json file located in the package.
The second one, correspond to a case where you would like to tests a specific version of a remote package without impacting your package.json.
let say, you want to install moment#2.29.2 without updating your package.json then you can run
npm link moment#2.29.2
it will install the package globally and then create a symlink in your node_modules for that package.

NodeJS - installing local module

npm i /path/to/module/folder will create a dependency for your project on local module
it creates a link to that folder as the docs says
• npm install < folder >:
Install the package in the directory as a symlink in the current
project. Its dependencies will be installed before it's linked. If
sits inside the root of your project, its dependencies may be
hoisted to the toplevel node_modules as they would for other types of
dependencies.
there is a flag --no-bin-links that prevent creating links only to bin's files
What i want is : is there a way to be able to make dependency on that local module by copy it not link it, so i can make changes and won't reflect on other projects until i manually npm update my-local-module it
PS : from what i searched that was the default behavior of npm install <folder> but they changed it.
You can create a tarball from your-local-module with npm-pack and then install it offline using npm-install:
npm install <tarball file>
Install a package that is sitting on the filesystem. Note: if you just want to link a dev directory into your npm root, you can do this more easily by using npm link. The filename must use .tar, .tar.gz, or .tgz as the extension.

npm link does not care for "files" in package.json or .npmignore

My goal is to specify what files will be included in my node module before publishing it and be able to test the installation locally. Using the "files" in the package.json works in that if I publish my package and install it, then I get only what was specified in "files".
This isn't the case when I use npm link. Be it "files" in package.json or an .npmignore, npm link always seems to give me every file. How can I test my modules installation locally like this?
Ex:
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 ~/projects/node-redis had "files: [lib]" in its package.json, you would expect only lib to show up in ~/projects/node-bloggy after running "npm link redis", but this is not the case.
Aside:
I love node and npm, but if you look at what is in your node modules, there's so many extraneous files like PNGs used in the readme. Modules are ridiculously huge because of this.
UPDATE:
npm install <path>
seems to respect "files" in package.json according to an answer here and others on stackoverflow. I can't speak for other systems but with npm v 6.9.0 on Fedora Linux, this doesn't work as all files are still copied.
Example:
If you need a published module to test this scenario with, I recently published num2cheque which has no dependencies. You will see that if you install it from the npm registry with
npm install num2cheque
you do not receive the test directory which I have locally because in the package.json I specify
"files": [lib]
Add a test directory to your local install then try to use npm link or npm install with a path and you will see that test directory is now included. Hope that illustrates the issue.
Workaround: npm install a GIT repo URL
You may want to install a package from a GIT repo, eg
npm install https://github.com/AndreasPizsa/parse-decimal-number.git
This is an actual npm install which respects the files entry, even if the package has not yet been published to an npm repository.
Background
npm link does not copy, it creates a link
npm link does not actually install the package by copying it into the target folder.
Instead it creates a symbolic link to the source folder, which is why you’re seeing all the files that are in the source folder ("node-redis"), not just those specified in files.
This behavior is documented in the npm link documentation:
First, npm link in a package folder will create a symlink in the
global folder {prefix}/lib/node_modules/ that links to the
package where the npm link command was executed. (see npm-config for
the value of prefix). It will also link any bins in the package to
{prefix}/bin/{name}.
Next, in some other location, npm link package-name will create a
symbolic link from globally-installed package-name to node_modules/ of
the current folder.
https://docs.npmjs.com/cli/link.html
"What’s a Symlink?" you may ask:
a symbolic link (also symlink or soft link) is a term for any file that contains a reference to another file or directory in the form of an absolute or relative path and that affects pathname resolution.
https://en.wikipedia.org/wiki/Symbolic_link
If your concern is the use of space on your hard disk, worry not - nothing is copied or duplicated, only linked (just like linking to Wikipedia doesn’t duplicate it, it actually saves space)
... and so does running npm install locally
npm install with the path to the package will also create a symbolic link to the package in question. A helpful scenario for this can be a module that’s still under development.
cd ~/projects/node-bloggy
npm install ~/projects/node-redis
This will create a symbolic link under node_modules in your node-bloggy project.

npm link, without linking devDependencies

It appears that when I run npm link, it will install the project globally, and it seems to install devDependencies with it.
Is there a way to run npm link without devDependencies, perhaps with the --only=production flag?
In npm#4.x or lower
When you run npm link in other_module then you will get both dependencies and devDependencies symlinked.
The --production flag doesn't change anything, still creates a symlink to the whole directory
In npm#5.1.0
They fixed it!
If you remove node_modules and then do npm link --only=production, it runs an install before symlinking, and therefore devDependencies folder are indeed excluded.
This is currently not possible with npm link. The problem is, if you install only prod dependencies in that dependency, you're able to link it, but you're not able to develop on that dependency anymore (since missing devDependencies). And vice-versa: If you install devDependencies, you can't link anymore.
The solution: A package called npm-local-development at https://github.com/marcj/npm-local-development
It basically does the same thing as npm link, but works around the devDependency limitation by setting up a file watcher and syncs file changes automatically in the background, excluding all devDependencies/peerDependencies.
You install npm-local-development: npm i -g npm-local-development
You create file called .links.json in your root package.
You write every package name with its local relative folder path into it like so
{
"#shared/core": "../../my-library-repo/packages/core"
}
Open a console and run npm-local-development in that root package. Let it run in the background.
Disclaimer: I'm the author of this free open-source project.
A workaround I use is npm pack then point to the packed file in the example

How to specify local modules as npm package dependencies

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

Resources