npm - getting rid of nested node_modules in one specific module - npm

I'm kind of lost here!
I'm using a module which has another module nested in its' node_modules.
I.E.
my_project
node_modules
widely_used_module
parent_dependency
node_modules
widely_used_module
I have some fixes in my "own" widely_used_module (it could be just a minor version from the original distributor, but to be completely honest, in this case its' my fork on Github containing some critical fixes).
When I manually remove node_modules/parent_dependency/node_modules, parent_dependency starts to reference to my "widely used module" instead of its' own. But this of course gets overriden once I hit npm install again.
Can I somehow prevent a package to install its' own modules, or can I force a package to reference the root node_modules and ignore its' own?
Is that even the right approach to fixing such issues? I don't want to fork parent_dependency as well...
Thank you

Answering my own question;
Yarn has a built-in solution for this exact issue.
This could be achievable with NPM as well but yarn made it so easy to fix that I moved the project dependencies to be handled by yarn.
Full solution:
Installing yarn
Ran yarn in project's root path
Removed package.lock.json
Added resolutions to my package.json. In my case:
{
"dependencies": {
"...": "...",
"parent_dependency": "^x.y.z"
},
"devDependencies": {
"...": "..."
},
"resolutions": {
"parent_dependency/widely_used_module": "git+https://git#github.com/myuser/widely_used_module.git"
}
}
Ran yarn install.
Result: No more widely_used_module folder under parent_dependency.

Related

How to symlink a package in workspace without updating yarn.lock?

package.json -
"workspaces": [
"packages/*",
"samples/*"
],
"packageManager": "yarn#3.1.0"
I want to install and symlink the dependencies in samples but I don't want the yarn install to update the yarn.lock file.
Is there a setting in workspaces or yarn to achieve this?
I think you want to use yarn add your-package#"workspace:^" (or other workspace: ranges). This does end up in your yarn.lock, but when publishing your package yarn will actually replace the dependency with a versioned dependency (depending on the range specifier). Also, it doesn't include any hash or anything in the yarn.lock, so you don't need to reinstall when changes are made to the package.

Dependency resolution in NPM

Consider the following:
A project has a dependency for package X #1.2.3
A project may need to install package Y.
Package Y has a dependency for package X #2.3.4
The version 2 of package X is not backwards compatible with version 1.
Can this cause issues of any kind?
If you have npm installed them in the default way, your project is safe from dependency conflicts.
Just to be sure, look for those dependencies in the package-lock.json file and you should immediately notice that certain package dependencies are managed differently from project dependencies. In particular, this is a simplified entry created when you install X#1.2.3.
"node_modules/X": {
"version": "1.2.3",
...
"dependencies": {
...
}
}
Then you install Y, that depends on X#2.3.4.
"node_modules/Y": {
"version": "x.y.z",
...
"dependencies": {
"X": "2.3.4"
},
}
However, since X#2.3.4 has not been installed yet, a new entry is automatically created:
"node_modules/Y/node_modules/X": {
"version": "2.3.4",
...
"dependencies": {
...
}
},
As you can see, npm detects the potential dependency conflict: instead of registering the package in the global node_modules folder, npm installs it inside the node_modules folder of the package installed. You could have more than 2 nested level of node_modules if there are conflictual dependencies inside node_modules/Y/node_modules too.
I showed you an example of package-lock.json because understanding dependency management is straightforward looking at it, even if big. Nonetheless, in case you do not use it (I hope you do), npm reasons in the same way and you are never going to experience a dependency hell. The only exception is when you manually change semantic versioning expression allowing a major variation, but you must know what you are doing.

Why does `npm install` add / remove caret (^) to / from version numbers?

I have a project that I work on with two different laptops. Sometimes I add extra packages to my project, so I have to use npm install <package-name> (duh). When I do that, I git push up the new package.json and package-lock.json files, and when I switch computers I have to git pull those changes, then run npm install again to get that package onto the other computer.
I recently noticed and started caring that one laptop kept adding carets (^) to the beginning of every package version number. For example:
One computer set package version #s to look like this:
"regexpu-core": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-1.0.0.tgz",
"integrity": "sha1-hqdj9Y7k18L2sQLkdkBQ3n7ZDGs=",
"requires": {
"regenerate": "1.4.0",
"regjsgen": "0.2.0",
"regjsparser": "0.1.5"
}
},
The other set package version #s to look like this:
"regexpu-core": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-1.0.0.tgz",
"integrity": "sha1-hqdj9Y7k18L2sQLkdkBQ3n7ZDGs=",
"requires": {
"regenerate": "^1.2.1",
"regjsgen": "^0.2.0",
"regjsparser": "^0.1.4"
}
},
I understand that carets (^) mean the version is not 100% precise, but I'm trying to figure out WHY my different laptops create different formats for package versions! I checked this SO question which has some great explanations for the differences between ~ and ^, but I didn't find anything explaining why npm would sometimes add and sometimes remove carets (^) altogether. I also looked at this npm issue on Github which recommended looking at npm config settings, but both of my laptops have the same settings:
npm config get save = true (both computers)
npm config get save-prefix = ^ (both computers)
npm config get save-exact = false (both computers)
One laptop was running npm version 5.6.0, but I just updated it to 6.5.0. The other computer was running version 6.4.1, but I also updated it to 6.5.0. I tried running npm install in my project on both computers, but still I find that one computer always removes ^ and the other always adds ^.
Please let me know if there's something I'm missing. Thanks for any help!
Edit: According to the discussion in issue #20434 this occurs by design using npm >=6.0.0.
Why does this happen?
#rarkins elaborately explains the reasoning for why this happens (and it’s advantages) in this comment. For convenience his comment is quoted below (verbatim):
Let's say that you use pinned versions of dependencies 'aaa', 'bbb' and 'ccc'. Let's say they each depend on 'zzz' like so:
aaa depends on zzz#^1.0.0
bbb depends on zzz#^1.1.0
ccc depends on zzz#^1.0.1
i.e. all three of them depend on a range of zzz, and not an exact version.
And let's say that the latest version of zzz is 1.5.0.
Both before and after this change, it's pretty obvious that the resolved version of zzz should be 1.5.0, so the only difference is how the package-lock.json is structured and documents this sub-dependency.
Before, the lock file would show that all three of them depend on zzz#1.5.0, and the resolved version of z is 1.5.0.
Now, it documents the actual "original" dependency versions (e.g. ^1.0.0, ^1.1.0, etc) for each dependency, but still shows the resolved version of z as 1.5.0.
Then consider what happens when zzz#1.5.1 is released:
Before, the lock file would need to update from z#1.5.0 to z#1.5.1 in all four places.
Now, the lock file only needs to update the resolved version of z to 1.5.1 while the dependencies can keep the ^1.0.0, ^1.1.0, and ^1.0.1 because they haven't changed.
As I mentioned previously in the thread, you still get the exact same node_modules in both cases. The advantages of the new approach are:
You get to see what the dependencies actually require (e.g. a range, and not an exact version). before, you could not tell if aaa actually required exactly zzz#1.5.0 or that it was instead zzz#^1.0.0.
Instead of four lines changing in the lock file, you get only one. It's less churn, and it's more clear what's happened.
As an aside, yarn uses a similar concept with yarn.lock. e.g. here's an example where #sindresorhus/is is pinned, but it's sub-dependency symbol-observable is not:
"#sindresorhus/is#0.10.0":
version "0.10.0"
resolved "https://registry.yarnpkg.com/#sindresorhus/is/-/is-0.10.0.tgz#f42dd6a9d12cd79fa6f53b27cf5bea3a30d2cafa"
dependencies:
symbol-observable "^1.2.0"
Original Answer:
After you git pull the revised package.json and package-lock.json onto computer two try deleting the node_modules directory before installing the packages again.
For example:
Firstly cd to your project directory on computer 2.
Delete the existing node_modules directory by running: rm -rf node_modules.
Then run: npm install
Or you can chain the two aforementioned commands using the && operator:
rm -rf node_modules && npm install

