Migrating to Yarn 2
Last updated April 04, 2023
Table of Contents
To our excitement, Yarn 2 was released in early 2020. The team has created a “zero installs” package manager, which means users may use “vendor” directories to include their yarn binaries, dependencies, and development dependencies in their repositories. Learn more about Yarn’s new philosophy.
This article is intended to help current Heroku users migrate from Yarn 1 to Yarn 2. Apps being migrated should already be using Yarn 1 and are using the most up-to-date version of the Heroku Node.js buildpack. This article will not work for applications that install Yarn from other scripts, such as the Heroku Ruby buildpack. Heroku expects all dependencies to be included in the .yarn
directory to take full advantage of “zero downloads”.
Heroku users using Yarn are not required to migrate to Yarn 2, and users will have access to Yarn 1 in their apps after it is deprecated. However, it’s advised to migrate to Yarn 2 to ensure the most up-to-date bug fixes and security patches in the package manager.
Use this article to migrate your app code locally to Yarn 2, as well your application on Heroku.
The following will reference checking files into git
while directions could also be applied to other version control systems.
Local Setup
Prepare local environment
Enter the directory of the source code that needs the migration. The local commands will be run at the root of the project. Make sure the local yarn version is up to date. To update it locally, run install with npm:
npm install -g yarn
The version should be >= 1.22.4
. Run yarn -v
to confirm.
Move custom cache directories to workspaces
If your package.json
, does not have a cacheDirectories
section, move ahead to the next section.
In package.json
, change your cacheDirectories
to workspaces
. For example, if you have the following:
"cacheDirectories": [
"client/node_modules"
]
Change it to the following, and specify that the project is private:
"workspaces": [
"client"
],
"private": true,
There’s no need to specify the node_modules
directory. Make sure the "name"
key in the package.json
of the subdirectory reflects the directory name and the workspace name specified in the root package.json
.
Next, delete any node_modules
folders and yarn.lock
files in subdirectories, and go to your application directory and run yarn
:
cd ~/path/to/project && yarn install
This should update the yarn.lock
file of your directory to reflect the entire dependency tree specified by the workspaces. Confirm that the lock file has been updated by looking for a dependency that has been specified in a package.json
of a subdirectory.
Make changes to source code
There are additional files that must be checked into git in order to use Yarn 2 on Heroku. Yarn subscribes to a “zero-download” philosophy. There will be additional download costs to checking into git more files and directories, but this will create faster builds on Heroku.
Use yarn
to set the yarn version on the source code.
yarn set version berry
To use the Zero-Installs feature, which will push locally cached dependendencies
to heroku, add the following to .gitginore
:
.yarn/*
!.yarn/cache
!.yarn/releases
!.yarn/plugins
!.yarn/sdks
!.yarn/versions
To opt-out of the Zero-Installs feature instead, which will trigger the buildpack to
download and install all dependendencies, add the following to .gitignore
:
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/sdks
!.yarn/versions
Next, use yarn to install packages and create the required files:
yarn install
This will create a .yarnrc.yml
file,a .yarn
directory, a pnp.js
file, and modify the yarn.lock
. Check these into git and make sure they are available to Heroku at build time.
The contents of .yarn/cache
are not comparable to node_modules
. The files are compressed and are meant to be checked into the project.
Clear Heroku App cache
Since Heroku won’t be restoring the cache at the beginning of the build or storing it at the end of the build, you can go ahead and purge any build cache that is leftover from previous builds.
Make sure you have heroku-cli
installed. Then, install the heroku-builds
plugin.
heroku plugins:install heroku-builds
Next, run the command to clear the cache.
heroku builds:cache:purge --app $APP_NAME
After this, you’ll want to redeploy your app, but first finish up the next steps to ensure a successful deploy.
Update Heroku environment (with Plug'n'Play)
If you’re using Yarn 2, you have the option of using Yarn’s Plug'n'Play to reference dependencies, or you can continue to use node modules. Each requires a slightly different set up, so if you intend to use node modules, set up your app accordingly.
Disable dependency caching
Right now, Heroku doesn’t cache dependencies with Yarn 2 from the .yarn/cache
directory. When using Plug'n'Play, Yarn will expect zipped up dependencies to be in the .yarn/cache
directory. However, the buildpack will still run yarn install
to ensure that postinstall
scripts will be run for all dependencies.
You will want to remove the environment variables that are associated with Yarn 1 and node_modules
. Therefore, remove the NODE_MODULES_CACHE
environment variable. This variable should be set to false
.
heroku config:set NODE_MODULES_CACHE=false
Heroku is working on caching from the .yarn/cache
directory, but it is not supported yet. If you’d like to use a custom cache setup, you can do with custom caching configuration.
Remove private registry environment variables
If you’ve set any tokens for accessing a private registry and you’re using Yarn 2 with a checked in cache, unset those as well. You may do something like this:
heroku config:unset PRIVATE_NPM_TOKEN
Update Heroku environment (for node modules)
As described above, you will either be using Plug'n'Play or node modules for dependencies. To use Plug'n'Play, you’ll want to follow the instructions above.
Set up Yarn configuration
If you’ve opted out of using PnP for dependencies, you’ll need to specify this in your .yarnrc.yml
. Add the following:
nodeLinker: "node-modules"
There’s more customizable Yarn 2 configurations documented here.
Now you’re ready to use node modules with Yarn 2!
Pruning devDependencies
The Yarn 2 package manager is modularized, so you’ll have to install the workspaces plugin in order to prune out devDependencies. This is suggested because the Node.js runtime will not need devDependencies installed, so it’s preferred to remove them after the build is complete so that they are not compiled into the slug.
In order to install, run the following:
yarn plugin import workspace-tools
Check in all the created artifacts into git with the other files that have been generated to use Yarn in the .yarn file.
Test your App
After you’ve made your changes, make sure to run your test suite on your app’s code. Once the tests have passed successfully, deploy your application to Heroku. Confirm that the build has been successful.
If you run into any issues, please open an Issue on GitHub.