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 passrequire()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 namednode_modulesThe directory:
    1. First Node looks in the current directorynode_modulesIf not, go to the parent directory and so on to the system root directory.
    2. findnode_modulesDirectory, and then look in that directory for the namemoduleName.jsFile or file namedmoduleNameSubdirectory of.

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:

  1. Resolves the version range of a dependent package to a specific version number
  2. Download the tar package dependent on the corresponding version to the local offline image
  3. Decompress dependencies from offline images to the local cache
  4. Copies dependencies from the cache to the current directorynode_modulesdirectory

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-appTurn 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.installConfigfield

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 scriptOr run.jsfile

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