npm install always goes for the local package instead of a remote

I have created project my-npm-lib and published it with npm.
Now I have an another project where I want to do:
npm install my-npm-lib --save
But if I do so, it always add to dependencies:
"dependencies": {
"my-npm-lib": "file:..\\my-npm-lib"
}
This is actually correct because I have the my-npm-lib project located there on the device where I do this.
But this is something I don't want to. Later in my new project I use the webpack and I need to do:
include: [
path.resolve(__dirname, "src"),
path.resolve(__dirname, "node_modules/my-npm-lib")
],
which
is impossible now because the module is not located in node_modules,
doesn't allow me to share the new project correctly with other associates, because there is a wrong path in the package.json file.
So far I have tried to rewrite the package.json manually with
"dependencies": {
"my-npm-lib": "^1.0.0"
}
and then use npm install, but it didn't install this particular module.
PS: Im quite sure my-npm-lib is working with npm, because it is working on other device. It seems there is a problem only with the device where the my-npm-lib is being developed.
I have found the solution,
be sure that package.json dependencies has a correct structure,
use npm install my-npm-lib --save,
then rewrite the "file:..\\my-npm-lib" to "^1.0.0",
delete the package-lock.json!, (it was the missing piece)
cast npm install again.

Twilio React Native - Unable to resolve module crypto

