preface
The Yarn team released the Yarn 2.0 plan before The Spring Festival. There was a mention of a previously unknown noun, “PnP”. Discover that this function of Yarn was proposed and implemented as early as September 2018. Therefore, I spent some time to understand its working principle and the problems solved, and sorted out this article.
Status quo and pain points
The most direct reason for the Yarn team to develop PnP features is that the existing dependency management mode is inefficient. Slow to reference dependencies, slow to install dependencies.
Let’s start with Node’s logic for dealing with dependent references. There are two scenarios:
- If we pass
require()
The argument to the call is oneThe core module(e.g. “fs”, “path”, etc.) or a local relative path (e.g./module-a.js
或/my-li/module-b.js
), Node will use the corresponding file directly. - If this is not the case described above, Node will start looking for an object named
node_modules
The directory:- First Node looks in the current directory
node_modules
If not, go to the parent directory and so on to the system root directory. - find
node_modules
Directory, and then look in that directory for the namemoduleName.js
File or file namedmoduleName
Subdirectory of.
- First Node looks in the current directory
The purpose here is to illustrate the problem and simplify the description of Node internal module parsing logic
Node does a lot of FILE I/O to resolve dependencies, which is inefficient.
Looking at what happens when dependencies are installed, the YARN Install operation at this stage performs the following four steps:
- Resolves the version range of a dependent package to a specific version number
- Download the tar package dependent on the corresponding version to the local offline image
- Decompress dependencies from offline images to the local cache
- Copies dependencies from the cache to the current directory
node_modules
directory
Step 4 also involves a lot of file I/O, making it inefficient to install dependencies (especially in a CI environment, where you need to install all dependencies each time).
Facebook’s engineers were fed up with these problems and decided to find a solution that would completely solve the problem while still being ecologically compatible. This is the Plug’n’Play feature, or PnP for short. It has been tested internally on Facebook for some time, and now the Yarn team has decided to share and refine the solution with the community.
Implementation scheme
How PnP works is that, as an alternative to copying dependencies from cache to node_modules, Yarn maintains a static mapping table that contains the following information:
- Which versions of which dependency packages are currently included in the dependency tree
- How do these dependency packages relate to each other
- The location of these dependency packages in the file system
This mapping table is in the.pNP. Js file corresponding to the project directory in the PnP implementation of Yarn.
How is the.pnp.js file generated and how does Yarn take advantage of it?
When installing a dependency, Yarn does not copy the dependency to the node_modules directory after step 3. Instead, it records the dependency’s location in the cache in.pnp.js. This avoids a lot of I/O and the project directory does not have node_modules generated.
Js also contains a special resolver that Yarn uses to handle require() requests. The resolver directly determines the exact location of dependencies in the file system based on the static mapping table contained in the.pnp.js file, thus avoiding the I/O operations of existing implementations dealing with dependent references.
What benefits did it bring
As you can see from the implementation of PnP, the same version of the same dependency referenced by different projects on the same system actually points to the same directory in the cache. This has several obvious benefits:
- The speed of installing dependencies has never been faster
- Multiple CI instances in a CI environment can share the same cache
- Multiple projects on the same system no longer need to occupy multiple disk space
How do I get started with the Plug’n’Play feature?
First you need Yarn 1.12+ version. Then you can choose according to your specific scene:
usecreate-react-app
Turn on PnP when creating a project
Create-react-app has integrated SUPPORT for PnP. Simply add the — use-pNP parameter when creating the project.
npx create-react-app testapp --use-pnp
Copy the code
Enable PnP in an existing project
Just perform in the project:
yarn --pnp
Copy the code
The PnP feature is enabled.
Matters needing attention
pkg.installConfig
field
After enabling the PnP feature in your project, Yarn creates an installConfig field in package.json:
{
"installConfig": {
"pnp": true}}Copy the code
PNP is enabled as long as the value of installConfig. PNP is a true value and the current version of Yarn supports it.
performnpm script
Or run.js
file
Since there is no longer a node_modules directory in pNP-enabled projects, all dependent references must be handled by resolver in.pnP.js. Therefore, both script execution and JS file execution using Node must be processed by Yarn. The command must be executed using YARN Run or YARN Node.
Debug dependencies in your project
Sometimes during development we debug dependencies directly in the node_modules directory. However, in PnP mode, since the dependencies point to the global cache, we can no longer modify them directly.
For this scenario, Yarn provides Yarn Unplug packageName to copy a specified dependency to the. PNP/Unplugged directory of the project. The unplug version is then automatically loaded by the resolver in.pnp.js.
After debugging, run yarn Unplug –clear packageName to remove the dependency in the local. PNP/Unplugged plugged port.
conclusion
PnP is still a relatively new feature, so try enabling PnP in your local development environment to get a feel for the new experience. If any problem occurs, report it to the ISSUE list of Yarn.
Reference links:
- Yarn’s Future – v2 and beyond
- Yarn Plug’n’Play: Getting rid of node_modules
- The plug-in ‘n’ Play Whitepaper
- Yarn Plug’n’Play: Implementation
- yarnpkg.com/en/docs/pnp
For more articles, please follow our team’s official account: Full Stack Exploration