Why one package's dependency impact another - javascript

I have a folder which name is project.
I use "yarn add" to install two packages (antd and antd-mobile),both of them have a dependency which name is rc-checkbox.
antd uses "rc-checkbox": "~2.1.5".
antd-mobile uses "rc-checkbox": "~2.0.0".
After running the command, project/node_modules has a 2.0.0 version rc-checkbox folder, and project/node_modules/antd/node_modules has a 2.1.5 rc-checkbox folder.
The weird thing is no matter which one I install first, antd-mobile's 2.0.0 rc-checkbox will be installed at project/node_module. And when I run the project, antd uses the rc-checkbox which version is 2.0.0 (it is supposed to use 2.1.5) and it causes the bug.
So why would this happen? I think two packages use same another package with difference version should not impact each other.

Copy from Here
Version locking
yarn generates yarn.lock after each installation which persists ALL versions of installed packages (as you probably know package can has also dependencies and dependency can have also dependency) so it can build up infinite tree of dependencies which can lead to very bad conflicts. Let's imagine this scenario
- lodash^1
- super_module#0.0.1
- - lodash#1.0.0
- another_module#0.0.01
- - lodash#1.x.x
Imagine scenario when maintainer of another_module decides to bump lodash to breaking changes version 1.2.0 what can happen is that npm in old days could fetch 2 different instances of same library, and 2 different version which could lead to extremely weird behavior. Because as you don't have exact lock in your module (you accept any semver version ^1.x.x and ^2.x.x so that means both sub modules would satisfie your requirements but fetch different version. Yarn will lock your yarn.lock AT THE TIME OF AN ADDING new package to the project, that means when other developers on your project will checkout the project he will also have same yarn.lock and yarn will ultimately "mimic" the state of package how they were installed when you committed yarn.lock on other hands NPM just looks to the semver satisfaction and can fetch 2 different version for 2 developers (assuming that in time packages are upgrading)

Related

How to update multiple packages and dependencies with major version changes in Node/npm/React?

I have an old React project with multiple outdated packages both in package.json and in dependencies in package-lock.json. Many of this packages need to be updated to next major version or even to the many major version change (for example React from 16.14 to 18.2). Since this is major version changes npm update and npm outdated would not work. For updating single top-level package I have this and this and this answers with npm install the-package#version, but that will not update packages, that dependent on this package. There is also npm-check-updates utility that will update all packages to the latest version, but according to this it is better to update and test single package after major version changes. There is also multiple packages that required update to major versions changes and not listed in package.json and only listed in package-lock.json since they used only as the dependencies of some other packages (and in come cases I must update to the versions bigger than listed in the depency itself due to security scan requirements). This answer suggests manually updating package-lock.json and running npm install.
What is the best way of updating multiple packages and dependencies with major version changes including packages that are only listed as dependencies of some other packages (an may be referenced to lower major versions then required)? Is there a way to update dependency tree for single package (not all packages, not only this package)?
I have tried npm audit and npm audit fix --force but it work strange - do not update all packages, sometimes do not upgrade to the latest version (which I have to use by the security scan) and sometimes even downgrade package version. I have tried to update packages by the install --save the-package#version but this do not update dependencies and work only for package.json. So far I see the possible way like this
Update top-level packages with npm install and test
Manually check dependencies, update with npm install and test
Manually check dependency tree for packages from package-lock.json, update packages that dependent on them if they still references to old version manually change package-llock.json and test changes
This requires a lot of manual work for each package and manual editing of package-lock.json and probably not the best way. There is also one possible solution for dependencies of dependensies as mentioned in this answers using override section in package.json, but it is recommended only for security fixes. Is there a better way with more automation?

Different versions of React in an npm workspace

We would like to have a workspace with different versions of react in two npm packages of the same workspace, due to one of them having dependencies not yet compatible with v18. However we're not able to do this without one of the versions being hoisted up to the root level, causing issues for the app in the other package.
At least I think that's what's going on. A simple reproduction goes as follows:
Create a new npm workspace with two packages, packages/a and packages/b; the root package.json including workspaces: ["packages/*"]
Create a new app in each of the workspace packages using create-react-app
Degrade the version in workspace a down to 17 by editing its package.json
Add a hook in each app, which will error if there are two versions running
Remove all node_modules folders, delete all package-lock.json files, and run npm i in the root folder
Start the two apps. This gives the "several versions of react" error with the hooks. Examining the node_modules folder in the root level we see that it contains one of the react versions
We also tried running npm i in each of the packages separately with the same result
In addition we tried creating a similar setup but without the full app, only installing (different versions of) react and react-dom in the two; still the root level node_modules contains one of them.
Lastly we tried using --legacy-bundling, but we haven't been able to make it work; also we're not sure it's worth the cost.
Is there a way to have a workspace with two different versions of react?

