Installing a local module using npm?
Asked Answered
A

11

673

I have a downloaded module repo, I want to install it locally, not globally in another directory?

What is an easy way to do this?

Arawakan answered 11/11, 2011 at 1:53 Comment(0)
A
750

you just provide one <folder> argument to npm install, argument should point toward the local folder instead of the package name:

npm install /path
Arawakan answered 11/11, 2011 at 2:35 Comment(19)
Unlike link, this uses .npmignore.Polythene
@bithavoc At least as of npm 5, installing a folder now creates a symlink, not a copy. See docs.npmjs.com/cli/installHarridan
I tried to use this way, but my module can't find it's peerDependencies.Headwaiter
it's nice to rm -rf node_modules before and npm install after you run the answer's script.Checklist
npm link creates 2 symlinks, 1 in the global scope and 1 in the importing package. npm install /path creates just 1 symlink in the importing packageAdemption
i'm not able to do this without an uncaught exception in node v8.10.0Rumania
@FrankTan Yes, but how to get the old behavior? I want the copy!Jennette
@Michael, unfortunately, as far as I can tell from the docs, you can't get the old behavior anymore.Harridan
This is a must for node addons, which require a rebuild in order to be used as a package. npm link will not do this.Gaffney
@Jennette There's a solution for that. Put the dependency modules in project root folder. Define your dependencies in package.json with the usual 'file:' prefix. Do npm i This will create a symlink in project's node_modules as well as its dependencies may be hoisted to the toplevel node_modules as they would for other types of dependencies. My npm version is v6.14.4 . After spending couple of hours on how to fix this, found this solution here : (atmos.washington.edu/~nbren12/reports/journal/…)Clingstone
it throws an error for me. @typescript-eslint/[email protected] requires a peer of eslint@^5.0.0 but none is installed. You must install peer dependencies yourself.Savagery
unlike link this works for global install so you can test binary from you node module locally.Plugugly
@FrankTan Someone said that you can do the copy by packing it first then install from the pack → https://mcmap.net/q/64858/-how-to-force-npm-not-to-create-symbolic-link-to-local-packageMckeever
Is this meant to work on windows? Because it doesn't for me (npm 7.5.1)Spermatic
I had package x already installed from elsewhere. npm install ../x --save-dev didn't create a symlink without npm uninstall x first.Dogmatics
Worked effortlessly for me, after spending quite some time trying to get npm link to work first.Drumfire
I am on npm 9.3.1, and npm install ./path --save copies the whole folder rather thn creating symlinks. thts strange. I want symlinksBartels
@Dogmatics i dont have the package installed, neither i have tht package in global modules. still npm install copies the whole folder rathen thn creating symlink. im on npm 9.3.1Bartels
npm link didn't work for Hubot because Hubot loads scripts dynamically, meaning the imports were expecting the modules to be located in the local/path/Hubot/node-modules folder, but not finding it there because the "parent" app was in a completely different folder. I ended up npm packing the local hubot and npm i hubot.tgz instead.Wahl
Y
597

From the npm-link documentation:

In the local module directory:

$ cd ./package-dir
$ npm link

In the directory of the project to use the module:

$ cd ./project-dir
$ npm link package-name

Or in one go using relative paths:

$ cd ./project-dir
$ npm link ../package-dir

This is equivalent to using two commands above under the hood.

Yamamoto answered 13/9, 2013 at 4:49 Comment(13)
This is the only sane looking approach I've seen so far - why npm has to be so obscure/obtuse w. regards to creating a local package, installing it and then using it, I don't know... link works, (and its great), but the terminology is rather confusing.Haile
@Rich Apodaca, thanks for the doc link. It doesn't mention undoing the process. It looks like all it does is create symlinks, so I can remove those as normal?Katharina
@TylerCollier npm unlink appears to be the mirror-image operation https://mcmap.net/q/64859/-how-do-i-uninstall-a-package-installed-using-npm-linkYamamoto
Just a note, if you use Angular2 (or maybe other applications?), there is some buzz around npm linking being root cause of specific kind of issue. Example here and hereLarcenous
However keep in mind that npm link will create a second instance of external dependencies. So if you have a package A need B and C, B need C. linking B will cause application A to have two instances of C.Symposiac
I wrote a TypeScript typings module for an existing JS project that I want to link locally. However, when I cd to the project directory and run the command npm link @types/promise-retry, it returns a 404 Not Found error, and the console log shows that it was trying to access the npm registry: https://registry.npmjs.org/@types%2fpromise-retry. Why is this bothering to connect to the registry at all, when it should be a completely local process?Trichromatic
It looks like npm 5 uses symbolic links by deafult when you npm install /pathAssets
Note that this does not work for packages that have a prepublish step (e.g. if they need translating via babel before they can be used as a library). You'll need to use npm install (or run npm run prepublish manually every time you change the library) for such packages.Doviedow
@Haile probably their business is to store package hence local package is push on the secondary zone with very less considerationMotherinlaw
Can someone explain to me why I have to occasionally do this again? I am using Ionic Framework, when I sync my plugins, sometimes it will defer to the public version instead of using my local version and I have to re-link it -- is this tied to rebooting?Gerigerianna
If you are in a yarn workspaces repo you can use yarn link & yarn link package-nameTrumpery
If both the host package and the local package use eslint, you'll run into github.com/vuejs/vue-cli/issues/1494#issuecomment-498144990Esquiline
I am on npm 9.3.1 and npm install --save ./path copies the folder to node_module rather then symlinking it. i want to symlink so it remains in syncBartels
C
211

