Windows Subsystem for Linux (WSL) using shared Node.js installation with Windows: Node.js npm & npx binaries not working
Asked Answered
B

6

8

I have recently moved to a Windows + WSL environment (WSL is going very good by the way). The main reason of doing this is to have a Linux environment for development and having Windows for other apps & games without having to reboot my computer (had a dual-boot setup before).

In the setup process, I found most of the Windows installed binaries can be executed from WSL. So instead of duplicating installations (eg: installing java and maven in Windows in order to use Eclipse IDE and then installing it in WSL separately to use it in the terminal) I could just install java jdk in Windows and symlink the binaries to WSL in order to share the jdk installation, this worked flawlessly). But doing the same with node, happens that node npm and npx binaries are not working :(

I wannted to have a single node installation which I could manage using using nvm windows. So I started the installation the following way:

In WSL, I configured my /etc/wsl.conf, following Nick Janetakis guide here (thanks Nick) in order to mount Windows drives at / instead of /mnt/:

/etc/wsl.conf

[automount]
root = /
options = "metadata"

Then installed node in windows:

C:\Windows\system32> nvm install 10.15.0
... installing process...
C:\Windows\system32> nvm use 10.15.0
...success message...
C:\Windows\system32> node -v
v10.15.0
C:\Windows\system32> npm -v
6.4.1

Everything working as expected so far. The next step is to symlink the windows node binaries to WSL. The binaries are located at:

C:\Windows\system32> where node
C:\Program Files\nodejs\node.exe

C:\Windows\system32> where npm
C:\Program Files\nodejs\npm
C:\Program Files\nodejs\npm.cmd

C:\Windows\system32>where npx
C:\Program Files\nodejs\npx
C:\Program Files\nodejs\npx.cmd

So inside WSL terminal (remember that my disks are mounted at /c not /mnt/c as the default behaviour):

user@host:~$ mkdir ~/bin
user@host:~$ ln -s /c/Program\ Files/nodejs/node.exe ~/bin/node
user@host:~$ ln -s /c/Program\ Files/nodejs/npm ~/bin/npm
user@host:~$ ln -s /c/Program\ Files/nodejs/npx ~/bin/npx

And...

user@host:/d/tmp$ node -v
v10.15.0
user@host:/d/tmp$ echo "console.log('Hello World');" >> index.js
user@host:/d/tmp$ node index.js
Hello World

Great! (Note: as node is installed on windows, when being on WSL you must use it inside a disk drive, /d in this case). But...

user@host:~$ npm -v
internal/modules/cjs/loader.js:583
throw err;
^

Error: Cannot find module 'C:\home\user\bin\node_modules\npm\bin\npm-cli.js'
at Function.Module._resolveFilename (internal/modules/cjs/loader.js:581:15)
at Function.Module._load (internal/modules/cjs/loader.js:507:25)
at Function.Module.runMain (internal/modules/cjs/loader.js:742:12)
at startup (internal/bootstrap/node.js:283:19)
at bootstrapNodeJSCore (internal/bootstrap/node.js:743:3)

Now that's the reason I'm writing this. The error is clear, npm is trying to find npm-cli.js in a path which is a wired mix of the npm symlink location inside a windows path.

Is there a way to tell npm/npx the correct Windows path where it must find its files from WSL?

Sorry for the long question but due to the very particular setup I considered that contextualization necessary.

Battlefield answered 4/1, 2019 at 7:2 Comment(1)
Did my answer or any of the others solve your issue?Assam
A
2

I could not install npm in WSL using Ubuntu 20.04 LTS in Windows 10.

However when I followed the instructions here I did manage to get it working. Note that it says it is for WSL2, but the steps for installing node are valid in a WSL1 environment (it's July 20 and I still cannot get WSL in my edition of Windows 10, argh!).

In a nutshell this solution gets you to install nvm (node version manager) in your WSL environement.

sudo apt-get install curl
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash

You can then install a newer version of node which ships with npm by default e.g.

nvm install --lts
Assam answered 14/7, 2020 at 0:19 Comment(4)
Ben, after you went through this process, did npx work for you? I used a similar approach for installing nvm and node in Ubuntu, separate from my installation of nvm and node in Windows. The problem is that 'which npx' from an Ubuntu terminal still responds with "/mnt/c/Program Files/nodejs/npx". Trying to run npx in Ubuntu results in the error, "/mnt/c/Program Files/nodejs/npx: bin/sh^M: bad intrepreter: No such file or directory". However, running 'which node' in Ubuntu responds with "/usr/bin/node", and everything seems to work when I execute node commands.Millsap
Hi @Lazor. When I followed these steps I was able to get nvm (and node) working, though I dont think I tried out npx. However when I was doing this work in WSL, I found that WSL was the culprit for adding the Windows path to the linux path. Luckily WSL has a way of stopping this behaviour as I posted here. Hope this helps!Assam
Hi Ben, thanks for the help. I honestly don't recall what changed, but I did a fresh installation of Ubuntu on Windows 10 and everything worked. After installing nvm and then the latest version of Node JS, npm and npx both worked.Millsap
Thats great news @Lazor. I had similar issues so I know how you feel (and the relief when you get it working!)Assam
T
1

Any workaround? I have met the same situation where I hope to share the same node and npm between WSL and Windows, as I want to run them in a terminal (WSL) and in IDEA (Windows) at the same time.

I found that npm cannot be run through drviers, like using npm under C:/, which has been installed under F:/, resulting in an error:

internal/modules/cjs/loader.js:638
    throw err;
    ^

Error: Cannot find module 'C:\f\Users\aleen\AppData\Roaming\nvm\v10.21.0\node_modules\npm\bin\npm-cli.js'
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:636:15)
    at Function.Module._load (internal/modules/cjs/loader.js:562:25)
    at Function.Module.runMain (internal/modules/cjs/loader.js:831:12)
    at startup (internal/bootstrap/node.js:283:19)
    at bootstrapNodeJSCore (internal/bootstrap/node.js:623:3)

However, we always work in one driver, which means we can install npm under the common used driver (F:/ for me), and make an alias to run it inside the driver via relative path:

# ~/.bash_aliases
function npm() {
  $(realpath --relative-to="$(pwd)" /mnt/f/Program\ Files/nodejs)/npm $@
}
export -f npm
Thrall answered 2/7, 2020 at 8:22 Comment(1)
The question has been created to tell Node: github.com/nodejs/node/issues/34165Thrall
F
1

Consolidating and expanding on existing answers ...

First, the primary answer here is:

  • Do not attempt to use the Windows version of NodeJS in WSL/Linux.

    There are several reasons for this:

    1. The NodeJS toolchain for Windows is going to expect (a) Windows paths instead of Linux paths (the problem being seen in this question)

    2. Even if you workaround that (and that's like tilting at windmills), as @AnselmoPark pointed out in a comment on this answer:

      some node modules have different implementation on [Windows] and WSL

      Also see this question and its answer for some additional information.

  • Instead, install and use the Linux version of the NodeJS toolchain within WSL.

    This is ultimately what BenSmith's answer is saying, but I would extend that to say that you can use any supported installation method for NodeJS under your Linux distribution. For instance, on Ubuntu, you can install from repo (but make sure your distribution has a supported version or install from PPA).

    Personally, I use n, but again, you can select whatever you are most comfortable with. The important thing is that you install the Linux version inside a WSL2 Linux distribution.

Secondary information, that hasn't been covered yet in any of these answers (but does come up in the comments as "still doesn't work") -- If you have installed both the Windows version and the Linux version (in WSL), you may end up in a situation like @Lazor did in the comments on this answer.

The problem happens because Windows Node provides npm as a shell script for those running Git Bash. However, this script is still pointing to the Windows version of the tools.

If the Windows NodeJS appears before the Linux version in the path, then (of course) it will take precedence. You need to either:

  • Make sure that the Linux version comes first
  • Or remove the Windows version.

Please do not follow the recommendations (like this answer) to completely remove all Windows paths from WSL, as that will severely limit your ability to run Windows applications in WSL (one of its great features).

Instead, using the Linux nvm (or n or other tools) is usually enough to place the Linux NodeJS directory first in the path.

Fini answered 20/1, 2022 at 21:28 Comment(1)
You said "If the Windows NodeJS appears before the Linux version in the path, then (of course) it will take precedence. You need to either:" , but where is? In .bashrc there isn't any export pointing to Windows directoryAnglice
B
0

I have my own development environment, so I couldn't test it on the same environment of yours. But, I suggest that you should check whether npm under "Program Files" works well on WSL.

user@host:~$ /c/Program\ Files/nodejs/npm -v

In my case, another error occurs when running above command.

Error: EINVAL: invalid argument, uv_pipe_open

If it is the same on your environment, you may solve this issue first.

And, about module path issue, it seems to be caused by path; the original npm(under Program Files) and your symbolic link have different current path.

I modified the original npm as below:

#!/bin/sh
(set -o igncr) 2>/dev/null && set -o igncr; # cygwin encoding fix

basedir=`dirname "$0"`

echo $basedir  # Added code

case `uname` in
    *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
esac
...

If you run the original npm and your symbolic link, $basedir will shows different results, and it causes module path issue.

If you can solve the first issue(uv_pipe_open error), how about adding the nodejs directory on your path instead of symbolic links?

Buitenzorg answered 4/1, 2019 at 9:13 Comment(4)
And I suggest that you should check simple network node.js program works well. I doubt Windows version node.exe has different implementation for socket.Buitenzorg
I not facing the invalid argument error, what setup are you using? Using the binary from its original location ends in the same behavior but with a different path (the windows one inside WSL) Cannot find module 'C:\c\Program Files\nodejs\node_modules\npm\bin\npm-cli.js' There seems to be two things happening here. The npm script is not able to get the canonical path of the symbolic link AND having the correct path, it needs to be transformed to a Windows path: /c/foo/bar/baz > c:/foo/bar/baz. I'm going to try to modify the npm script to achieve this. Maybe this can be PR to node source?Battlefield
I'm using nvm on WSL and nvm-windows on GIt Bash.Buitenzorg
As I know, Node.js for Windows is not fully compatible with WSL. And some node modules have different implementation on Git Bash and WSL. So, I set up node.js independently on WSL and Git Bash.Buitenzorg
K
0

What I did is I modified the npm bash file located at C:\Program Files\nodejs.

Replace this:

"$NODE_EXE" "$NPM_CLI_JS" "$@"

With this:

"$NODE_EXE" "/Program Files/nodejs/node_modules/npm/bin/npm-cli.js" "$@"

Then save it as a unix format file inside wsl.

Kuebbing answered 18/11, 2021 at 10:31 Comment(0)
S
0

I just copied the binary inside the /usr/bin folder.

How i did?

which node

it gave me binary location. I copied it inside the bin folder.

and in windows, i use it like this

wsl node

And it works fine.

Scales answered 24/8 at 17:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.