Managing packages with Yarn - yarnpkg

I need to update old dependencies because of security reasons in a project, that uses Yarn and I would like to know the best way to do this. I have used yarn add package-name#latest and yarn upgrade package-name#latest with the same result. The old version package definition remains. Is that acceptable? Since I have to update the old version for security, I think the old version should be removed. Is there a command that updates a package to a specific version and removes the old package definition?

The situation you are describing should only arise if you also have transitive dependencies that come from other dependencies.
So you may have another package that depends on acorn in a lower version.
If this is not the case I would try:
yarn upgrade package-name --latest
To update all packages to the latest versions, I recommend:
yarn upgrade-interactive --latest

Related

`yarn add` installs stale version of local .tgz

I am using yarn to install a package from a .tgz. When I update the package and install it again, yarn uses an old cached version of the package. Here is a report from someone running into a similar problem. If I try to delete the package from the cache, it gives me errors, and if I use yarn cache clean it will clear the whole cache, which is also not what I want.
The reason the package is changing is that I am developing it, and don't want to bump the version number every five minutes. I read maybe newer yarn versions take the package hash into account when installing, but I am stuck with version 1.22.1 (actually jlpm which is JupyterLab's vendored version of yarn).
Is there a way to say yarn add package-0.1.0.tgz --dont-use-cache? Or should I just skip yarn and use npm, or something else on top?

Update previously patched package with Yarn Berry

