Why does installing modules from NPM or Yarn depend on node? - node.js

I am using React (create-react-app)
My understanding of what happens when we install a package from NPM or Yarn is: It finds the module and clones the code into node_modules, modules can also have their own package.json and dependent modules are cloned recursively.
If we are using a purely client side app (like React in my case), why does install process depend on node version? Like I get jsdom#16.2.0: The engine "node" is incompatible with this module. Expected version ">=10". Got "9.11.2"

As newer versions of Node.js are released, new features are added and older features are deprecated. Libraries using these new features can decide to lock in the minimum Node.js version needed to use their library.
If you use the library with a lower version of Node.js, the library will probably not work.
If you're working on multiple projects that require different versions of Node.js, consider installing and using nvm. With nvm, you can switch between multiple versions as needed by your projects.
https://github.com/nvm-sh/nvm

Related

Module compiled against a different NODE_MODULE_VERSION when developing an extension for vscode

I'm trying to use node's tree-sitter package in my vscode extension, but I get the following error:
Activating extension 'extension name' failed: The module '.../node_modules/tree-sitter/build/Release/tree_sitter_runtime_binding.node'
was compiled against a different Node.js version using
NODE_MODULE_VERSION 93. This version of Node.js requires
NODE_MODULE_VERSION 89. Please try re-compiling or re-installing
the module (for instance, using npm rebuild or npm install)..
From what I understand, the NODE_MODULE_VERSION is the version of node's ABI. However, I couldn't even find a release of node that has NODE_MODULE_VERSION 89 in the official website.
What I've tried:
Deleting the node_modules folder and reinstalling the packages.
Running npm rebuild tree-sitter --update-binary from the top directory.
Rebuilding the tree-sitter package with node-gyp rebuild and node-gyp rebuild --target=(my node version) from the node_modules/tree-sitter directory.
Switching node versions using nvm.
None of that helped. I understand from here that changing node versions won't help, as I confirmed when I tried
console.log(process.version); // v14.16.0
console.log(process.versions.modules); // 89
This gave the same output no matter which node version I used. I also tried rebuilding the tree-sitter package using that node version node-gyp rebuild --target=14.16.0, but I get the same error, however this time it says the module was compiled using NODE_MODULE_VERSION 83, which is consistent with what node's site says.
How do I resolve this error?
Any help is appreciated.
As I suspected, the version of node ABI used by vscode extensions is the ABI version used by vscode's internal electron. According to this source
Native Node.js modules are supported by Electron, but since Electron has a different application binary interface (ABI) from a given Node.js binary (due to differences such as using Chromium's BoringSSL instead of OpenSSL), the native modules you use will need to be recompiled for Electron...
This explains why I couldn't find NODE_MODULE_VERSION 89 in node's site.
Next, I checked what version of electron my build of vscode uses. To do this, I simply checked the package.json that came with vscode (/usr/lib/code/package.json on linux, I guess that it is inside the folder vscode is installed on on windows).
Next, following the instructions from electron's site, rebuild the module using the package electron-rebuild. To specify a target version, simply run
./node_modules/.bin/electron-rebuild -v [version]
However, I have no source for this but it seems that tree-sitter does not currently support newer versions of electron, so the build fails. This seems to be because of a change in V8's API (according to this).
The author linked his solution here. I copied his changes and the build succeeded.
Note that I had to replace the existing node addon with the newly built one.

Co-Existience of two different NodeJS for same project

I am quite new to NodeJS and am planning to upgrade NodeJS version for my current project. The most recent NodeJS LTS is installed using NVM.
I need to keep switching between the current LTS that i am using and the new LTS that has been installed. I understand that i can do 'NVM use' for this purpose. npm-shrinkwrap.json is being used to lock down the npm package dependencies.
I am planning to follow the below approach both in my dev machine and build machine;
Is it okay? If not, please suggest a best approach.
nvm use latest_LTS
Update the package.json to pick the version which is supported by
latest_LTS
npm install
generate testing_build
Whenever i need to generate a build for current release (with the previous LTS NodeJS)
nvm use currently_used_LTS
clear the node modules
npm install (Release npm-shrinkwrap.json)
generate release_build
Thanks
In theory that should work.
However have you considered the option of just doing a point release for the current release_build that does nothing except version-bump node?
You may find (after re-running your tests) that the latest version of node is backwards compatable with release_build (or only requires minor fixes), and you can simplify your life by porting everything to the latest node version, rather than constantly switching

What exactly is the relation between the versions of npm and node when installing them with nvm

tl;dr
Is there is a reason that I shouldn't do the following; Install and manage packages with a version of npm that is different (much newer) from the npm version that comes with the node version I am going to be using to run my app.
longer
Some context why I am asking. I have to work with a service that supports only node 0.10.32 (I know, don't ask) and an app that was written some time ago. We need to add some functionality and unfortunately when I try to run the codebase locally it does not because some dependency of some dependency updated the minor version and they introduced const or fat arrow notation (=>). We had used shrinkwrap to lock down the versions but something must have slipped.
I have spent days on this and at some point it came to me that the problem lies with the package manager not doing what I want. So I managed to install the packages I wanted and shrinkwrapped it using npm#3.10.10 which is what I get when I use node#6.12.3 (nvm use 6.12.3). And when I want to run the app I just switch to the node#0.10.32 to make sure that is going to work on the service.
Can anyone think of any problems with this solution or a reason I shouldn't do that?
Side question
I noticed that when installing node versions using nvm, they usually come with a specific version of npm? What is the relation of those versions? How are they decided? Was it the latest npm version along with that node version when it was released? Is it the latest version of npm that can run with that specific version of node?

Webpack failed to compile react code after upgrade to node v8 (on Ubuntu 16)

After upgrading from node v7 to node v8, webpack failed to compile my react code.
It said that some node_modules are not found. Note: This issue does not happen on Windows.
I tried several ways from refreshing node cache & npm_modules to double-checking $NODE_PATH, but still failed to make it work. Looks like an compatibility issue of node v8 and webpack (or some ES6 syntax).
Temporarily I reverted back to node v7 to make it work.
Does anyone encounter this issue?
When you install a new Node version then you need to make sure that you install all modules that you want installed globally using that new version (you need to have both node and npm in your PATH with that new version first before any other version of node and npm that you might have in your PATH or this will likely not work as expected). Then you need to rebuild all locally installed modules (you may need to remove node_modules directory in some cases to make sure that everything is built from scratch).
One issue that is quite common when you have multiple Node versions installed from the binary packages (using either binary tarballs or nvm etc.) is that the npm that gets installed has a general shebang line #!/usr/bin/env node instead of a specific path like #!/opt/node-v8.0.0/bin/node which would be the case if you built Node from the sources yourself.
This means that you can sometimes go into trouble by running npm with global path that would use the wrong version of Node, leading to some issues that can be hard to notice.
The least problematic Node installation in my experience is building it from sources, installing in a versioned directory and explicitly adding it to PATH before installing the modules globally, before local npm install and before running the project that you want to be using that specific Node version. That way you can make sure that you're not using any files that could be left overs from older versions, like would be the case with installing under a common /usr/local prefix.
You can take a look at my tutorial for more details and other options to install Node:
https://gist.github.com/rsp/edf756a05b10f25ee305cc98a161876a
In general what you described is usually caused by clashing installations of Node.

How can I install node.js without putting it in the path?

I have an older node.js installed on my mac, that is still needed, but for some other application a newer version is needed as well that I would like to access using full path, so that the node command uses the older version.
So is there a way to compile from source or install node.js without modifying the PATH?
PS.: newer npm is needed for the newer node.js
The nvm (node version manager) package is designed to allow you using multiple node versions without modifying the system PATH.
You even can specify the required node version per project directory.

Resources