Update npm package in pakcage.json and its dependencies in yarn.lock - npm

In one of our application we are using loader-utils with version 1.3.5, Below is the exact entry from package.json
"loader-utils": "^1.3.5",
I updated this package to version 1.4.1 by manually editing the package.json file and then running the yarn command. It updated the package in package.json file but in yarn.lock file there are still some instances where 1.3.5 version is being called, mainly on different dependencies. For example this is new code it added on yarn.lock file after I updated the package using yarn command
> loader-utils#^1.4.1: version "1.4.2" resolved
> "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.2.tgz#29a957f3a63973883eb684f10ffd151fec01a3"
> integrity
> sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==
> dependencies:
> big.js "^5.2.2"
> emojis-list "^3.0.0"
> json5 "^1.0.1"
But upon searching on same yarn.lock file there are some instances where older version is being called, for example (in the last line)
webpack#~4.28:
version "4.28.4"
resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.28.4.tgz#1ddae6c89887d7efb752adf0c3cd2b9b07eacd0"
integrity sha512-NxjD61WsK/a3JIdwWjtIpimmvE6UrRi3yG54/74Hk9rwNj5FPkA4DJCf1z4ByDWLk2ZhTZE+P3C/eh6UD5lDcw==
dependencies:
"#webassemblyjs/ast" "1.7.11"
"#webassemblyjs/helper-module-context" "1.7.11"
"#webassemblyjs/wasm-edit" "1.7.11"
"#webassemblyjs/wasm-parser" "1.7.11"
loader-utils "^1.1.0"
Now my question is how can I update this one as well? Will I have to do it manually and just replace it with the latest version? Thanks

Related

version in package-lock file of a dependency is being ignored

