How to force package installs to use yarn not npm

ascorbic

Matt Kane

Posted on January 18, 2019

How to force package installs to use yarn not npm

Leaving aside arguments over which node package manager is better, one thing that should be clear is that it's a bad idea to switch between them in the same project, as conflicting lockfiles can leave the project in an unpredictable state. If you run yarn in a project that has a package-lock.json from npm then it does warn you about this, but npm doesn't do the reverse. If you run npm install in a project with a yarn.lock it will happily install the packages and create a package-lock.json for yarn to complain about next time. This is my solution.

If you add a "preinstall" script to your package.json it is run before any install by npm or yarn. If it exits with an error code then the install is aborted. This means it's the perfect place to check. During script execution, the environment variable $npm_execpath is set to the path of the npm or yarn executable, so we can use this to check what the install is using. You could use node to check this, but that seems like overkill, so I'm going to use shell commands directly inside the script. I echo the contents of the variable, pipe it to grep, and if it doesn't match yarn then it exits with an error. (I ❤️ emojis in shell scripts):

echo "$npm_execpath" | grep -q "yarn\.js$" || (echo '⚠️ Use yarn not npm! ⚠️' && exit 1)
Enter fullscreen mode Exit fullscreen mode

This works great, but it can look confusing as it displays the full command when it's run, so looks like there's an error even when all is well. The way around this is to make it a separate script, which is run with the --quiet flag. We can use $npm_execpath again to be sure we're running it with the same script:

"scripts": {
        "preinstall": "$npm_execpath --silent run checkyarn",
        "checkyarn": "echo \"$npm_execpath\" | grep -q \"yarn\\.js$\" || (echo '⚠️  Use yarn not npm! ⚠️ ' && echo && exit 1)"
}

Enter fullscreen mode Exit fullscreen mode

If you run npm install you get the error:

example git:(master) ✗ npm i

> example@0.0.1 preinstall /Users/matt/Documents/repos/example
> $npm_execpath --silent run checkyarn

⚠️  Use yarn not npm! ⚠️

npm ERR! code ELIFECYCLE
errno 1
Enter fullscreen mode Exit fullscreen mode

...but if you run yarn:

➜  example git:(master) ✗ yarn
yarn install v1.12.3
$ $npm_execpath --silent run checkyarn
[1/4] 🔍  Resolving packages...
success Already up-to-date.
✨  Done in 1.35s.
Enter fullscreen mode Exit fullscreen mode

Happy installing!

💖 💪 🙅 🚩
ascorbic
Matt Kane

Posted on January 18, 2019

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related