Since asked and answered by the same person, I'll add a npm link as an alternative.

from docs:

This is handy for installing your own stuff, so that you can work on it and test it iteratively without having to continually rebuild.

cd ~/projects/node-bloggy  # go into the dir of your main project
npm link ../node-redis     # link the dir of your dependency

[Edit] As of NPM 2.0, you can declare local dependencies in package.json

"dependencies": {
    "bar": "file:../foo/bar"
  }
Coquina answered 28/6, 2013 at 19:10 Comment(7)
It might not be original intent of the question, but it's probably what most people who find this through google want.Polivy
This answer seems incomplete, you need to run npm link against the folder once (to create a global symlink) and then run npm link package-name within the folder of the project (to use the global symlink in your project). The answer below is the right answer.Gensler
@ThomasPotaire both answers are correct. If you look at the npm link documentation, it presents both methods, with this relative directory approach as a shorthand.Zhdanov
The second method (using the file: approach) allowed for my app and the local module to share a dependency. My test of npm link resulted in a duplicate dependency, which breaks things if the dependency needs to be used as a singleton.Steelworks
I had a local package(say package1), package2 has a dependency mentioned with relative path of package1. npm i not installing the package when relative path starts with "file:../../package1" , working when it is ''../../package1", does adding file in the begining means anything else?Monteria
a caveat: using npm link ../my-module doesnt enforce type checking if my-module is a typescript module.Blanchard
To add the local dependency without editing the package.json file manually you can run npm install with the local path: npm install ../foo/bar --save updates the packages.json file the same way.Gree
P
149

npm pack + package.json

This is what worked for me:

STEP 1: In module project, execute npm pack:

This will build a <package-name>-<version>.tar.gz file.

STEP 2: Move the file to the consumer project

Ideally you can put all such files in a tmp folder in your consumer-project root:

STEP 3: Refer it in your package.json:

"dependencies": {
  "my-package": "file:/./tmp/my-package-1.3.3.tar.gz"
}

STEP 4: Install the packages:

npm install or npm i or yarn

Now, your package would be available in your consumer-project's node_modules folder.

Good Luck...

Phonon answered 16/1, 2020 at 9:37 Comment(6)
I forgot to build my package before packing, so npm run build before.Metry
This is the best reply because it also install sub-dependencies!Variance
Yeah, if you use file:<package_root_path> (not the path of the pack file) in the dependencies to install the package from your local file system. The local package will not be copied to your node_modules but instead it is linked into node_modules. With npm i, sub-dependencies can be installed automatically but the sub-dependencies cannot be shared with other packages. In this situation, the instanceof keyword may not work as expected if you want to use the keyword for the objects from the local project. So, I think npm pack + package.json is a reasonable solution.Thereinto
PSA: Yarn struggles with this method due to overzealous caching. See yarnpkg/yarn#2165. I had to migrate my project (back) from Yarn to NPM for this.Agnes
Pls add one more step to it at the beginning. Otherwise pack cmd wont work npm run buildBlizzard
For Windows don't forget to use backslash in paths. Like: file:.tmp\\pkg-name-lib-0.0.6.tgzSpirant
C
23

Neither of these approaches (npm link or package.json file dependency) work if the local module has peer dependencies that you only want to install in your project's scope.

For example:

/local/mymodule/package.json

"name": "mymodule",
"peerDependencies":
{
  "foo": "^2.5"
}

/dev/myproject/package.json

