npm 1.0 is in release candidate mode. Go get it!
Local-npm is a Node server that acts as a local npm registry. It serves modules, caches them, and updates them whenever they change. Basically it's a local mirror, but without having to replicate the entire npm registry. This allows your npm install commands to (mostly) work offline. Sep 18, 2018 - What I Wanted to Do I would like to install a local package and run myfunction defined in the local package. I expect the function to print.
More than anything else, the driving force behind the npm 1.0 rearchitecture was the desire to simplify what a package installation directory structure looks like.
In npm 0.x, there was a command called
bundle
that a lot of people liked. bundle
let you install your dependencies locally in your project, but even still, it was basically a hack that never really worked very reliably.Also, there was that activation/deactivation thing. That’s confusing.
Two paths
In npm 1.0, there are two ways to install things:
- globally —- This drops modules in
{prefix}/lib/node_modules
, and puts executable files in{prefix}/bin
, where{prefix}
is usually something like/usr/local
. It also installs man pages in{prefix}/share/man
, if they’re supplied. - locally —- This installs your package in the current working directory. Node modules go in
./node_modules
, executables go in./node_modules/.bin/
, and man pages aren’t installed at all.
Which to choose
Whether to install a package globally or locally depends on the
global
config, which is aliased to the -g
command line switch.Just like how global variables are kind of gross, but also necessary in some cases, global packages are important, but best avoided if not needed.
In general, the rule of thumb is:
- If you’re installing something that you want to use in your program, using
require('whatever')
, then install it locally, at the root of your project. - If you’re installing something that you want to use in your shell, on the command line or something, install it globally, so that its binaries end up in your
PATH
environment variable.
When you can't choose
Of course, there are some cases where you want to do both. Coffee-script and Express both are good examples of apps that have a command line interface, as well as a library. In those cases, you can do one of the following:
- Install it in both places. Seriously, are you that short on disk space? It’s fine, really. They’re tiny JavaScript programs.
- Install it globally, and then
npm link coffee-script
ornpm link express
(if you’re on a platform that supports symbolic links.) Then you only need to update the global copy to update all the symlinks as well.
The first option is the best in my opinion. Simple, clear, explicit. The second is really handy if you are going to re-use the same library in a bunch of different projects. (More on
npm link
in a future installment.)You can probably think of other ways to do it by messing with environment variables. But I don’t recommend those ways. Go with the grain.
Slight exception: It’s not always the cwd.
Let’s say you do something like this:
In this case, npm will install
redis
into ~/projects/foo/node_modules/redis
. Sort of like how git will work anywhere within a git repository, npm will work anywhere within a package, defined by having a node_modules
folder.Test runners and stuff
If your package's
scripts.test
command uses a command-line program installed by one of your dependencies, not to worry. npm makes ./node_modules/.bin
the first entry in the PATH
environment variable when running any lifecycle scripts, so this will work fine, even if your program is not globally installed:January 17, 2016Nicolas Girault5 min read
Remember the last time you ran the
npm install
command, and you had time to grab three coffees, learn Russian and read Dostoievski before you could do anything productive?During the installation of a node app, the
npm install
step is doubtless the most time consuming one. Assuming your network is somehow slow it can be endless... It's inefficient because this command will download packages that you might have already downloaded tens of times for this app or another.The npm cache already saves approximately 30% of the installation time: when packages are in the npm cache, the initial metadata request sends the cached ETag for the package, and in the vast majority of cases, the registry will return a 304 and the package tarball won't need to be downloaded again. However, the number of HTTP requests is still the same so there is some time that can still be saved.
Although I do recognize the social gain of taking a coffee break with your teammates, I will tell you how to avoid taking a coffee each time you run
npm install
thanks to Nexus!Nexus
Nexus is a a repository manager developed by Sonatype. In other words it can simulate the npm registry on your host. It supports other repositories such as RPM, Maven, Docker Registry...
Install Nexus
The simplest way to use Nexus is to pull the official Docker image.
It can take some time (2-3 minutes) for the service to launch in a new container. You can tail the log to determine once Nexus is ready:
Otherwise following the official installation guide would take approximately 30 minutes.
Here are the main steps for ubuntu 15.10 (easily adaptable for other OS):
Then you can access the web interface here: http://localhost:8081/
Set up the Nexus server
The next steps are based on Nexus guide for npm.
this video shows how to do the steps below!
- Log in as 'admin' with the default password 'admin123' (you should change it as explained in the post install checklist)
- Create a npmjs proxy:
- Create a new repository: Parameters > Repositories > Create repository
- Select 'npm proxy' (the 'npm hosted' allow to store private packages and is not in the scope of this article)
- Fill the form (name: 'npm-proxy', remote storage: 'https://registry.npmjs.org' check 'Use the Nexus truststore', select 'default' for the blobstore) and click on 'create repository'
- Create a repository group
- Then create a new repository 'npm group'
- I named it 'npm' and fill the simple form including the repository you just created
Tell npm to hit the Nexus repository
In
~/.npmrc
file, replace the line by:Now try to install a package. Then you'll find it in the list of components in the nexus npm repository. You can disconnect from the Internet, remove your node modules and re-install. Voilà!
Unfortunately the official docker image does not provide the version 3 of Nexus so you cannot browse the npm packages.
Bonus: configure your local repository as a service
To avoid starting the nexus server each time you reboot, you can configure nexus as a service that will start during the boot phase.
If you're using a docker image, you'll just have to use the
--restart=always
option in your run
commands.Otherwise, the Nexus guide explain how to do it but it is not simple and the doc is not up to date (this is actually the reason why I started using Docker).
Alternatives
There are alternatives to Nexus to cache npm packages. Here are two interesting ones:
- npm-cache wraps npm and includes cache utilities but it breaks the standard way to install node apps. Who expects to run
npm-cache install
instead ofnpm install
to install a node app? - npm-proxy-cache is a simple node app doing the same job as Nexus but I don't like the fact it's not a formal registry (have you used it? Your feedback would be great).
Conclusion
Using Nexus saves approximately 30% of the installation time of packages already in the npm cache.
This is one of the many use cases of Nexus. You can easily set up this tool to store private packages and thus improve your installation process. This tool can be useful for companies with security concerns that do not want to access the Internet during the installation process.
So install Nexus but don't forget to heavily test your app to run
npm test
and get another excuse to take a coffee break with your teammates![joinus]
[yikes-mailchimp form='1']
Nicolas Girault
Web Developer at Theodo