I'm working on implementing the twilio package into my react-native project and when I require it in my file the project wont load and I'm seeing the following error:
Unable to resolve module crypto from /Users/[myname]/Documents/Projects/React-Native/[app-name]/node_modules/twilio/lib/webhooks.js: Unable to find this module in its module map or any of the node_modules directories under /Users/node_modules/crypto and its parent directories
I've tried installing the crypto package directly and that doesn't seem to work either.
Has anyone experienced this issue, and has a way to resolve it?
You can use the rn-nodeify module to get crypto on react-native.
Add rn-nodeify to your devDependencies in package.json:
"devDependencies": {
"rn-nodeify": "^6.0.1"
}
Add the following to the scripts section of the same file:
"scripts": {
…
"postinstall": "node_modules/.bin/rn-nodeify --install crypto --hack"
}
Be aware that rn-nodeify will modify your package.json.
More information available here: https://www.npmjs.com/package/rn-nodeify
I suggest you have a look there, plenty of solutions are given because none seem to fix for everyone.
I suggest you try the following (taken from the issue from the link) :
rm -rf node_modules
rm -fr $TMPDIR/react-*
watchman watch-del-all
npm cache clean && npm install
npm start from ./node_modules/react-native
But check out the issue in its integrality, many found other fixes that worked for them.
It seems that React Native doesn't accept certain packages based on their dependencies, Twilio being one of these.
While not a direct solution, I created a work around to this issue by creating a separate Express server to make the Twilio call, and calling that route from within my React Native app.
React Native packager uses Babel under the hood. This means that you can use babel-plugin-rewrite-require Babel plugin to rewrite all require('crypto') calls to require('crypto-browserify'), assuming that the latter is installed in your node_modules.
As of January 2016, you can use .babelrc file to define optional configuration, so this becomes really easy. First, install the dependencies:
npm install --save crypto-browserify
npm install --save-dev babel-plugin-rewrite-require
Then add plugins config to your .babelrc file:
{
"presets": ["react-native"],
"plugins": [
["babel-plugin-rewrite-require", {
aliases: {
crypto: 'crypto-browserify'
}
}]
]
}
Restart the packager and that should be it.
This is the same approach that ReactNativify uses, except that here we use .babelrc instead of defining custom transformer. When ReactNativify was written, it was not supported, so they had to go with more complex solution. See this file from ReactNativify for almost complete list of node polyfills.