npm is Node's module manager and is extremely powerful. It's one of the big reasons for Node's success.
Thanks to npm, we can install modules written by others with just one line of command.
$ npm install
This article describes the details of the npm module installation mechanism and how to solve the slow installation problem.
1. Start with npm install
npm install
The command is used to install the module into the node_modules
directory.
$ npm install <packageName>
Before installation, npm install
it will first check node_modules
whether the specified module already exists in the directory. If it exists, there is no reinstallation, even if the remote repo already has a new version.
If you want npm to force a module to be reinstalled regardless of whether it was installed or not, you can use the -f
or --force
parameter.
$ npm install <packageName> --force
二、npm update
If you want to update installed modules, you need to use npm update
the command.
$ npm update <packageName>
It will first go to the remote repository to query the latest version, and then query the local version. If the local version does not exist, or the remote version is newer, it will be installed.
Third, registry
npm update
How does the command know the latest version of each module?
The answer is that the npm module repository provides a query service called registry. Take npmjs.org as an example, its query service URL is https://registry.npmjs.org/
.
Follow this URL with the module name and you will get a JSON object with information about all versions of the module. For example, if you visit https://registry.npmjs.org/react
, you will see information about all versions of the react module.
It has the same effect as the following command.
$ npm view react # npm view 的别名 $ npm info react $ npm show react $ npm v react
After the module name of the registry URL, you can also follow the version number or label to query the information of a specific version. For example, visit https://registry.npmjs.org/react/v0.14.6 to see version 0.14.6 of React.
In the returned JSON object, there is an dist.tarball
attribute, which is the URL of the compressed package of this version.
dist: { shasum: '2a57c2cf8747b483759ad8de0fa47fb0c5cf5c6a', tarball: 'http://registry.npmjs.org/react/-/react-0.14.6.tgz' },
Go to this website to download the compressed package, decompress it locally, and get the source code of the module. npm install
and npm update
commands, all install modules in this way.
Fourth, the cache directory
npm install
Or npm update
command, after downloading the compressed package from the registry, it is stored in the local cache directory.
This cache directory, which defaults to the user's home directory on Linux or Mac .npm
, is the default on Windows %AppData%/npm-cache
. Through the configuration command, you can view the specific location of this directory.
$ npm config get cache $HOME/.npm
You'd better browse this directory.
$ ls ~/.npm # 或者 $ npm cache ls
You will see a large number of modules are stored inside, the storage structure is {cache}/{name}/{version}
.
$ npm cache ls react ~/.npm/react/react/0.14.6/ ~/.npm/react/react/0.14.6/package.tgz ~/.npm/react/react/0.14.6/package/ ~/.npm/react/react/0.14.6/package/package.json
Each version of each module has its own subdirectory containing the code zip package.tgz
file and a description file package/package.json
.
In addition to that, a {cache}/{hostname}/{path}/.cache.json
file is generated. For example, when you download a react module from the official npm repository, a registry.npmjs.org/react/.cache.json
file is generated.
This file saves all version information, as well as the last modification time of the module and the ETag returned by the server during the latest request.
{ "time":{ "modified":"2016-01-06T23:52:45.571Z", // ... }, "_etag":"\"7S37I0775YLURCFIO8N85FO0F\"" }
For some operations that are not very critical (such as npm search
or npm view
), npm will first check .cache.json
the latest update time of the module in it, and whether the gap with the current time is within an acceptable range. If it is, it will no longer make a request to the remote warehouse, but return .cache.json
the data directly.
.npm
The directory holds a large number of files, and the command to clear it is as follows.
$ rm -rf ~/.npm/* # 或者 $ npm cache clean
Five, the module installation process
To sum up, the installation process of Node modules is like this.
- issue an
npm install
order- npm queries the registry for the URL of the module compressed package
- Download the compressed package and store it in the
~/.npm
directory- Unzip the archive to the
node_modules
directory of the current project
Note that after a module is installed, two copies are actually saved locally. One is ~/.npm
the compressed package in the directory, and the other is node_modules
the decompressed code in the directory.
However, npm install
when running, only the node_modules
directory is checked, not the ~/.npm
directory. That is, if a ~/.npm
module has a tarball under it, but it's not installed in the node_modules
directory, npm will still download a new tarball from the remote repository.
This behavior certainly guarantees that the latest code is always available, but sometimes it is not what we want. The biggest problem is that it greatly affects the installation speed. Even if the compressed package of a module is in the cache directory, it must be downloaded from the remote warehouse. How can it not be slow?
In addition, in some occasions there is no network (such as on an airplane), but the module you want to install is obviously in the cache directory, and it cannot be installed at this time.
6. --cache-min
Parameters
To address these issues, npm provides an --cache-min
argument for installing modules from a cache directory.
--cache-min
The parameter specifies a time (in minutes), and only modules that exceed this time will be downloaded from the registry.
$ npm install --cache-min 9999999 <package-name>
The above command specifies that only modules older than 999999 minutes are downloaded from the registry. In fact, it is specified that all modules are installed from the cache, which greatly speeds up the download speed.
It has another way of writing it.
$ npm install --cache-min Infinity <package-name>
However, this does not equate to offline mode, where an internet connection is still required . Because the current --cache-min
implementation has some problems.
(1) If the specified module is not in the cache directory, npm will connect to the registry and download the latest version. This is no problem, but if the specified module is in the cache directory, npm will also connect to the registry , issue the etag of the specified module, and the server returns a status code of 304, indicating that the compressed package does not need to be downloaded again.
(2) If a module is already in the cache, but the version is lower than required, npm will report an error directly instead of going to the registry to download the latest version.
The npm team is aware of these issues and is rewriting the cache . And, in the future, a --offline
parameter will be provided to make npm available offline.
However, there is no schedule for these improvements. Therefore, the current use of --cache-min
improving the installation speed is problematic.
Seven, offline installation solutions
The community has proposed several solutions for offline use of npm. They can greatly speed up module installation.
Solutions fall broadly into three categories.
The first category, the Registry proxy.
The usage of the above three modules is very similar. They all start a Registry service on the machine, and all npm install
commands must be proxied by this service.
# npm-proxy-cache $ npm --proxy http://localhost:8080 \ --https-proxy http://localhost:8080 \ --strict-ssl false \ install # local-npm $ npm set registry http://127.0.0.1:5080 # npm-lazy $ npm --registry http://localhost:8080/ install socket.io
With the local registry service, the cache installation can be completely realized and offline use can be realized.
The second category is npm install
substitution.
If you can change npm install
the behavior, you can achieve cache installation. npm-cache
Tools are this idea. Substitutes can be used npm install
wherever they are used .npm-cache
$ npm-cache install
The third category, node_modules
as a cache directory.
The idea of this scheme is to not use the .npm
cache, but to use the project's node_modules
directory as the cache.
The above two tools can make the node_modules
directory of the project into a compressed package, and then extract the files from this compressed package when installing it later.