I am importing a dependency in my package.json. That dependency has it's own package-lock.json file in which a the versions of its own dependencies are written. However, when I do my npm install ... --save, the version of the dependency's dependency is not the right one, npm is picking up the latest version. It seems to be ignoring the lock file that belongs to the dependency.
So my dependency contains this in it's package.json file: "ccxt": "^1.52.41". And in it's package-lock.json there is ... "ccxt": { "version": "1.52.41"....
When I add this dependency to my project, the version of ccxt that gets installed (the version in my lock file) is 1.52.94.
What am I doing wrong?
Using npm v6.14.13
Ok, so the package-lock files that belong to your dependencies are ignored by npm. This is by "design" apparently. So at npm install time, you will essentially get a totally random bunch of dependencies installed and added to your package-lock file. From that point on those dependencies are fixed by your lock file until you manually update them using the npm command line.
This means that if you are unlucky and install at a 'bad' time, like I did, then you will pick up some completely untested code that could be broken and/or incompatible with its parent project or your project.

What is the correct use of package.lock.json file, when exactly it works

What is the exact use of package.lock.json file? I have read about it but it's confusing.
Let's say I do npm install so that it will create a package.lock.json file, and the next time when I do npm install, will it retain installation of the same packages as it was mentioned in the package.lock.json file?
Let's say I have a package version defined as "^1.0.0" in my package.json file and a new version becomes available in the npm registry. Will it update the package when I do npm install, or will it keep the same as what was there in the package.json?
Is there any easy way to update the package.json file with the exact no of package version without manually updating it one by one? I want to keep maintain the version of the package the same so that next time anybody does npm install, they should get exactly the same package. It's need for a release branch
Actually I need what was the original definition of package.lock.json file but I found inconsistency in its behavior.
I tried using NPM CI but it fails with error node_gyp needs python https://github.com/nodejs/node-gyp/issues/1977
What is the exact use of package.lock.json file?
Ans: The file is used to describe the exact tree that was generated initially, that is the version of the dependency that was used initially to install (NOTE: It will always be modified if package.json or node_modules are modified by npm)
source: https://docs.npmjs.com/configuring-npm/package-lock-json.html
Now coming to your specific questions :
Let's say I do npm install so that it will create a package.lock.json file, and the next time when I do npm install, will it retain installation of the same packages as it was mentioned in the package.lock.json file?
The simple answer here is: Yes
When you do npm install initially, you specify the package name. npm will create node_modules folder and package-lock.json file and the entry of the package with the version that was used to install will be added. next time when you do npm install, without specifying the package it will not update any of your package even with the caret (^) symbol because this time npm will look at the package-lock.json file (as it is present there) and it will install the same version that is specified in the (package-lock.json) file.
Let's say I have a package version defined as "^1.0.0" in my package.json file and a new version becomes available in the npm registry. Will it update the package when I do npm install, or will it keep the same as what was there in the package.json?
As explained in first question, it will not, if the package-lock.json is present in the directory. Updating of the package will only happen if package-lock.json file and node_modules folder are not present in the directory.
Is there any easy way to update the package.json file with the exact no of package version without manually updating it one by one? I want to keep maintain the version of the package the same so that next time anybody does npm install, they should get exactly the same package. It's need for a release branch
It is a good practice to use npm ci, but you can also use npm update, this will update the dependencies to its latest minor version, and your package.json as well as package-lock.json file will also be updated
For the production, its preferred way to use the same version of dependencies that was used initially. In this case it is better to have package-lock.json file, so in case of dockerizing application when you do npm install it will install the dependencies with versions that are used in package-lock.json

npm install not updating package to the latest dist-tag

I am publishing artifact to npm repository with a custom tag 'dev-latest'. After executing npm install in a project where I have this dependency defined, the latest version is not updated.
After new artifact is published I see that dev-latest points to the latest version:
npm view #kosmos/equote-lib dist-tags
{ 'dev-latest': '1.0.0-dev20190125.1',
latest: '1.0.0-rel20190122.0',
'rel-latest': '1.0.0-rel20190123.0' }
Locally i have installed previous version. In my package.json my dependency is defined:
"#kosmos/equote-lib": "dev-latest",
after executing npm install to update whole project my package is not updated to the latest version.
When I do npm install #kosmos/equote-lib#dev-latest it will update it but also change my package.json entry to the specific package version.
Other solution is to remove node_modules and the I will get latest version as well.
I would expect that using tag will remove the need of specifying the version in package.json Is there a way to implement the desired behavior ?
I think I found the good answer here: https://stackoverflow.com/a/19824154/1347496
Basically in case you have already installed the modules locally you should use npm update to update one/all dependencies. In my case while using tags I do
npm update --no-save
to not to overwrite my package.json

How to override package.json "latest" dist-tag with version from package-lock.json?

I want to use latest distribution tag in my package.json for internal packages. This allows me to always get their latest versions when I npm install in local environment, without updating all external 3rd parties.
The issue comes when I'm hotfixing deployed verion:
For hotfix purpose I generate and save package-lock.json for each deployed version of the application.
But when I npm install during hotfix preparation, there is a conflict between versions of internal package in package.json and package-lock.json: package-lock.json points to version that was used in deployed application, but package.json point to latest distribution tag, which itself points to later version.
Since version specified in package-lock.json doesn't suit to version range specified in package.json (which is very specific - only the latest version will suit), npm install ignores package-lock.json and installs the latest version.
I searched through documentation and internet and didn't find any existing solution for the issue:
I didn't find any npm install flag that would treat package-lock.json versions with higher priority than distribution tag in package.json
I dind't find any tool that would reconstruct package.json from package-lock.json, or at least replace aliases (distribution tags) in package.json with specific versions from package-lock.json.
Is there any solution for my issue (besides writing a tool that will implement last approach)?
Sandbox:
https://github.com/maxlk/npm-lock-version-should-override-latest (clone and run npm install or its alternative)
I found a solution - to use npm ci instead of npm install.
It doesn't exit with error, despite the claim in the documentation: https://docs.npmjs.com/cli/ci
If dependencies in the package lock do not match those in package.json, npm ci will exit with an error, instead of updating the package lock.

Yarn: use yarn.lock of dependencies

I use yarn to install packages directly from the companies' GitLab:
yarn add git+ssh://<user>#<host>:<repo>
For first-level dependencies, I use yarn --pure-lockfile to reconstruct my node_modules according to the yarn.lock.
However, for second level dependencies yarn seems to always install the latest version.
So let's say I depend on A which is tested with a specific version of B. In A's package.json I don't specify the version, but it is contained in the yarn.lock.
When I now install package A yarn will get the latest version of B despite the entry in A/yarn.lock
I know that I might resolve this by passing a specific version in A/package.json (at least I think).
But is there an option to tell yarn to look at the yarn.lock of dependencies?
TLDR:
When you install dependencies in your
application, only your own yarn.lock file is respected. Lockfiles
within your dependencies will be ignored. Reference
Let's get some things cleared first:
--pure-lockfile is same as normal yarn install except that it won't generate a yarn.lock file or update one if present.
Yarn always reads from the yarn.lock by default for resolving dependencies while installing unless supplied with --no-lockfile. So, there is no need to tell it to read from yarn.lock.
What is yarn.lock used for?
yarn.lock is used for resolving what version should be fetched
given the semver version of a module in package.json. It is not used to determine what semver version should a module be resolved to. That is simply not its use-case.
As mentioned in yarn DOCS: In order to get consistent
installs across machines, Yarn needs more information than the
dependencies you configure in your package json.. Yarn needs to store
exactly which versions of each dependency were installed.
To do this Yarn uses a yarn.lock file in the root of your project.
So, for resolving semver version of a dependency, yarn always depends on package.json. For a given semver version, yarn checks the yarn.lock file to see what version should it fetch. This is what makes yarn Deterministic (Same tecknique is used by npm which uses npm-shrinkwrap.json).
Example: Semver Versions like ^1.2.4 can resolve to any version number which is >= 1.2.3 and < 2.0.0. Without yarn, npm would install 1.2.4 in one machine but 1.9.9 in some other machine, depending on the latest version present at the time of install. This is the problem that yarn solves using yarn.lock.
The semver version is determined by the
package.json file. The yarn.lock file is only a lookup for which
version and commit hash to install for the given semver version number.
How does yarn resolve version of a module given its semver version?
Suppose currently our yarn.lock file looks like this:
bluebird#2.9.6:
version "2.9.6"
resolved "https://<...>/bluebird-2.9.6.tgz#1fc3a6b1685267dc121b5ec89b32ce069d81ab7d"
bluebird#^2.9.30:
version "2.11.0"
resolved "https://<...>/bluebird-2.11.0.tgz#534b9033c022c9579c56ba3b3e5a5caafbb650e1"
...
myModule#5.1.0:
version "5.1.0"
resolved "https://<...>/moduleA-5.1.0.tgz#ce97130858add59d616ee80675383b0c127290a0"
dependencies:
bluebird "^1.0.0"
If package.json has bluebird: "^2.9.30", yarn looks for an entry bluebird#^2.9.30 in the lockfile. It is present and hence is resolved to version=2.11.0.
If package.json has bluebird: "^2.9.0", yarn looks for an entry bluebird#^2.9.0 in the lockfile. It is not present. Suppose the latest stable version which satisfies semver criteria is 2.13.0, then yarn adds an entry for bluebird#^2.9.0, resolved to 2.13.0. While resolving version for a given semver version of bluebird, it does not matter what entry is present for bluebird in moduleA's dependencies in the lockfile.
Semver Version is not affected by what entries are
present in the dependencies map for a module in yarn.lock file.
So, if package.json has bluebird: "", yarn looks for an entry bluebird# in the lockfile but is unable to find it. Hence, it resolves bluebird: "" to the latest version, suppose 3.5.0. Now, yarn will add an entry for bluebird# resolved to 3.5.0.
bluebird#:
version "3.5.0"
resolved "https://<...>/bluebird-3.5.0.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9"
Form now on whenever yarn encounters {bluebird: ""}, it will find an entry for bluebird# in the lockfile and hence will always resolve it to 3.5.0.
Solution to your problem
To resolve B: "" to version say 1.0.0, you need to have an entry for B# in yarn.lock resolved to 1.0.0. Once, yarn.lock has an entry for B#, all the successive installs will always fetch version 1.0.0 for B="".
Following are the steps you need to take to accomplish the same:
Approach 1 (Recommended)
If you want B to resolve to latest version:
Add B:"" in A's package.json
Run yarn install. This will add an entry for B# resolved to latest version.
Push yarn.lock file.
Form now on, whoever runs yarn install will get the same version.
Approach 2
If you want B to have an older version: (Highly Not Recommended)
Add B: 1.0.0 in A's package.json.
Run yarn install. This will add an entry B#1.0.0 in the lockfile.
Add B# alongside B#1.0.0 in yarn.lock. B#, B#1.0.0: ...
Change B's version to "" in A's package.json.
Push yarn.lock file.
Form now on, whoever runs yarn install will get the B's version as 1.0.0.
This approach is highly dangerous as you can break something easily. Your yarn.lock file should always be managed by yarn.
Approach 3 (Recommended)
If you want B to stay at 1.0.0
Fix B's version to 1.0.0 in A's package.json.
Run yarn install. This will add an entry B#1.0.0 in the lockfile.
Push yarn.lock file
Form now on, whoever runs yarn install will get the B's version as 1.0.0.
Edit: Using the yarn.lock file present in the dependencies
If you check this doc:, they have clearly mentioned that yarn will use only the top level yarn.lock file and ignore the lock files present in the dependencies.
There is currently no way of locking down second level dependencies using yarn.lock present in them. I don’t see any need for it. In fact the creators of yarn explain here why that is the case. The reasons being:
The versions to be installed for second level dependencies can be
captured well by the top-level yarn.lock file, as I have explained
above.
You would never be able to update the versions of sub-dependencies in your own application when using them directly because they would be locked by other yarn.lock files. You can verify this point by my explanation of how yarn resolves dependencies.
Yarn would never be able to fold (de-duplicate) dependencies so that compatible version ranges only install a single version.
Also, as in your use-case, if A has a dependency B which works only with version 1.0.0, A’s package.json should have version mentioned for B as 1.0.0 and not “”. You can always fix your top-level yarn.lock to add an entry for B# resolved to 1.0.0 but it is not recommended to manually fix a yarn.lock file as I have mentioned above.
Hope this helped! Please ping me in the comments for any doubts.