"dependencies":
{
  "mymodule": "file:/local/mymodule",
  "foo": "^2.5"
}

In this scenario, npm sets up myproject's node_modules/ like this:

/dev/myproject/node_modules/
 ↳ foo/
 ↳ mymodule -> /local/mymodule

When node loads mymodule and it does require('foo'), node resolves the mymodule symlink, and then only looks in /local/mymodule/node_modules/ (and its ancestors) for foo, which it doen't find. Instead, we want node to look in /local/myproject/node_modules/, since that's where were running our project from, and where foo is installed.

So, we either need a way to tell node to not resolve this symlink when looking for foo, or we need a way to tell npm to install a copy of mymodule when the file dependency syntax is used in package.json. I haven't found a way to do either, unfortunately :(

Commentative answered 8/11, 2018 at 20:12 Comment(3)
I found a workaround, which is to set NODE_PATH to point to the node_modules/ where foo is installed. So for the above case, it would be this: NODE_PATH=/dev/myproject/node_modules/ That allows mymodule to find foo.Commentative
There's a solution for. Put the dependency modules in project root folder. Define your dependencies in package.json with the usual 'file:' prefix. Do npm i This will create a symlink in project's node_modules as well as its dependencies may be hoisted to the toplevel node_modules as they would for other types of dependencies. My npm version is v6.14.4 . After spending couple of hours on how to fix this, found this solution here : (atmos.washington.edu/~nbren12/reports/journal/…) . Thanks nbren12.Clingstone
I was having the same trouble. I found this answer: #50807829, this solves my problem with peer dependencies and local libraries.Silk
L
17

Missing the main property?

As previous people have answered npm i --save ../location-of-your-packages-root-directory. The ../location-of-your-packages-root-directory however must have two things in order for it to work.

  1. package.json in that directory pointed towards

  2. main property in the package.json must be set and working i.g. "main": "src/index.js", if the entry file for ../location-of-your-packages-root-directory is ../location-of-your-packages-root-directory/src/index.js

Lab answered 13/9, 2019 at 13:29 Comment(2)
npm --save? You mean npm i --save? (Which is now equivalent to npm i)Cenozoic
When working with nx workspaces this is what solved the issue of local modules not being found.Celestinacelestine
L
15

So I had a lot of problems with all of the solutions mentioned so far...

I have a local package that I want to always reference (rather than npm link) because it won't be used outside of this project (for now) and also won't be uploaded to an npm repository for wide use as of yet.

I also need it to work on Windows AND Unix, so sym-links aren't ideal.

Pointing to the tar.gz result of (npm package) works for the dependent npm package folder, however this causes issues with the npm cache if you want to update the package. It doesn't always pull in the new one from the referenced npm package when you update it, even if you blow away node_modules and re-do your npm-install for your main project.

so.. This is what worked well for me!

Main Project's Package.json File Snippet:

  "name": "main-project-name",
  "version": "0.0.0",
  "scripts": {
    "ng": "ng",
    ...
    "preinstall": "cd ../some-npm-package-angular && npm install && npm run build"
  },
  "private": true,
  "dependencies": {
    ...
    "@com/some-npm-package-angular": "file:../some-npm-package-angular/dist",
    ...
  }

This achieves 3 things:

  • Avoids the common error (at least with angular npm projects) "index.ts is not part of the compilation." - as it points to the built (dist) folder.
  • Adds a preinstall step to build the referenced npm client package to make sure the dist folder of our dependent package is built.
  • Avoids issues where referencing a tar.gz file locally may be cached by npm and not updated in the main project without lots of cleaning/troubleshooting/re-building/re-installing.

I hope this is clear, and helps someone out.

The tar.gz approach also sort of works..

npm install (file path) also sort of works.

This was all based off of a generated client from an openapi spec that we wanted to keep in a separate location (rather than using copy-pasta for individual files)

====== UPDATE: ======

There are additional errors with a regular development flow with the above solution, as npm's versioning scheme with local files is absolutely terrible. If your dependent package changes frequently, this whole scheme breaks because npm will cache your last version of the project and then blow up when the SHA hash doesn't match anymore with what was saved in your package-lock.json file, among other issues.

As a result, I recommend using the *.tgz approach with a version update for each change. This works by doing three things.

First:

For your dependent package, use the npm library "ng-packagr". This is automatically added to auto-generated client packages created by the angular-typescript code generator for OpenAPI 3.0.

