cosmjs/docs/YARN.md

399 lines
14 KiB
Markdown
Raw Permalink Normal View History

2021-05-04 16:00:39 +02:00
# Yarn 2 Migration Guide
Upgrading a monorepo from Yarn v1 with Lerna.js to Yarn v2 makes use of the
weirdest versioning system I ever saw, and Yarns migration guide is not the
most helpful: although it purports to guide you through the process in
[a single document](https://yarnpkg.com/getting-started/migration), the
information you need is actually spread across multiple pages in quite a
confusing way, not helped by the poor English throughout. There is also an
[introductory blogpost](https://dev.to/arcanis/introducing-yarn-2-4eh1) which
you may find helpful.
This document is intended broadly as a replacement for the official
documentation (except where indicated), to help others get through the process
faster than I did. It wont cover every feature of Yarn v2, just enough for you
to complete the migration and be confident it was worthwhile.
2021-05-26 15:21:22 +02:00
Overall I would say that the Yarn vision is pretty impressive:
- zero installs are very cool,
- enforcing strict dependency specification gives us confidence we never had
with `node_modules`,
- delegating dependency resolution to the package manager makes a lot of sense.
However, its an open source project with limited resources, hence the difficult
documentation and slightly unstable feel. Moreover the ecosystem often does not
live up to the high standards required to reap all the benefits (eg packages not
listing all their dependencies).
## Step 1: Update Yarn v1 to the latest version (eg v1.22)
2021-05-04 16:00:39 +02:00
For example: `npm install --global yarn` or `brew upgrade yarn`.
2021-05-26 15:21:22 +02:00
## Step 2: Enable Yarn v2 in your project
2021-05-04 16:00:39 +02:00
Navigate inside the project and run `yarn set version berry`.
From the
[docs](https://yarnpkg.com/getting-started/install#per-project-install):
> "Berry" is the codename for the Yarn 2 release line. It's also the name of our
> repository!
This will create a `.yarn/` directory with a `yarn-berry.cjs` release inside and
a `.yarnrc.yml` configuration file (a new format compared to the `.yarnrc` that
was previously used).
Now run `yarn set version latest` to get a specific berry version. (Why doesnt
this happen when you set the version to berry? Good question!) You should see
the version number reflected in the `.yarn/releases/yarn-X.Y.Z.cjs` filename and
the `yarnPath` option in the `.yarnrc.yml` file.
Now if you run `yarn --version` in this repository it should tell you youre
using v2. Note that its the same binary as v1 though! Ie:
```sh
$ which yarn && yarn --version
/usr/local/bin/yarn
2.4.1
$ (cd .. && which yarn && yarn --version)
/usr/local/bin/yarn
1.22.10
```
Weird, right? 🤷
2021-05-26 15:21:22 +02:00
## Step 3: Transfer your configuration to the new configuration file
2021-05-04 16:00:39 +02:00
You might not have had either, but any configuration in a `.npmrc` or `.yarnrc`
file will need to be transferred to the newly created `.yarnrc.yml` file.
See
[Update your configuration to the new settings](https://yarnpkg.com/getting-started/migration#update-your-configuration-to-the-new-settings)
and [Configuration](https://yarnpkg.com/configuration/yarnrc). Note that these
options might secretly relate to plugins which you will need to install (for
example I added `changesetBaseRefs` and was informed it wasnt a valid
configuration option until I added the `version` plugin).
2021-05-26 15:21:22 +02:00
## Step 4: Set the Node linker to node-modules (for now)
2021-05-04 16:00:39 +02:00
One of the core concepts in Yarn v2 is the
[Zero Install](https://yarnpkg.com/features/zero-installs), ie packages that
dont need you to run `yarn install` after youve downloaded them. Powering this
is Yarn v2s PlugnPlay (or "PnP") installation strategy/module resolution
system. Well come back to this later, but at this point in the migration we
want to specify the traditional `node_modules` installation strategy and Nodes
own module resolution strategy, because thats what Yarn v1 uses:
```yml
nodeLinker: "node-modules"
```
2021-05-26 15:21:22 +02:00
## Step 5: Add any other basic configuration you need
2021-05-04 16:00:39 +02:00
For example:
```yml
# For more info see https://yarnpkg.com/advanced/telemetry
enableTelemetry: false
# See section on specifying missing dependencies below
preferInteractive: true
```
Refer to the
[configuration documentation](https://yarnpkg.com/configuration/yarnrc) (with
the same caveat as above).
2021-05-26 15:21:22 +02:00
## Step 6: Migrate the lockfile
2021-05-04 16:00:39 +02:00
Run `yarn install` and Yarn will sort it all out. It will probably give you a
bunch of warnings. Note that `yarn.lock` is now valid YAML, unlike with Yarn v1.
2021-05-26 15:21:22 +02:00
## Step 7: Tell VCS which files to ignore
2021-05-04 16:00:39 +02:00
Add all of this to your `.gitignore` (or whatever):
```
.yarn/*
!.yarn/patches
!.yarn/releases
!.yarn/plugins
!.yarn/sdks
!.yarn/versions
.pnp.*
```
Everything else thats new or changed should be committed. Well come back to
this ignore list when we revisit PlugnPlay.
2021-05-26 15:21:22 +02:00
## Step 8: Update Yarn CLI invocations and options in scripts
2021-05-04 16:00:39 +02:00
If are using the Yarn CLI tool in any scripts you will need to update some
command and option names which have changed from v1 to v2. For example
`--frozen-lockfile` has been deprecated in favour of `--immutable`. Other option
changes werent covered in the official documentation, so have fun finding out
which ones still work. A table of changes to commands can be found
[here](https://yarnpkg.com/getting-started/migration#renamed).
2021-05-26 15:21:22 +02:00
## Step 9: Add plugins
Adding a plugin updates the `.yarnrc.yml` file and adds a plugin to
`.yarn/plugins`. Here are some helpful ones, but there are more and you can even
write your own.
### `workspace-tools`
2021-05-04 16:00:39 +02:00
2021-05-26 15:21:22 +02:00
```sh
yarn plugin import workspace-tools
```
2021-05-04 16:00:39 +02:00
2021-05-26 15:21:22 +02:00
Most importantly this will let you use the `yarn workspaces foreach` command.
See [the docs](https://yarnpkg.com/cli/workspaces/foreach) for more information.
2021-05-04 16:00:39 +02:00
**NOTE:** The root project is a valid workspace, which means if you want to run
2021-05-26 15:21:22 +02:00
a script using `foreach` in all workspaces _except_ the root, other than running
a script defined in the root `package.json`, you have to filter it out.
2021-05-04 16:00:39 +02:00
**NOTE:** You probably want to use the `--parallel`, `--topological-dev` and
`--verbose` options in most cases.
2021-05-26 15:21:22 +02:00
### `version`
```sh
yarn plugin import version
```
This lets you do version things. More info: https://yarnpkg.com/cli/version
### `interactive-tools`
```sh
yarn plugin import interactive-tools
```
Most useful for `yarn upgrade-interactive`: see
https://yarnpkg.com/cli/upgrade-interactive
### `typescript` (maybe)
Automatically installs DefinitelyTyped `@types/*` definitions if the project
doesnt have its own. This sounds useful, but might actually be annoying because
sometimes you dont need the type definitions even when theyre available (eg
for tools). I installed it initially but ended up removing it.
```sh
yarn plugin import typescript
```
More info:
https://github.com/yarnpkg/berry/tree/master/packages/plugin-typescript
## Step 10: Specify missing dependencies
2021-05-04 16:00:39 +02:00
2021-05-26 15:21:22 +02:00
Yarn v2 wants to enforce dependencies strictly. You may be used to listing
2021-05-04 16:00:39 +02:00
development dependencies in the root of the project and then being able to use
the executables they define in workspaces. But Yarn v2 wont let you, so if you
2021-05-26 15:21:22 +02:00
are using any of these executables in your `package.json` scripts youll need to
add the relevant development dependency to the workspace. This doesnt mean that
2021-05-04 16:00:39 +02:00
it will install duplicates, as long as you tell it not to via
`yarn add --interactive`. (You can also set `preferInteractive` in the
`.yarnrc.yml` file.)
Note that the dependency resolution appears to be inconsistent depending on
whether you are using the `workspace-tools` plugin, and how:
- `yarn run <executable>` within workspace -> dependency must be specified in
workspace
- `yarn workspaces foreach run <executable>` in worktree -> OK if dependency is
not specified in workspace as long as it is in the worktree
- `yarn workspaces foreach --include 'my-pattern/*' run <executable>` in
worktree -> dependency must be specified in relevant workspaces
- `yarn workspaces foreach --include '*' run <executable>` in worktree -> OK if
dependency is not specified in workspace as long as it is in the worktree
- `yarn workspaces foreach --exclude my-pattern/* run <executable>` in worktree
-> OK if dependency is not specified in workspace as long as it is in the
worktree
2021-05-26 15:21:22 +02:00
(This might depend on which linker youre using.) See
https://yarnpkg.com/features/workspaces#what-does-it-mean-to-be-a-workspace for
more information on workspaces.
2021-05-04 16:00:39 +02:00
2021-05-26 15:21:22 +02:00
## Step 11: Specify local dependencies as workspaces
2021-05-04 16:00:39 +02:00
2021-05-26 15:21:22 +02:00
In packages which depend on other packages in the same monorepo, you can specify
these dependencies using the `workspace:packages/my-other-package` format. This
way you dont need to constantly update the versions manually, itll all be
calculated for you at publication time.
2021-05-04 16:00:39 +02:00
2021-05-26 15:21:22 +02:00
More info: https://yarnpkg.com/features/workspaces#workspace-ranges-workspace
2021-05-04 16:00:39 +02:00
2021-05-26 15:21:22 +02:00
## Step 12: Adjust lifecycle scripts
2021-05-04 16:00:39 +02:00
Unlike npm or Yarn v1, Yarn v2 wont run arbitrary lifecycle scripts (i.e.
`prexxx` and `postxxx`). There are
[some exceptions](https://yarnpkg.com/advanced/lifecycle-scripts), including
`postinstall`, but if youve been relying on any other lifecycle scripts you
will need to
[explicitly call them](https://yarnpkg.com/getting-started/migration#explicitly-call-the-pre-and-post-scripts)
in the main script definition.
**NOTE:** Yarn
[recommends explicitly calling the lifecycle scripts](https://yarnpkg.com/getting-started/migration#explicitly-call-the-pre-and-post-scripts)
in the main script, but I would recommend not doing that, because its going to
get confusing if people start trying to use other package managers. Its much
simpler just to put it all in the same script definition, or outsource to a
script file.
2021-05-26 15:21:22 +02:00
## Intermission: Check it works
2021-05-04 16:00:39 +02:00
2021-05-26 15:21:22 +02:00
At this point you should have a working setup. Make sure you can build, test,
lint, run scripts etc.
2021-05-04 16:00:39 +02:00
2021-05-26 15:21:22 +02:00
## Step 13: Remove shx or equivalents (probably)
2021-05-04 16:00:39 +02:00
According to
[this blog post](https://dev.to/arcanis/introducing-yarn-2-4eh1#normalized-shell):
> Yarn 2 ships with a rudimentary shell interpreter that knows just enough to
> give you 90% of the language structures typically used in the scripts field.
> Thanks to this interpreter, your scripts will run just the same regardless of
> whether they're executed on OSX or Windows.
So you probably dont need `shx` or any other tool that you were using for
cross-platform shell compatibility. Then again, maybe you do still need it
because you use a language structure outside the 90%. 🤷
2021-05-26 15:21:22 +02:00
## Step 14: Enable plug-n-play
2021-05-04 16:00:39 +02:00
Read about the problems of `node_modules` and how Yarn aims to fix them here:
https://yarnpkg.com/features/pnp#the-node_modules-problem
2021-05-26 15:21:22 +02:00
The rest of this section will take you through adding PnP. This was the most
painful part of the process, introducing many shiny new things that the rest of
the ecosystem doesnt seem quite ready for.
[Die Idee ist gut, doch die Welt noch nicht bereit](https://www.youtube.com/watch?v=SW8a7svcQGY).
If you choose to skip this section that is a totally legitimate decision.
2021-05-04 16:00:39 +02:00
### Check whether your project is ready
```sh
yarn dlx @yarnpkg/doctor@2
```
2021-05-26 15:21:22 +02:00
**NOTE:** You need to specify the `@2` because the incompatible v3 release
candidate was released as `latest` on npm.
2021-05-04 16:00:39 +02:00
By the way, this uses another new feature of Yarn v2: `yarn dlx`. This is like
2021-05-26 15:21:22 +02:00
`npx`, but downloads the package only temporarily and then throws it away.
2021-05-04 16:00:39 +02:00
### Remove the `nodeLinker` setting from `.yarnrc.yml`.
2021-05-26 15:21:22 +02:00
This uses the default PnP setting, which is the real Yarn v2 magic.
2021-05-04 16:00:39 +02:00
### Install again
2021-05-26 15:21:22 +02:00
Run `yarn`. This will remove the `node_modules/` directory and store lots of zip
files in `.yarn/cache`.
2021-05-04 16:00:39 +02:00
### Update the VCS ignore list
Remove what you put there before and add these:
```
.yarn/*
!.yarn/cache
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/sdks
!.yarn/versions
```
2021-05-26 15:21:22 +02:00
Basically were adding the cache and the `.pnp.js` file to VCS. It might seems
weird to add all those zip files to version control, but the reasoning is in the
article listed above.
Before you add these to the VCS index, you might want to think about how you
want to store the large zip files. For example, if youre using Git LFS you
could get it to handle zip files by adding the following to `.gitattributes`:
```
*.zip filter=lfs diff=lfs merge=lfs -text
```
2021-05-04 16:00:39 +02:00
### Run node using yarn node
2021-05-26 15:21:22 +02:00
Replace calls to `node` outside of a `package.json` script with `yarn node`. For
example in shebangs in development scripts. You can pass the `-S` option to make
this work like this:
```sh
#!/usr/bin/env -S yarn node
```
You probably dont want to update executables you will ship to your users
because they may not be using Yarn, but that means youll have to remember to
run them using `yarn node` from within your project rather than just executing
them directly.
### Add in support for ESM (if needed)
Running Node via Yarn v2 does not handle ESM as described in this issue:
https://github.com/yarnpkg/berry/issues/638
For a quick solution, you can run `yarn add -D esm` in every relevant package,
and then replace every `yarn node script.js` with a
`yarn node --require esm script.js`.
For a more general workaround, check out this repo:
https://github.com/DaneTheory/yarn-pnp-with-esm
### Maybe dont use Node v15+ until you upgrade to Yarn v3(!!!)
It might not affect you but theres an issue with the `fs` patch and `bigint`,
which is solved in v3, but wont be backported to v2:
https://github.com/yarnpkg/berry/issues/2232#issuecomment-818514929
### Setup your IDE
Make sure you have everything you want your IDE to use installed in the root of
the project. I suggest `typescript` and `prettier` at least. Then run
2021-05-04 16:00:39 +02:00
2021-05-26 15:21:22 +02:00
```sh
2021-07-21 10:02:38 +02:00
yarn dlx @yarnpkg/sdks
2021-05-26 15:21:22 +02:00
```
This will set up your IDE and put a bunch of things in `.yarn/sdks`, which
youll want to add to VCS. If youre using VSCode, it will also add some stuff
to `.vscode/extensions.json` and `.vscode/settings.json`. You may or may not
want to add these to VCS—talk to your colleagues.
https://next.yarnpkg.com/advanced/pnpify#ide-support
## Step 15: Switch versioning from Lerna to Yarn
2021-05-04 16:00:39 +02:00
2021-05-19 15:37:25 +02:00
Lerna unfortunately appears to be unmaintained. Remove the dependency and the
`lerna.json` configuration file.
2021-05-04 16:00:39 +02:00
2021-05-26 15:21:22 +02:00
You can read about Yarns release workflow here:
2021-05-04 16:00:39 +02:00
https://next.yarnpkg.com/features/release-workflow
2021-05-26 15:21:22 +02:00
## Step 16: Consider using constraints
2021-05-19 19:05:07 +02:00
2021-05-26 15:21:22 +02:00
E.g. to ensure that each package specifies the right fields in its
`package.json`. Bonus: you get to learn Prolog! (I for one did not have time.)
2021-05-19 19:05:07 +02:00
2021-05-26 15:21:22 +02:00
More info: https://yarnpkg.com/features/constraints
## Conclusion
Thats it! Theres a lot more configuration available that has not been covered
here, but hopefully you made it through all that and your code still works.
2021-05-26 17:44:12 +02:00
## Links
Here are some additional resources I found helpful:
- https://www.huy.dev/yarn-v2-workspace-docker-vs-code-2020-03-23/
- https://github.com/DerekZiemba/yarn-V2-workspaces-simple-monorepo/issues/1