Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Force yarn install instead of npm install for Node module?

I want to force using yarn install instead of npm install. I want to raise error in npm install. What should I do in package.json?

like image 232
Matt - sanemat Avatar asked Dec 10 '16 13:12

Matt - sanemat


People also ask

Can I use Yarn install instead of NPM install?

Migrating from npm should be a fairly easy process for most users. Yarn can consume the same package. json format as npm, and can install any package from the npm registry.

Can Yarn work without NPM?

As I noted above, npm comes preinstalled with Node, so there's no need to install npm manually. In this case, berry is the version we want to set. With Yarn we can use a different version for each project. To do the same with npm, you'll need to have nvm (Node Version Manager) installed.

Does Yarn install to node_modules?

yarn install --focusShallowly installs a package's sibling workspace dependencies underneath its node_modules folder. This allows you to run that workspace without building the other workspaces it depends on.


3 Answers

UPDATE: Alexander's answer is the better solution and uses the same technique I describe here. I am leaving my answer in tact for posterity. The original point of my answer was to show that you can execute a small node script which should work on all platforms.

In your preinstall script you can run a mini node script which should work on all platforms, whereas things like pgrep (and other common *nix commands and operators) won't work on Windows until Windows 10 has received widespread adoption.

I tested the below script on Node v4.7.0 (npm v2.15.11) and Node v7.2.1 (npm v3.10.10). I assume it works on everything in between. It works by checking the environment variables on the currently running process - the npm_execpath is the path to the currently running "npm" script. In the case of yarn, it should point to /path/to/yarn/on/your/machine/yarn.js.

"scripts": {     "preinstall": "node -e \"if(process.env.npm_execpath.indexOf('yarn') === -1) throw new Error('You must use Yarn to install, not NPM')\"" } 

You can read more about npm scripts here: https://docs.npmjs.com/misc/scripts

As far as the npm_execpath environment variable, while not documented I doubt that it will ever change. It's been around for multiple major releases of npm and it doesn't really pass the "there's a better name for this" test.

like image 154
Ryan Wheale Avatar answered Sep 23 '22 16:09

Ryan Wheale


Most of the answers here involve hacky scripts but there's a built in way to achieve this which I posted over on the Yarn github issue. Unlike soe of the other ways, this works for any and all NPM commands.

You add a fake engine version like so in package.json (you may want to tweak the yarn and node entries):

  "engines": {
    "npm": "please-use-yarn",
    "yarn": ">= 1.17.3",
    "node": ">= 12.5.0"
  }

Then you add an .npmrc file to the project root with this:

engine-strict = true

Running NPM then raises an error:

npm ERR! code ENOTSUP
npm ERR! notsup Unsupported engine for root@: wanted: {"npm":"please-use-yarn","yarn":">= 1.17.3","node":">= 12.5.0"} (current: {"node":"12.9.1","npm":"6.10.2"})
npm ERR! notsup Not compatible with your version of node/npm: root@
like image 32
Adam Thomas Avatar answered Sep 23 '22 16:09

Adam Thomas


Like the other answers, I'd recommend using a preinstall script and checking your environment. For a portable solution that won't have false-positives if another npm process happens to be running, using node -e 'JS_CODE' is probably the best option.

In that JS code, you can check the package manager's path using the following:

process.env.npm_execpath

Yarn's binary is yarn.js, compared to npm-cli.js used by NPM. We can use a regex like the following to check that this string ends with yarn.js.

/yarn\.js$/

By using this regex, we can be sure it won't accidentally match somewhere earlier in the file system. Most-likely yarn won't appear in the file path, but you can never be too sure.

Here's a minimal example:

{
  "name": "test",
  "version": "1.0.0",
  "scripts": {
    "preinstall": "node -e 'if(!/yarn\\.js$/.test(process.env.npm_execpath))throw new Error(\"Use yarn\")'"
  }
}

Of course, the user will still be able to get around this check be editing the JSON or using the --ignore-scripts options:

npm install --ignore-scripts
like image 23
Alexander O'Mara Avatar answered Sep 24 '22 16:09

Alexander O'Mara