Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

yarn global installs don't get shimmed #42

Closed
dbernheisel opened this issue May 12, 2017 · 24 comments
Closed

yarn global installs don't get shimmed #42

dbernheisel opened this issue May 12, 2017 · 24 comments
Labels

Comments

@dbernheisel
Copy link
Contributor

Steps to reproduce:

asdf plugin-install nodejs https://github.com/asdf-vm/asdf-nodejs
asdf install nodejs 7.10.0
asdf global nodejs 7.10.0
npm -g install yarn
yarn global add eslint
# eslint is not shimmed, so I cannot execute eslint without an absolute path

npm -g install eslint
# eslint is shimmed now in ~/.asdf/shims
# eslint works

Looking at the source, it seems that npm is the only package manager that's managed in this plugin for postinstall hooks for shimming.

@dbernheisel
Copy link
Contributor Author

In light of npm5, this is less of an issue for me. If you think it's worth the effort to build in yarn support, let me know and I'm willing to contribute a PR. Otherwise maybe this should be a note in the readme to indicate yarn global installs are not supported.

@lustrousgorilla
Copy link

FWIW I'd definitely appreciate yarn support.

@doughsay
Copy link

doughsay commented Nov 5, 2017

http://blog.scottlogic.com/2017/06/06/does-npm5-deprecate-yarn.html
npm 5 is better, but still not as good as yarn... I'd like first-class support for yarn in this plugin as well.

@gipcompany
Copy link

I think this issue is not only about yarn, but also all the packages installed globally are involved!

e.g.) npm-check-updates is the same as below.

$ npm install -g npm-check-updates
$ which npm-check-updates
$ npm-check-updates -u
bash: npm-check-updates: command not found

So, this issue should be fixed.

@dbernheisel
Copy link
Contributor Author

@gipcompany I think that's slightly different. If you run asdf reshim nodejs you'll probably find your global shim now. See #47 and #56

@b0o
Copy link
Contributor

b0o commented May 5, 2018

You can fix this by configuring yarn to use a custom global prefix path.

You can run yarn config set prefix ~/.yarn, which will add the following line to your ~/.yarnrc:

prefix "/home/maddy/.yarn"

Then, just add ~/.yarn/bin to your PATH in your shell rc file, e.g. ~/.zshrc:

# Yarn bin
export PATH="$PATH:$HOME/.yarn/bin"

See yarnpkg/yarn#630 for some more info.


Working example to show that installing global binary packages with yarn works as expected:

$ which yarn # yarn is installed via `npm` managed by `asdf`
/home/maddy/.asdf/shims/yarn

$ which grunt # grunt isn't installed yet
grunt not found

$ yarn global add grunt # globally install grunt with yarn 
yarn global v1.6.0
[1/4] Resolving packages...
[2/4] Fetching packages...
info [email protected]: The platform "linux" is incompatible with this module.
info "[email protected]" is an optional dependency and failed compatibility check. Excluding it from installation.
[3/4] Linking dependencies...
[4/4] Building fresh packages...
success Installed "[email protected]" with binaries:
      - grunt
Done in 2.28s.

$ which grunt # grunt should now be installed and available in your `PATH`
/home/maddy/.yarn/bin/grunt

$ grunt --version # verify that we can successfully call grunt
grunt-cli v1.2.0

@taiansu
Copy link
Contributor

taiansu commented May 15, 2018

yarn config set prefix doesn't work for me for some reason.
But I end up with use yarn global dir to find where yarn install the global modules, then put
~/.local/share/yarn/global/node_modules/.bin in my $PATH.

@mohsenkhanpour
Copy link

is this issue still present?

@dbernheisel
Copy link
Contributor Author

Ya, I believe it's still present. Even though I opened the issue, I don't think this should be fixed.

Yarn doesn't recommend npm install -g yarn as an installation method anyway (https://yarnpkg.com/lang/en/docs/install), and I don't think it's ever been recommended to install via npm.
image

If you're on a mac and install it via brew, or another system packager, you don't need asdf to shim packages that're installed via yarn since yarn is installed somewhere else on your system, and caches in different locations, and works independently of the nodejs version. asdf-nodejs only needs to worry about the nodejs version at this point, which in my book is 👍

Or, you could use npm which asdf-nodejs does shim bins for. Sometimes you have to run asdf reshim nodejs to make those npm install -g mypackage to be recognized, but it works. And ever since npm@5 supported lock files, it's been suitable for use again.

Maybe there are compelling reasons for asdf-nodejs to support shimming yarn global installs, but I haven't found any yet. Let me know if you know of any.

@mohsenkhanpour
Copy link

@dbernheisel Yes, I installed yarn via apt and this was solved. Also other issues have been resolved by asdf reshim too. Also there is a PR to throttle postinstall so it only runs after the last package.
I guess we can close this issue as it can be misleading to new users trying out asdf.