node_modules has a lot of files I don't know

I'm going through a tutorial by Kent C. Dodds on building an open source library. So far I have used npm to install chai, commitizen, cz-conventional-changelog, mocha, and unique-random-array.
I'm not sure when but I just noticed that my node_modules file became very large. There are around 100 folders just in the root of the node_modules folder.
I have attached two screenshots of some of the node_modules.
I do remember running npm install sementaic-release-cli without the global flag for a split second before realizing my mistake and quickly exiting the command. Could that split second have installed all these modules? If this is a result of my mistake then is there any way I can fix it?
What version of npm are you using? As of version 3, npm installs all dependencies as flatly as possible. So even though you only installed a few modules, those modules have dependencies of their own, and npm installs them all next to each other whenever possible.
Commitizen author here. Previously we had a bunch of our dev dependencies as regular dependencies. The latest Commitizen version removes this. If you clean out your node modules, install the latest Commitizen version, then rerun npm install you should have fewer dependencies.

Is bad practice to run "bower install" when deploying in production?

I am working on an application that uses bower.js; it's the first time I use bower, so please correct me if you see anything evidently wrong in my problem description.
------------------------------------------------
Coming from a Ruby background, I expect a package manager to have a .lock file, tracked under git, that tells me exactly which are the versions currently in use. This doesn't seem to happen with bower (am I right?).
A couple of days ago I deleted and re-cloned my repository, and ran bower install, thinking that such command would just install the required versions of the js components.
Then, today I did a one-line fix in a javascript file, compiled application.js using grunt watch, and realised that application.js was automatically filled up with tons of new code from bower component updates I wasn't aware of.
I found out that our bower components were under .gitignore, and that bower install, that I had run a few days ago, had actually updated two components without me noticing it.
When I realised what was happening, I immediately looked into our deployment procedure, which I paste here:
bundle install --path ${SNAP_CACHE_DIR}/.bundle
npm install -g bower grunt-cli
bower cache clean && bower install && bower list
bundle exec cap [our application name] deploy
Is this dangerous? Will bower install update all the components, that are likely not updated in my local version and are not tracked by git, ending up having completely different js code in production?
Is this dangerous? Will bower install update all the components, that are likely not updated in my local version and are not tracked by git, ending up having completely different js code in production?
Yes, this may happen and can cause problems. Although the impact will be limited as long as your dependency versions are specified as e.g. "~1.2.3", which will lock the major/minor version and only allow patch level updates.
In contrast to bower, the package manager normally used in node.js environments - npm - has a feature/command called npm shrinkwrap, which creates an npm-shrinkwrap.json file which locks down your dependency versions so that it is safe to run npm install afterwards.
This is probably what you would want.
However, bower as it stands does not have this feature yet - there is a discussion about it going on on Github e.g. here.
I think there currently are the following options to solve this problem in your situation:
Un-ignore and commit your bower_components (very ugly because of the huge amount of noise this produces in git).
Specify your dependency versions down to the patch level, e.g. "1.2.3" instead of "~1.2.3".
Culprit: If your dependencies have sub-dependencies, they might still be specified on the minor-version level, which means that even if your direct dependencies have a predictable version, your transitive dependencies may not.
Stop using bower and use npm instead (interface-/usability-wise, they are almost identical imho) and use npm shrinkwrap to lock down your dependencies.
Cheers, Alex

npm dependency management best practices

I'm a relative newcomer to the node community. I recently got on board so that I could put together a build for a complex web application that's been under development for several years. The two key tools in my build are Grunt and Browserify, but the application uses jQuery, Backbone, d3 and a smattering of other libraries and plugins as well.
A problem that I've been running into is this: by default, when I install and save a package with npm, it sets up the package with a semver expression that captures all future releases of the package whenever you run npm update. Like this article explains well, that may seem like a good thing at first ("give me this package and all future upgrades"), but it exposes your own application to any non-backwards compatible updates the package maintainer makes... The article also provides some recommended best practices, but it was written almost 4 years ago to the day; I'm hoping there are other, newer ideas.
What sort of solutions do you use to resolve this issue? I can't keep wasting time updating my software every time a breaking change is made in a library I rely on. I want to update when I am good and ready, not whenever I run npm update.
Use npm shrinkwrap to save the tree of dependencies containing the exact versions, so when you npm install it'll use those exact versions.
The npm outdated command will tell you what packages are outdated.
Instead of npm update which updates all your packages, update specific packages with npm install <pkg>#<version> --save

Categories