Migration
Edit this page on GitHubAny major release has its breaking changes, and Yarn 2 isn't the exception. A few old behaviors were cleaned, fixed, modified, or removed. While one of our goals is to make the transition as easy as we can, there are a few things to be aware of when migrating a codebase. To make this process more efficient we've listed below the recommended migration steps, along with solutions for the most common problems you might face.
- Upgrade to Node.js 14.x or newer
- Fix dependencies with
packageExtensions
- Use
yarn dlx
instead ofyarn global
- Enable the PnP plugin when using Webpack 4
- Upgrade
resolve
to 1.9+ - Call binaries using
yarn run
rather thannode_modules/.bin
- Call your scripts through
yarn node
rather thannode
- Explicitly call the
pre
andpost
scripts - Setup your IDE for PnP support
- Update your configuration to the new settings
- Don't use
.npmrc
files - Take a look at our end-to-end tests
- Don't use
bundleDependencies
- If required: enable the
node-modules
plugin - Replace
nohoist
bynmHoistingLimits
Why should you migrate?
We answer this question in details here.
In a few words, upgrading to the latest versions is critical to a fast and stable Yarn experience. Numerous bugs were fixed since the first major version, and we no longer expect to build new features on the old trunk. Even if you don't plan to use the new default installation strategy called Plug'n'Play your projects will still get benefits from the upgrade:
- The good old
node_modules
installer improved as well as various edge cases got fixed - A renewed focus on performances and good practices (we now formally track perfs via a dashboard)
- Improved user experience for various CLI commands and settings (
yarn add -i
,yarn up
,logFilters
, ...) - New commands and capabilities (such as the TypeScript plugin, or the release workflow)
And of course a very active development cycle.
Step by step
Note: Don't worry if your project isn't quite ready for Plug'n'Play just yet! This guide will let you migrate without losing your node_modules
folder. Only in a later optional section we will cover how to enable PnP support, and this part will only be recommended, not mandatory. Baby steps! 😉
Note that those commands only need to be run once for the whole project and will automatically take effect for all your contributors as soon as they pull the migration commit, thanks to the power of yarnPath
:
- Run
npm install -g yarn
to update the global yarn version to latest v1 - Go into your project directory
- Run
yarn set version berry
to enable v2 (cf Install for more details) - If you used
.npmrc
or.yarnrc
, you'll need to turn them into the new format (see also 1, 2) - Add
nodeLinker: node-modules
in your.yarnrc.yml
file - Commit the changes so far (
yarn-X.Y.Z.js
,.yarnrc.yml
, ...) - Run
yarn install
to migrate the lockfile - Take a look at this article to see what should be gitignored
- Commit everything remaining
Some optional features are available via external plugins:
- Run
yarn plugin import interactive-tools
if you wantupgrade-interactive
- Run
yarn plugin list
to see what other official plugins exist and might be useful - Commit the yarn plugins
Good, you should now have a working Yarn install! Some things might still require a bit of work (for instance we deprecated arbitrary pre/post
-scripts, and renamed --frozen-lockfile
into --immutable
), but those special cases will be documented on a case-by-case basis in the rest of this document (for example here).
Switching to Plug'n'Play
This step is completely optional - while we recommend to use Plug'n'Play for most new projects, it may sometimes require an average time investment to enable it on existing projects. For this reason, we prefer to list it here as a separate step that you can look into if you're curious or simply want the absolute best of what Yarn has to offer.
Before we start
Plug'n'Play enforces strict dependency rules. In particular, you'll hit problems if you (or your dependencies) rely on unlisted dependencies (the reasons for that are detailed in our Rulebook), but the gist is that it was the cause of many "project doesn't work on my computer" issues, both in Yarn and other package managers.
To quickly detect which places may rely on unsafe patterns run yarn dlx @yarnpkg/doctor
in your project - it'll statically analyze your sources to try to locate the most common issues that could result in a subpar experience. For example here's what webpack-dev-server
would reveal:
➤ YN0000: Found 1 package(s) to process
➤ YN0000: For a grand total of 236 file(s) to validate
➤ YN0000: ┌ /webpack-dev-server/package.json
➤ YN0000: │ /webpack-dev-server/test/testSequencer.js:5:19: Undeclared dependency on @jest/test-sequencer
➤ YN0000: │ /webpack-dev-server/client-src/default/webpack.config.js:12:14: Webpack configs from non-private packages should avoid referencing loaders without require.resolve
➤ YN0000: │ /webpack-dev-server/test/server/contentBase-option.test.js:68:8: Strings should avoid referencing the node_modules directory (prefer require.resolve)
➤ YN0000: └ Completed in 5.12s
➤ YN0000: Failed with errors in 5.12s
In this case, the doctor noticed that:
testSequencer.js
depends on a package without listing it as a proper dependency - which would be reported as an error at runtime under Plug'n'Play.webpack.config.js
references a loader without passing its name torequire.resolve
- which is unsafe, as it means the loader won't be loaded fromwebpack-dev-server
's dependencies.contentBase-option.test.js
checks the content of thenode_modules
folder - which wouldn't exist anymore under Plug'n'Play.
Enabling it
- Look into your
.yarnrc.yml
file for thenodeLinker
setting - If you don't find it, or if it's set to
pnp
, then it's all good: you're already using Plug'n'Play! - Otherwise, remove it from your configuration file
- Run
yarn install
- Various files may have appeared; check this article to see what to put in your gitignore
- Commit the changes
Editor support
We have a dedicated documentation, but if you're using VSCode (or some other IDE with Intellisense-like feature) the gist is:
- Install the ZipFS VSCode extension
- Make sure that
typescript
,eslint
,prettier
, ... all dependencies typically used by your IDE extensions are listed at the top level of the project (rather than in a random workspace) - Run
yarn dlx @yarnpkg/sdks vscode
- Commit the changes - this way contributors won't have to follow the same procedure
- For TypeScript, don't forget to select Use Workspace Version in VSCode
Final notes
Now you should have a working Yarn Plug'n'Play setup, but your repository might still need some extra care. Some things to keep in mind:
- There is no
node_modules
folder and no.bin
folder. If you relied on these, callyarn run
instead. - Replace any calls to
node
that are not inside a Yarn script withyarn node
- Custom pre-hooks (e.g. prestart) need to be called manually now
All of this and more is documented in the following sections. In general, we advise you at this point to try to run your application and see what breaks, then check here to find out tips on how to correct your install.
General Advices
Upgrade to Node.js 14.x or newer
Node.js 12.x reached its official End of Life in April 2022 and won't receive any further update. Yarn consequently doesn't support it anymore.
Fix dependencies with packageExtensions
Packages sometimes forget to list their dependencies. In the past it used to cause many subtle issues, so Yarn now defaults to prevent such unsound accesses. Still, we don't want it to prevent you from doing your work as long as you can do it in a safe and predictable way, so we came up with the packageExtensions
setting.
For example, if react
was to forget to list a dependency on prop-types
, you'd fix it like this:
packageExtensions:
"react@*":
dependencies:
prop-types: "*"
And if a Babel plugin was missing its peer dependency on @babel/core
, you'd fix it with:
packageExtensions:
"@babel/plugin-something@*":
peerDependencies:
"@babel/core": "*"
Use yarn dlx
instead of yarn global
yarn dlx
is designed to execute one off scripts that may have been installed as global packages with yarn 1.x
. Managing system-wide packages is outside of the scope of yarn
. To reflect this, yarn global
has been removed. Read more on GitHub.
Enable the PnP plugin when using Webpack 4
Webpack 5 supports PnP natively, but if you use Webpack 4 you'll need to add the pnp-webpack-plugin
plugin yourself.
Upgrade resolve
to 1.9+
The resolve
package is used by many tools in order to retrieve the dependencies for any given folder on the filesystem. It's compatible with Plug'n'Play, but only starting from 1.9+, so make sure you don't have an older release in your dependency tree (especially as transitive dependency).
Fix: Open your lockfile, look for all the resolve
entries that could match 1.9+ (for example ^1.0.0
), and remove them. Then run yarn install
again. If you run yarn why resolve
, you'll also get a good idea of which package is depending on outdated version of resolve
- maybe you can upgrade them too?
Call binaries using yarn run
rather than node_modules/.bin
The node_modules/.bin
folder is an implementation detail, and the PnP installs don't generate it at all. Rather than relying on its existence, just use the yarn run
command which can start both scripts and binaries:
yarn run jest
# or, using the shortcut:
yarn jest
Call your scripts through yarn node
rather than node
We now need to inject some variables into the environment for Node to be able to locate your dependencies. In order to make this possible, we ask you to use yarn node
which transparently does the heavy lifting.
Note: this section only applies to the shell CLI. The commands defined in your scripts
are unaffected, as we make sure that node
always points to the right location, with the right variables already set.
Explicitly call the pre
and post
scripts
Rewrite:
{
"scripts": {
"prestart": "do-something",
"start": "http-server"
}
}
Into:
{
"scripts": {
"prestart": "do-something",
"start": "yarn prestart && http-server"
}
}
Note: This only applies to user scripts, such as start
& friends. It's still fine to use any of preinstall
, install
, and postinstall
. Consult the script documentation for more information.
Setup your IDE for PnP support
We've written a guide entirely designed to explain how to use Yarn with your IDE. Make sure to take a look at it, and maybe contribute to it if some instructions are unclear or missing!
Update your configuration to the new settings
Yarn 2 uses a different style of configuration files than Yarn 1. While mostly invisible for the lockfile (because we import them on the fly), it might cause some issues for your rc files.
The main change is the name of the file. Yarn 1 used
.yarnrc
, but Yarn 2 is moving to a different name:.yarnrc.yml
. This should make it easier for third-party tools to detect whether a project uses Yarn 1 or Yarn 2, and will allow you to easily set different settings in your home folders when working with a mix of Yarn 1 and Yarn 2 projects.As evidenced by the new file extension, the Yarnrc files are now to be written in YAML. This has been requested for a long time, and we hope it'll allow easier integrations for the various third-party tools that need to interact with the Yarnrc files (think Dependabot, etc).
The configuration keys have changed. The comprehensive settings list is available in our documentation, but here are some particular changes you need to be aware of:
Custom registries are now configured via
npmRegistryServer
.Registry authentication tokens are now configured via
npmAuthToken
.The
yarn-offline-mirror
has been removed, since the offline mirror has been merged with the cache as part of the Zero-Install effort. Just commit the Yarn cache and you're ready to go.
Don't use .npmrc
files
On top of their naming, the way we load the Yarnrc files has also been changed and simplified. In particular:
Yarn doesn't use the configuration from your
.npmrc
files anymore; we instead read all of our configuration from the.yarnrc.yml
files whose available settings can be found in our documentation.As mentioned in the previous section, the yarnrc files are now called
.yarnrc.yml
, with an extension. We've completely stopped reading the values from the regular.yarnrc
files.All environment variables prefixed with
YARN_
are automatically used to override the matching configuration settings. So for example, addingYARN_NPM_REGISTRY_SERVER
into your environment will change the value ofnpmRegistryServer
.
Take a look at our end-to-end tests
We now run daily end-to-end tests against various popular JavaScript tools in order to make sure that we never regress - or to be notified when those tools do.
Consulting the sources for those tests is a great way to check whether some special configuration values have to be set when using a particular toolchain.
Don't use bundleDependencies
The bundleDependencies
(or bundledDependencies
) is an artifact of the past that used to let you define a set of packages that would be stored as-is within the package archive, node_modules
and all. This feature has many problems:
- It uses
node_modules
, which doesn't easily allow different install strategies such as Plug'n'Play. - It encodes the hoisting inside the package, which is the exact opposite of what we aim for
- It messes with the hoisting of other packages
- Etc, etc, etc
So how to replace them? There are different ways:
If you need to patch a package, just fork it or reference it through
file:
(it's perfectly fine even for transitive dependencies to use this protocol). Theportal:
andpatch:
protocols are also options, although they'll only work for Yarn consumers.If you need to ship a package to your customers as a standalone (no dependencies), bundle it yourself using Webpack, Rollup, or similar tools.
If required: enable the node-modules
plugin
Despite our best efforts some tools don't work at all under Plug'n'Play environments, and we don't have the resources to update them ourselves. There are only two notorious ones on our list: Flow, and React Native.
In such a radical case, you can enable the built-in node-modules
plugin by adding the following into your local .yarnrc.yml
file before running a fresh yarn install
:
nodeLinker: node-modules
This will cause Yarn to install the project just like Yarn 1 used to, by copying the packages into various node_modules
folders.
More information about the nodeLinker
option.
Replace nohoist
by nmHoistingLimits
The nohoist
setting from Yarn 1 was made specifically for React Native (in order to help it support workspaces), but the way it worked (through glob patterns) was causing a lot of bugs and confusion, noone being really sure which patterns needed to be set. As a result, we've simplified this feature in order to only support three identified patterns.
If you were using nohoist
, we recommend you remove it from your manifest configuration and instead set nmHoistingLimits
in your yarnrc file:
nmHoistingLimits: workspaces
CLI Commands
Renamed
Yarn Classic (1.x) | Yarn (2.x) | Notes |
---|---|---|
yarn audit | yarn npm audit | |
yarn create | yarn dlx create-<name> | yarn create still works, but prefer using yarn dlx |
yarn global | yarn dlx | Dedicated section |
yarn info | yarn npm info | |
yarn list | yarn info --recursive | |
yarn login | yarn npm login | |
yarn logout | yarn npm logout | |
yarn outdated | yarn upgrade-interactive | Read more on GitHub |
yarn publish | yarn npm publish | |
yarn tag | yarn npm tag | |
yarn upgrade | yarn up | Will now upgrade packages across all workspaces |
yarn install --production | yarn workspaces focus --all --production | Requires the workspace-tools plugin |
yarn install --verbose | YARN_ENABLE_INLINE_BUILDS=true yarn install |
Removed from core
Yarn Classic (1.x) | Notes |
---|---|
yarn check | Cache integrity is now checked on regular installs; read more on GitHub |
yarn import | First import to Classic, then migrate to 2.x |
yarn licenses | Perfect use case for plugins; read more on GitHub |
yarn versions | Use yarn --version and node -p process.versions |
Not implemented yet
Those features simply haven't been implemented yet. Help welcome!
Yarn Classic (1.x) | Notes |
---|---|
yarn owner | Will eventually be available as yarn npm owner |
yarn team | Will eventually be available as yarn npm team |
Troubleshooting
Cannot find module [...]
Interestingly, this error often doesn't come from Yarn. In fact, seeing this message should be extremely rare when working with Yarn 2 projects and typically highlights that something is wrong in your setup.
This error appears when Node is executed without the proper environment variables. In such a case, the underlying application won't be able to access the dependencies and Node will throw this message. To fix that, make sure that the script is called through yarn node [...]
(instead of node [...]
) if you run it from the command line.
A package is trying to access another package [...]
Full message: A package is trying to access another package without the second one being listed as a dependency of the first one.
Some packages don't properly list their actual dependencies for a reason or another. Now that we've fully switched to Plug'n'Play and enforce boundaries between the various branches of the dependency tree, this kind of issue will start to become more apparent than it previously was.
The long term fix is to submit a pull request upstream to add the missing dependency to the package listing. Given that it sometimes might take some time before they get merged, we also have a more short-term fix available: create .yarnrc.yml
in your project, then use the packageExtensions
setting to add the missing dependency to the relevant packages. Once you're done, run yarn install
to apply your changes and voilà!
packageExtensions:
"debug@*":
peerDependenciesMeta:
"supports-color":
optional: true
If you also open a PR on the upstream repository you will also be able to contribute your package extension to our plugin-compat
database, helping the whole ecosystem move forward.