I'm using Yarn#3.0.2 in my project.
I have patched a package (#pkg/pkg) with the command yarn patch #pkg/pkg and I am using it as a devDependency with the patch: protocol.
Now I need to make another patch to the same package - but when I run the same command I get Multiple candidate packages found [...].
It works when trying to target the original package (using yarn patch #pkg/pkg#x.x.x), but I can't seem to find a way to target the patched project.
Any skilled yarn developer out there?
(Possibly useful information: I cannot use the resolutions field for the patch since #pkg/pkg is a CLI which does not seem to work with this approach)
The solution was choose the patch suggested with the error and encapsule it in qoutes such as:
yarn patch "patch:..."

How do I avoid lock file conflicts with PNPM?

Our team uses PNPM and a recurring problem is that we seem to have different versions of the pnpm command installed, causing lock files git conflicts when adding or updating packages. PNPM is a global tool, so I am not totally sure how to handle this situation. Some Node tools have a global CLI interface (Grunt), but utilize a locally installed package to avoid this issue. Does PNPM have a way to ensure consistent behavior across the team to avoid lock file conflicts and such?
The current recommended approach is to declare which pnpm version should be used in the project. It may be done via the engines field of packages.json. For instance, if your project should be used with pnpm v6, add this to package.json:
{
"engines": {
"pnpm": "6"
}
}
If someone will run pnpm install using a different version of pnpm, an error will be thrown.
In the future we might automatically download the right version of pnpm and use it. Kind of how Yarn does it with version policies.

Committing .yarn directory to git when using yarn berry

In the next version of yarn ("berry") the manual states that one should just commit the directory created called .yarn, but if you use the multi-version setup for yarn, this directory contains the file releases/yarn-berry.js which seems to be the entire berry version of yarn, taking up more than 2MB of disk.
This just seems really wrong - why should I commit a package manager to git, just to get it to work?
The Yarn developers explain the rationale for this in the Installation docs, in the section called "About global installs":
Using a single package manager across your system has always been a problem. To be stable, installs need to be run with the same package manager version across environments, otherwise there's a risk we introduce accidental breaking changes between versions - after all, that's why the concept of lockfile was introduced in the first place! And with Yarn being in a sense your very first project dependency, it should make sense to "lock it" as well.
Once Yarn is tracked and "locked" as a per-project dependency, it ends up getting committed to Git if you follow Yarn 2's zero-install strategy, the rationale for which is explained here.
I'm a newcomer to Yarn, but I spent years working devops, helping developers figure out why their code would sometimes build correctly on half of the team's laptops but not on the other half, or would suddenly start failing to build in CI while continuing to work elsewhere. Trying to keep the version of npm consistent across every computer and codebase in the company was essentially impossible, given that Node is constantly being upgraded, but locking each project to its own specific version of Yarn -- which, by being committed to Git, is guaranteed to be available in every checkout of that project -- solves this problem.
I have written a small tool for those people who don't want to commit Yarn 2+ binary into their git repos, while still benefiting from sticking Yarn version per project. If you already have Yarn 2+ configured in your project just don't want to commit it, you can run:
yarn dlx pinyarn
This command will generate .pinyarn.js (4KB) which you should commit, instead. .pinyarn.js will contain URLs inside to download Yarn 2+ and its plugins from the official Yarn Berry GitHub repo. .pinyarn.js will download binary and plugins from these URLs if they are not downloaded yet.
You can also specify which version of Yarn 2+ you want via:
yarn dlx pinyarn 3 - the latest released Yarn 3 version, or
yarn dlx pinyarn 2.2.2 - version 2.2.2, or
yarn dlx master - version from latest sources, or
yarn dlx 1638 - version from Pull Request 1638
The pinyarn tool repo on GitHub:
https://github.com/sysgears/pinyarn
The official documentation mentions what's should be ignored and what should be committed. It can solve this problem I think.
https://yarnpkg.com/getting-started/qa#which-files-should-be-gitignored
The new docs states using node's newest corepack feature (to date).
This means that when using appropriate node you only need to place a valid packageManager field value in package.json and run corepack enable, e.g.
{
"name": "foo",
"packageManager": "yarn#3.2.0",
"scripts": {
...
}
}

Should I commit the yarn.lock file and what is it for?

Yarn creates a yarn.lock file after you perform a yarn install.
Should this be committed to the repository or ignored? What is it for?
Yes, you should check it in, see Migrating from npm
What is it for?
The npm client installs dependencies into the node_modules directory non-deterministically. This means that based on the order dependencies are installed, the structure of a node_modules directory could be different from one person to another. These differences can cause works on my machine bugs that take a long time to hunt down.
Yarn resolves these issues around versioning and non-determinism by using lock files and an install algorithm that is deterministic and reliable. These lock files lock the installed dependencies to a specific version and ensure that every install results in the exact same file structure in node_modules across all machines.
Depends on what your project is:
Is your project an application? Then: Yes
Is your project a library? If so: No
A more elaborate description of this can be found in this GitHub issue where one of the creators of Yarn eg. says:
The package.json describes the intended versions desired by the original author, while yarn.lock describes the last-known-good configuration for a given application.
Only the yarn.lock-file of the top level project will be used. So unless ones project will be used standalone and not be installed into another project, then there's no use in committing any yarn.lock-file – instead it will always be up to the package.json-file to convey what versions of dependencies the project expects then.
I see these are two separate questions in one. Let me answer both.
Should you commit the file into repo?
Yes. As mentioned in ckuijjer's answer it is recommended in Migration Guide to include this file into repo. Read on to understand why you need to do it.
What is yarn.lock?
It is a file that stores the exact dependency versions for your project together with checksums for each package. This is yarn's way to provide consistency for your dependencies.
To understand why this file is needed you first need to understand what was the problem behind original NPM's package.json. When you install the package, NPM will store the range of allowed revisions of a dependency instead of a specific revision (semver). NPM will try to fetch update the dependency latest version of dependency within the specified range (i.e. non-breaking patch updates). There are two problems with this approach.
Dependency authors might release patch version updates while in fact introducing a breaking change that will affect your project.
Two developers running npm install at different times may get the different set of dependencies. Which may cause a bug to be not reproducible on two exactly same environments. This will might cause build stability issues for CI servers for example.
Yarn on the other hand takes the route of maximum predictability. It creates yarn.lock file to save the exact dependency versions. Having that file in place yarn will use versions stored in yarn.lock instead of resolving versions from package.json. This strategy guarantees that none of the issues described above happen.
yarn.lock is similar to npm-shrinkwrap.json that can be created by npm shrinkwrap command. Check this answer explaining the differences between these two files.
You should:
add it to the repository and commit it
use yarn install --frozen-lockfile and NOT yarn install as a default both locally and on CI build servers.
(I opened a ticket on yarn's issue tracker to make a case to make frozen-lockfile default behavior, see #4147).
Beware to NOT set the frozen-lockfile flag in the .yarnrc file as that would prevent you from being able to sync the package.json and yarn.lock file. See the related yarn issue on github
yarn install may mutate your yarn.lock unexpectedly, making yarn claims of repeatable builds null and void. You should only use yarn install to initialize a yarn.lock and to update it.
Also, esp. in larger teams, you may have a lot of noise around changes in the yarn lock only because a developer was setting up their local project.
For further information, read upon my answer about npm's package-lock.json as that applies here as well.
This was also recently made clear in the docs for yarn install:
yarn install
Install all the dependencies listed within package.json
in the local node_modules folder.
The yarn.lock file is utilized as follows:
If yarn.lock is present and is enough to satisfy all the dependencies
listed in package.json, the exact versions recorded in yarn.lock are
installed, and yarn.lock will be unchanged. Yarn will not check for
newer versions.
If yarn.lock is absent, or is not enough to satisfy
all the dependencies listed in package.json (for example, if you
manually add a dependency to package.json), Yarn looks for the newest
versions available that satisfy the constraints in package.json. The
results are written to yarn.lock.
If you want to ensure yarn.lock is not updated, use --frozen-lockfile.
From My experience I would say yes we should commit yarn.lock file. It will ensure that, when other people use your project they will get the same dependencies as your project expected.
From the Doc
When you run either yarn or yarn add , Yarn will generate a yarn.lock file within the root directory of your package. You don’t need to read or understand this file - just check it into source control. When other people start using Yarn instead of npm, the yarn.lock file will ensure that they get precisely the same dependencies as you have.
One argue could be, that we can achieve it by replacing ^ with --. Yes we can, but in general, we have seen that majority of npm packages comes with ^ notation, and we have to change notation manually for ensuring static dependency version.But if you use yarn.lock it will programatically ensure your correct version.
Also as Eric Elliott said here
Don’t .gitignore yarn.lock. It is there to ensure deterministic dependency resolution to avoid “works on my machine” bugs.
Not to play the devil's advocate, but I have slowly (over the years) come around to the idea that you should NOT commit the lock files.
I know every bit of documentation they have says that you should. But what good can it possibly do?! And the downsides far outweigh the benefits, in my opinion.
Basically, I have spent countless hours debugging issues that have eventually been solved by deleting lock files. For example, the lock files can contain information about which package registry to use, and in an enterprise environment where different users access different registries, it's a recipe for disaster.
Additionally, the lock files can really mess up your dependency tree. Because yarn and npm create a complex tree and keep external modules of different versions in different places (e.g. in the node_modules folder within a module in the top node_modules folder of your app), if you update dependencies frequently, it can create a real mess. Again, I have spent tons of time trying to figure out what an old version of a module was still being used in a dependency wherein the module version had been updated, only to find that deleting the lock file and the node_modules folder solved all the hard-to-diagnose problems.
I even have shell aliases now that delete the lock files (and sometimes node_modules folders as well!) before running yarn or npm.
Just the other side of the coin, I guess, but blindly following this dogma can cost you........
I'd guess yes, since Yarn versions its own yarn.lock file:
https://github.com/yarnpkg/yarn
It's used for deterministic package dependency resolution.
Yes! yarn.lock must be checked in so any developer who installs the dependencies get the exact same output! With npm [that was available in Oct 2016], for instance, you can have a patch version (say 1.2.0) installed locally while a new developer running a fresh install might get a different version (1.2.1).
Yes, You should commit it. For more about yarn.lock file, refer the official docs here

Resources