As a result the project that I'm referencing has a "scripts" section within package.json that looks like this:

  "scripts": {
    "build": "ng-packagr -p ng-package.json",
    "package": "npm install && npm run build && cd dist && npm pack"
  },

And the project referencing this other project adds a pre-install step to make sure the dependent project is up to date and rebuilt before building itself:

  "scripts": {
    "preinstall": "npm run clean && cd ../some-npm-package-angular && npm run package"
  },

Second

Reference the built tgz npm package from your main project!

  "dependencies": {
    "@com/some-npm-package-angular": "file:../some-npm-package-angular/dist/some-npm-package-angular-<packageVersion>.tgz",
    ...
  }

Third

Update the dependent package's version EVERY TIME you update the dependent package. You'll also have to update the version in the main project.

If you do not do this, NPM will choke and use a cached version and explode when the SHA hash doesn't match. NPM versions file-based packages based on the filename changing. It won't check the package itself for an updated version in package.json, and the NPM team stated that they will not fix this, but people keep raising the issue: https://github.com/microsoft/WSL/issues/348

for now, just update the:

"version": "1.0.0-build5",

In the dependent package's package.json file, then update your reference to it in the main project to reference the new filename, ex:

"dependencies": {
       "@com/some-npm-package-angular": "file:../some-npm-package-angular/dist/some-npm-package-angular-1.0.0-build5.tgz",
        ...
}

You get used to it. Just update the two package.json files - version then the ref to the new filename.

Hope that helps someone...

Langille answered 15/7, 2020 at 17:58 Comment(0)
M
5

I came across different solution than above while installing custom build package for CKEditor5.

So I uploaded package to app root directory, than:

npm add file:./ckeditor5

In my package.json package is listed as a file:

"ckeditor5-custom-build": "file:ckeditor5",

I think this answer could be relevant to the topic on how to add local package.

Morbid answered 9/5, 2022 at 10:43 Comment(1)
Hi Simon Klimek. This solution works for me to map to a local NPM module. But If i do any changes to the module, i have to re-install it again using npm add file:./ckeditor5 command. Is there any way to overcome this problem so that whenever i do any changes locally, they should be automatically reflected without re installing?Series
S
3

As explained in the accepted answer by @fancy, you can use this command:

npm install ...<path_to_your_local_package>

to add your local packages.

In the package.json of your project it will create an entry like:

"dependencies": {
    ...
    "your_package_name": "file:...<path_to_your_local_package>"
    ...
}

If the package you're including is within the project root, then it will do an installation of all the dependencies of your included local package. Otherwise, i.e. if it's outside your project root, it will simply create a symbolic link (as @frank-tan pointed out), in which case, if for some reason you've deleted the node_modules directory in your project or you need to do a fresh reinstall you must run:

npm install --install-links

The command line option install-links ensures that all dependencies of the local packages get installed automatically. This will come in handy if, for example, you're using Jenkins and need to deploy a large project with many custom-developed nested dependencies.

See official npm-install documentation for more detail: https://docs.npmjs.com/cli/v9/commands/npm-install

Secularity answered 14/3, 2023 at 5:33 Comment(0)
B
1

For installing local module / package, that not yet on npm or you are developing an npm package and want to test it locally before publishing it. You can try this -

npm i yalc -g

Go to the module/package folder then -

yalc publish

Your packakge is ready to use, now go the project you want to install it -

yalc add <Your package name>

Package will be installed to you project. If you want to remove it -

yalc remove <Your package name>
Braiding answered 10/12, 2022 at 9:33 Comment(0)
G
-1

For more recent versions of npm (I'm using 8.1.3 under macOS Big Sur), the sequence of commands is even easier...

cd /path-where-your-local-project-is/
npm init

This will ask you for some data related to your project and properly initialises your project.json file.

Once that is done, you can install additional modules with:

cd /path-where-your-local-project-is/
npm install --save-dev some-npm-module .

That's all you need!

Note: I believe that the trailing dot is not necessary if you're inside the project directory, but I also think that it doesn't hurt to add it :-)

(I wonder why the official docs still don't explain this...)

Greeley answered 9/2, 2022 at 17:41 Comment(4)
I did a few tests, and, indeed, it seems to work without the dot for designating the current directory, when you're already inside it.Greeley
How do you install local modules with this? This answer doesn't make sense to me.Agnes
This doesn't install a local module at allLayman
Shouldn't the second directory be something of the form cd /path-where-you-want-to-install-your-local-project? Then, install it as you describe.Heliostat

© 2022 - 2024 — McMap. All rights reserved.