npm
What does install do?
When we hit NPM Install, NPM does a few things.
- Check the config
NPM execution reads NPM config and NPMRC first.
NPMRC is weighted,
Project level NPMRC > User level NPMRC > Global NPMRC > NPM Built-in NPMRC
- Check for package-lock.json
-
If you have
-
Is it consistent with the version declared in the current package-lock
-
consistent
-
Check the cache
-
-
Don’t agree
-
If the versions are inconsistent, the solution depends on the NPM version. In the latest VERSION of NPM, the system checks the compatible versions of dependent packages. If the versions are compatible, install them according to package-lock; otherwise, install them according to package.json
-
(Because different VERSIONS of NPM can lead to different processes, it is a best practice for teams to have the same VERSION of NPM)
-
-
-
If there is no
-
Get information about dependent packages
-
Building a dependency tree
-
flat
-
Check the cache
-
-
Check the cache
- If you have a cache
-
Decompress the corresponding cache to node_modules
-
To generate the package – the lock
-
- If you don’t have caching
-
Download resource Packs
-
Check resource pack integrity
-
Add to cache
-
Unzip node_modules
-
To generate the package – the lock
-
- If you have a cache
This is how we executed NPM install.
As you can see, caching plays a key role in the overall ARCHITECTURE of NPM. A cache is created for the corresponding package each time a dependency is installed. How do we look at the cache?
NPM cache
We can get through
npm config get cache
Copy the code
This command gets the local path to the NPM cache. We go to that directory, the _cacache directory, where the NPM cache is stored
~/.npm/_cacache » ls content-v2 index-v5 TMPCopy the code
Content-v2 is the cache binary file, and index-v5 is the cache corresponding index.
How to generate a cache
When NPM install is running, pacote first downloads the dependent packages to the cache and decompresses the corresponding packages to node_modules.
Pacote relies on NPM-registry-fetch to download packages and generates cached data according to IETF RFC 7234 in the specified path.
How to leverage caching
Each time the resource is installed, a unique key is generated based on the integrity, version, and name information stored in package-lock.json. This key corresponds to a cached record in the index-v5 directory. If cached resources are found, the hash of the tar package will be found, and the corresponding binary file will be decompressed to the corresponding node_modules using pacote.
This completes the caching workflow
npm link
Imagine that we now face the following scenario.
We developed a dependency package, and we wanted to test our dependencies below, but we couldn’t release untested dependencies. Now it’s an endless cycle…
We came up with a primitive way to do this: manually place dependencies into node_modules. So we can start testing. This satisfies the current requirements, but it is not elegant to keep CV manual. So is there a way to solve this need?
Enter our hero, NPM Link
The essence of NPM link is to create a soft connection
It works by linking it to the global Node module installation path. Create a soft connection for the executable bin file of the target NPM module and connect it to the global Node command installation path.
npx
NPX can directly execute files under node_modules/. Bin, and automatically check whether the command exists in node_modules/. Bin and environment variable $path.
NPX installs dependencies first when the module is executed, but removes them after the installation, which has the advantage of avoiding global module installation
(so NPX create-react-app XXX will install crA by default and delete it after completion)
The source of NPM
NPM is essentially a query service (default: npmjs.org: registry.npmjs.org/)
We can use NPM config set Registry XXX to switch our source.
If we encounter different packages with different sources, we can use the NPM hook preinstall to execute the Node script and implement the source switch.
Deploying the benefits of privatized NPM
-
Ensure high speed and stable NPM service, making it safer to distribute private modules
-
Audit mechanism can ensure module quality and safety
yarn
What does install do?
-
Testing kits
- Check whether there are NPM related files
- Check OS CPU information
-
Analytic package
-
Get dependencies in package.json to obtain dependencies version information (dependencies and devDependencies), recursively obtain nested dependencies (dependencies needed in the package) version information. The parsed and parsed packages are stored in a set to ensure that packages in the same version range are not parsed twice.
-
For packages that have not been parsed, an attempt is made to get the version and mark it as parsed.
-
If the declaration of the package is not found in yarn-lock, a request is made to Registry to obtain the highest version of the package that meets the version range and the information obtained is marked as resolved.
-(This process is finished with all the dependent version information and download address)
-
-
Get package
-
Check whether the current dependent package exists in the cache, and download the non-existing package to the cache directory
-
Yarn Generates a path based on cacheFolder + slug + node_modules + pkg.name to check whether the path proof exists in the system and whether it is cached
-
For packets that do not match the cache, YARN maintains a FETCH queue for network requests based on rules
-
-
Links to package
-
(peerDependencies is a package that the host environment uses to install peerDependencies. It is a package that the host environment uses to install peerDependencies. Finally resolve the issue of inconsistency between plug-ins and dependent packages.
-
Warning if a conflict is found
-
And then flattening depends on the tree
-
Executing a Copy Task
-
Unzip node_modules
-
-
Build a package
-
If you have packages that need to be built, such as binary packages, build them in this step
-
Why do NPM and YARN pursue flattening in unison
If we were to design a dependency system, the first thing we would think of would be a tree structure
The spanning tree surface is fine, it works for our needs, but if
- The project depends on A and B, and both A and B depend on C of the same version. Repeated installation will waste resources
The dependency structure is as follows
app
|
-- A : V1. 0 -> C : V1. 0
-- B : V1. 0 -> C : V1. 0
Copy the code
What if C depends on D? . It’s getting out of hand.
- Too long windos to delete node_modules may cause problems.
Here comes the word dependency hell
Rely on the hell
In layman’s terms, dependency hell is when a developer installs a dependency package that then relies on a different version of another dependency package. As the number of dependencies increases, we run the risk of version control being locked down as the number of dependencies increases and the dependencies become deeper.
So the solution to dependency hell is flattening
// before flattening
app
|
-- A : V1. 0 -> B : V1. 0
-- C : V1. 0 -> B : V2. 0
// After flattening
app
|
-- A : V1. 0
-- B : V1. 0
-- C : V1. 0 -> B : V2. 0
-- D : V1. 0 -> B : V2. 0
Copy the code
See this may be some students want to ask, flat does not seem to solve the problem of dependency hell ah? But if we install modules C or D first, let’s look at dependencies
app
|
-- A : 1.0 -> B : V1. 0
-- B : V2. 0
-- C : V1. 0
-- D : V1. 0
Copy the code
From this we can see that which repeating modules are placed outside depends on the order in which they are installed.
Back to the first case, if A upgrades from V1.0 to V2.0 and relies on the B: V2.0 module, the dependencies are as follows
app
|
-- A 2.0
-- B 2.0
-- C 1.0 -> B 2.0
-- D 1.0 -> B 2.0
Copy the code
In this case, you can run NPM dedupe(yarn automatically executes this command) or delete node_modules and reinstall the dependency. The optimized dependency relationship is as follows:
app
|
-- A 2.0
-- B 2.0
-- C 1.0
-- D 1.0
Copy the code
Finally: Welcome to discuss with me in the comments section, code word is not easy, trouble more than three support ~