@squarism
Copy link

squarism commented Dec 5, 2018

@dbernheisel The reshim tip worked for me, great! TIL about yarn not recommending -g installs. The problem is, my equivalent on mac is brew. If I brew install yarn, I get node (because it's a dependency). Maybe that's a good idea, keeping a brew yarn and a dev target of node distinct? Or perhaps it defeats the point of asdf? What do you think?

@dbernheisel
Copy link
Contributor Author

@squarism https://yarnpkg.com/en/docs/install#mac-stable
brew install yarn --without-node might be what you're looking for

@mohsenkhanpour
Copy link

mohsenkhanpour commented Dec 6, 2018 via email

@dboune
Copy link

dboune commented Mar 13, 2019

asdf v0.7.0 (installed via homebrew)
node v10.15.3 (installed via asdf)

$ brew install yarn --ignore-dependencies
🍺  /usr/local/Cellar/yarn/1.13.0: 14 files, 4.7MB, built in 8 seconds

$ yarn global bin
/Users/username/.asdf/installs/nodejs/10.15.3/.npm/bin

$ yarn global add grunt
yarn global v1.13.0
[1/4] 🔍  Resolving packages...
[2/4] 🚚  Fetching packages...
[3/4] 🔗  Linking dependencies...
[4/4] 🔨  Building fresh packages...
success Installed "[email protected]" with binaries:
      - grunt
✨  Done in 4.92s.

$ which grunt
$ asdf reshim
$ which grunt
/Users/username/.asdf/shims/grunt

$ grunt --version
grunt-cli v1.2.0

I found the below behavior a little strange. I think I'd rather just have the shim not exist if not installed for a given version.

Due to one unfortunate nature of Yarn (one global install for all), after performing a global add <package> while set to a particular node version all installed bins will be symlinked.

This can seem a bit odd. If you switch to another node version, and are expecting this behavior, you'll need to run yarn global add, and then run asdf reshim before the bins will be available to you.

It might be best to have yarn use a private bin folder -- often defaulted to /usr/local/bin for MacOS, for example as occurs naturally when using nvm (nvm is not compatible with npm's prefix config, and screams loudly about it if it is set).

$ asdf global nodejs 8.10.0
$ which grunt
/Users/username/.asdf/shims/grunt
$ grunt --version
asdf: No version set for command grunt
you might want to add one of the following in your .tool-versions file:

nodejs 10.15.3

# yarn hasn't yet symlinked bins for this version in my case, so naturally this won't work.
$ asdf reshim
$ which grunt
/Users/username/.asdf/shims/grunt
$ grunt --version
asdf: No version set for command grunt
you might want to add one of the following in your .tool-versions file:

nodejs 10.15.3

$ asdf global nodejs 10.15.3
$ which grunt
/Users/username/.asdf/shims/grunt
$ grunt --version
grunt-cli v1.2.0

It certainly would be nice if shims could be recreated after yarn global add. There doesn't appear to be a way to configure yarn to do this -- no apparent post-global add hook.

I'm coming to the conclusion that it may be best to manage global packages using NPM. I've had some trouble in the past with global packages that require node-gyp when installing with yarn, using a version manager, and needing those packages to be available for multiple versions of node.

@brewster1134
Copy link

brewster1134 commented Mar 30, 2019

until a solution is added to asdf-nodejs, i wrote a script to handle this.

when you initialize a shell session, it adds the bin path of the current version of node to your PATH.
if you change to another directory that uses a different version of node, after asdf symlinks to that new version, this script will replace the previous node bin path, with the new one.

drop this in your .shellrc file

i did some basic smoke tests, but let me know if something isn't acting right

on_change_dir() {
  # -> asdf-nodejs
  local nodejs_current
  if nodejs_current=$(asdf current nodejs); then
    # add current path the first time
    if [ ! $nodejs_current_version ]; then
      local nodejs_current_path=$(asdf where nodejs)
      export PATH=$nodejs_current_path/.npm/bin:$PATH
    fi
    
    # set next version to extracted current semantic version
    local nodejs_next_version=$(echo $nodejs_current | cut -d '(' -f 1 | xargs)
    
    # set current version to next version if it has not been set yet
    nodejs_current_version=${nodejs_current_version-$nodejs_next_version}
    
    # check if version has changed
    if [ $nodejs_current_version != $nodejs_next_version ]; then
      local nodejs_current_path=$(asdf where nodejs $nodejs_current_version)
      local nodejs_next_path=$(asdf where nodejs)
  
      # update path with new path
      PATH=${PATH/$nodejs_current_path/$nodejs_next_path}
  
      # update current version
      nodejs_current_version=$nodejs_next_version
    fi
  else
    echo "No nodejs version set. Type `asdf list-all nodejs` for all versions."
  fi
}
function chpwd { on_change_dir }
on_change_dir

@Fenntasy
Copy link

Fenntasy commented Jun 1, 2019

Couldn't yarn decome a first class citizen on asdf-nodejs like it is in the docker node containers?

@bo5o
Copy link

bo5o commented May 13, 2020

Yarn doesn't recommend npm install -g yarn as an installation method anyway (https://yarnpkg.com/lang/en/docs/install), and I don't think it's ever been recommended to install via npm.
image
...

Things have changed with yarn 2. They now recommend to install yarn globally with npm and then spawn a per-project installation with the globally installed version.

If I understand correctly, this means that there is no need for multiple yarn installations anymore and installation via <your OS-specific tool> is more suitable.

@Nezteb
Copy link

Nezteb commented May 24, 2020

... Even though I opened the issue, I don't think this should be fixed.

Yarn doesn't recommend npm install -g yarn as an installation method anyway (yarnpkg.com/lang/en/docs/install), and I don't think it's ever been recommended to install via npm.

@dbernheisel: @cbows is correct above. Yarn 2 behaves differently now. asdf reshim nodejs works for me, but I'd rather not have to run that every time I install a package via yarn global add xyz.

If I have to I will uninstall my npm version of yarn and instead use brew install yarn --without-node, but the reason I switched to asdf in the first place was to manage all language and tooling installs on my machine with a single tool.

(I don't mind either way; this is just my personal preference.)

@dbernheisel
Copy link
Contributor Author

dbernheisel commented May 24, 2020

My comments above about Yarn are 2+ yrs old and about Yarn 1. I haven't used Yarn 2 yet, but looks like it should be treated differently so perhaps this can be fixed now?

I'm not familiar with Yarn 2, but I'm sure the maintainers will accept PRs to make asdf-nodejs better. Since I don't use Yarn 2 I'm not well-suited to contribute at this point.

@emmanuelkant
Copy link

yarn config set prefix doesn't work for me for some reason.
But I end up with use yarn global dir to find where yarn install the global modules, then put
~/.local/share/yarn/global/node_modules/.bin in my $PATH.

For me, this works. The prefix doesn't work and I do not know why. By the way, I think that is a better way to fix this issue.

@misraelson
Copy link

In 2021 @b0o solution worked for me. Must admit a bit of a pain in the 🍑 when simply trying to add global packages like expo etc via yarn

@codering
Copy link

codering commented Dec 6, 2021

You can do like this:

export PATH="$(yarn global bin):$PATH"

@dyegros
Copy link

dyegros commented May 24, 2022

Unfortunelly the problem persists.

In fact, it becomes more problematic due to changes on yarn installation instructions.

As @dbernheisel mentioned, using npm install -g yarn was not recommend. But now, the new recommendation (since Node version 16.10.0) is use embedded yarn (if I understood correctly) boarded on new nodejs versions.

Using the command corepack enable the user will able to use yarn binaries delivered with Node (it means no more need to use homebrew, for example).

Well, this new method doesn't work with 'asdf' too. You need to manually reshim nodejs to allow you call this embedded yarn after run corepack enable.

And, of course, any subsequent call of yarn global add <package-name> stills require another reshim to allow user interact with new global packages.

About change yarn configurations (like yarn config set prefix) or even change PATH environment variable, I believe it cannot be an user task, it must be automated in someway. The suggestion from @brewster1134 whom created a catching .tool-versions loading script and react changing $PATH seems a good idea to me, but I'm not sure it solve all scenarios (at least the corepack enable use case isn't covered).

@augustobmoura
Copy link
Member

augustobmoura commented May 25, 2022

I don't see why this would be a worse problem in yarn v2 as system-wide installations have been removed. Apparently, since its inception (more on this github issue). And I agree with this direction. The best recommendation for using commands from packages is by using either npx or yarn dlx, as it solves a lot of problems that might arise from having different installations of the same package in different node versions/prefixes.

If you are sure about installing global commands (there are some fair points to do it), the recommended way would be not to run yarn global add at all and stick to using npm install -g. Because they are global installs, there's no practical difference between using npm or yarn for it (aside from performance, that by itself is questionable as npm is getting faster as it's being actively updated, differently from yarn v1)

As this was a decision made by the yarn team itself, I'm marking this issue as wontfix. We are already support auto-reshimming of npm global installs, that should be on all occasions virtually the same as yarn global installs. If you are adamant about using yarn instead of npm, you can implement a wrapper on your own. Just adding a function like this to your .bashrc/.zshrc should suffice for the most cases:

yarn() {
  command yarn "$@"
  if [ "$1" = global ]; then
    asdf reshim nodejs
  fi
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests