package-lock, package.json, woe - node.js

I'm not a node expert by any means. In one project, something's gone wrong somewhere, and package-lock.json and package.json seems to have fallen out of sync. The only way I can get stuff to build is this sequence:
rm -rf node-modules
npm install
rm package-lock.json
npm install
webpack
i.e. I have to run npm install once with package-lock, and then once without. There are a lot of dependencies, and tracking down which ones are needed is proving difficult. What's the best way of resolving this so that I don't need to npm install twice? And how can I prevent this sort of thing not arising in the future?
Note: Two different devs were working on this git repo, and it's very possible that the package-lock and package files were not checked in properly.

Could You paste Your packake.json and package-lock.json files here?
If they are too big - put them in some fillde and give link.
(srry that this is an answer, not a comment, but don't have 50 rep needed).

It turns out the issue was to do with a specific version of #types/react-redux. There's a breaking change between 4.4.40, and 4.4.41. I was previously using ^4.4.40, so when the package-lock was being used, it was fetching 4.4.40, and everything worked. When I deleted the package lock, the ^4.4.40 moniker downloaded 4.4.41, as it was latest, and things broke. Changing the version from ^4.4.40 to just 4.4.40 has fixed it for now.

Related

Can I switch React Native app from Yarn to NPM seamlessly or is it more involved?

I am now in charge of an app whose dependencies were installed using yarn. I am more familiar with NPM. Is switching over as easy as deleting the yarn.lock file and installing NPM to the project? The app hasn't been updated in a year or two so I'm trying to update everything.
Or maybe a better question is, can I install both NPM and yarn globally but pick and choose which one I use for what app? Will it cause issues if they are both installed globally on machine?
Thanks in advance
You can definitely have Yarn and NPM installed on the same machine without issue. NPM generally comes packaged with Node, so most people using Yarn will also have NPM installed, wether they use it or not.
In terms of switching a project from Yarn to NPM, it's a pretty straightforward process, like you described: remove yarn.lock and remove the existing node_modules directory just to avoid any issues.
The subtle issue here is that the yarn.lock will be the current source of truth for exactly which versions of each dependency (and sub-dependencies) is installed. So by removing the yarn.lock your package.json will now become the (incomplete) source of truth which will likely result in some dependencies being upgraded when you perform your first npm install -- then your package-lock.json will become the new strict source of truth.
Given you're planning on updating everything anyway, then this likely isn't going to be an issue, but it's worth keeping in mind as you're likely to see some minor dependency changes.

Do I also need to ignore the package-lock.json file when I ignore the node_modules folder from git? [duplicate]

npm 5 was released today and one of the new features include deterministic installs with the creation of a package-lock.json file.
Is this file supposed to be kept in source control?
I'm assuming it's similar to yarn.lock and composer.lock, both of which are supposed to be kept in source control.
Yes, package-lock.json is intended to be checked into source control. If you're using npm 5+, you may see this notice on the command line: created a lockfile as package-lock.json. You should commit this file. According to npm help package-lock.json:
package-lock.json is automatically generated for any operations where npm
modifies either the node_modules tree, or package.json. It describes the
exact tree that was generated, such that subsequent installs are able to
generate identical trees, regardless of intermediate dependency updates.
This file is intended to be committed into source repositories, and serves
various purposes:
Describe a single representation of a dependency tree such that teammates, deployments, and continuous integration are guaranteed to install exactly the same dependencies.
Provide a facility for users to "time-travel" to previous states of node_modules without having to commit the directory itself.
To facilitate greater visibility of tree changes through readable source control diffs.
And optimize the installation process by allowing npm to skip repeated metadata resolutions for previously-installed packages.
One key detail about package-lock.json is that it cannot be published, and it
will be ignored if found in any place other than the toplevel package. It shares
a format with npm-shrinkwrap.json, which is essentially the same file, but
allows publication. This is not recommended unless deploying a CLI tool or
otherwise using the publication process for producing production packages.
If both package-lock.json and npm-shrinkwrap.json are present in the root of
a package, package-lock.json will be completely ignored.
Yes, you SHOULD:
commit the package-lock.json.
use npm ci instead of npm install when building your applications both on your CI and your local development machine
The npm ci workflow requires the existence of a package-lock.json.
A big downside of npm install command is its unexpected behavior that it may mutate the package-lock.json, whereas npm ci only uses the versions specified in the lockfile and produces an error
if the package-lock.json and package.json are out of sync
if a package-lock.json is missing.
Hence, running npm install locally, esp. in larger teams with multiple developers, may lead to lots of conflicts within the package-lock.json and developers to decide to completely delete the package-lock.json instead.
Yet there is a strong use-case for being able to trust that the project's dependencies resolve repeatably in a reliable way across different machines.
From a package-lock.json you get exactly that: a known-to-work state.
In the past, I had projects without package-lock.json / npm-shrinkwrap.json / yarn.lock files whose build would fail one day because a random dependency got a breaking update.
Those issue are hard to resolve as you sometimes have to guess what the last working version was.
If you want to add a new dependency, you still run npm install {dependency}. If you want to upgrade, use either npm update {dependency} or npm install ${dependendency}#{version} and commit the changed package-lock.json.
If an upgrade fails, you can revert to the last known working package-lock.json.
To quote npm doc:
It is highly recommended you commit the generated package lock to
source control: this will allow anyone else on your team, your
deployments, your CI/continuous integration, and anyone else who runs
npm install in your package source to get the exact same dependency
tree that you were developing on. Additionally, the diffs from these
changes are human-readable and will inform you of any changes npm has
made to your node_modules, so you can notice if any transitive
dependencies were updated, hoisted, etc.
And in regards to the difference between npm ci vs npm install:
The project must have an existing package-lock.json or npm-shrinkwrap.json.
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.
npm ci can only install entire projects at a time: individual dependencies cannot be added with this command.
If a node_modules is already present, it will be automatically removed before npm ci begins its install.
It will never write to package.json or any of the package-locks: installs are essentially frozen.
Note: I posted a similar answer here
Yes, it's intended to be checked in. I want to suggest that it gets its own unique commit. We find that it adds a lot of noise to our diffs.
Yes, the best practice is to check-in (YES, CHECK-IN)
I agree that it will cause a lot of noise or conflict when seeing the diff. But the benefits are:
guarantee exact same version of every package between your dev and prod environments. This part is the most important when building in different environments at different times. You may use ^1.2.3 in your package.json, but how can you ensure each time npm install will pick up the same version in your dev machine and in the build server, especially those indirect dependency packages? Well, package-lock.json will ensure that. (With the help of npm ci which installs packages based on lock file)
it improves the installation process.
it helps with new audit feature npm audit fix.
I don't commit this file in my projects. What's the point ?
It's generated
It's the cause of a SHA1 code integrity err in gitlab with gitlab-ci.yml builds
Though it's true that I never use ^ in my package.json for libs because I had bad experiences with it.
To the people complaining about the noise when doing git diff:
git diff -- . ':(exclude)*package-lock.json' -- . ':(exclude)*yarn.lock'
What I did was use an alias:
alias gd="git diff --ignore-all-space --ignore-space-at-eol --ignore-space-change --ignore-blank-lines -- . ':(exclude)*package-lock.json' -- . ':(exclude)*yarn.lock'"
To ignore package-lock.json in diffs for the entire repository (everyone using it), you can add this to .gitattributes:
package-lock.json binary
yarn.lock binary
This will result in diffs that show "Binary files a/package-lock.json and b/package-lock.json differ whenever the package lock file was changed. Additionally, some Git services (notably GitLab, but not GitHub) will also exclude these files (no more 10k lines changed!) from the diffs when viewing online when doing this.
Yes, you can commit this file. From the npm's official docs:
package-lock.json is automatically generated for any operations where npm modifies either the node_modules tree, or package.json. It describes the exact tree that was generated, such that subsequent installs are able to generate identical trees, regardless of intermediate dependency updates.
This file is intended to be committed into source repositories[.]
Yes, it's a standard practice to commit package-lock.json.
The main reason for committing package-lock.json is that everyone in the project is on the same package version.
Pros:
If you follow strict versioning and don't allow updating to major versions automatically to save yourself from backward-incompatible changes in third-party packages committing package-lock helps a lot.
If you update a particular package, it gets updated in package-lock.json and everyone using the repository gets updated to that particular version when they take the pull of your changes.
Cons:
It can make your pull requests look ugly :)
npm install won't make sure that everyone in the project is on the same package version. npm ci will help with this.
Disable package-lock.json globally
type the following in your terminal:
npm config set package-lock false
this really work for me like magic
All answers say "YES" but that also depend of the project, the doc says:
One key detail about package-lock.json is that it cannot be published, and it will be ignored if found in any place other than the toplevel package.
This mean that you don't need to publish on npm your package-lock.json for dependency but you need to use package-lock.json in your repo to lock the version of your test dependency, build dependencies…
However, If your are using lerna for managing projects with multiple packages, you should put the package.json only on the root of your repo, not in each subpackage are created with npm init. You will get something like that :
.git
lerna.json
package.json
package-lock.json <--- here
packages/a/package.json
packages/a/lib/index.js
packages/b/package.json
packages/b/lib/index.js
My use of npm is to generate minified/uglified css/js and to generate the javascript needed in pages served by a django application. In my applications, Javascript runs on the page to create animations, some times perform ajax calls, work within a VUE framework and/or work with the css. If package-lock.json has some overriding control over what is in package.json, then it may be necessary that there is one version of this file. In my experience it either does not effect what is installed by npm install, or if it does, It has not to date adversely affected the applications I deploy to my knowledge. I don't use mongodb or other such applications that are traditionally thin client.
I remove package-lock.json from repo
because npm install generates this file, and npm install is part of the deploy process on each server that runs the app. Version control of node and npm are done manually on each server, but I am careful that they are the same.
When npm install is run on the server, it changes package-lock.json,
and if there are changes to a file that is recorded by the repo on the server, the next deploy WONT allow you to pull new changes from origin. That is
you can't deploy because the pull will overwrite the changes that have been made to package-lock.json.
You can't even overwrite a locally generated package-lock.json with what is on the repo (reset hard origin master), as npm will complain when ever you issue a command if the package-lock.json does not reflect what is in node_modules due to npm install, thus breaking the deploy. Now if this indicates that slightly different versions have been installed in node_modules, once again that has never caused me problems.
If node_modules is not on your repo (and it should not be), then package-lock.json should be ignored.
If I am missing something, please correct me in the comments, but the point that versioning is taken from this file makes no sense. The file package.json has version numbers in it, and I assume this file is the one used to build packages when npm install occurs, as when I remove it, npm install complains as follows:
jason#localhost:introcart_wagtail$ rm package.json
jason#localhost:introcart_wagtail$ npm install
npm WARN saveError ENOENT: no such file or directory, open '/home/jason/webapps/introcart_devtools/introcart_wagtail/package.json'
and the build fails, however when installing node_modules or applying npm to build js/css, no complaint is made if I remove package-lock.json
jason#localhost:introcart_wagtail$ rm package-lock.json
jason#localhost:introcart_wagtail$ npm run dev
> introcart#1.0.0 dev /home/jason/webapps/introcart_devtools/introcart_wagtail
> NODE_ENV=development webpack --progress --colors --watch --mode=development
10% building 0/1 modules 1 active ...
Committing package-lock.json to the source code version control means that the project will use a specific version of dependencies that may or may not match those defined in package.json. while the dependency has a specific version without any Caret (^) and Tilde (~) as you can see, that's mean the dependency will not be updated to the most recent version. and npm install will pick up the same version as well as we need it for our current version of Angular.
Note : package-lock.json highly recommended to commit it IF I added any Caret (^) and Tilde (~) to the dependency to be updated during the CI.

npm error: Cannot find module '.../immer.js' when building a create react app through CLI

I am trying to build a website using create react app and bootstrap. We are hosting the site via GH-pages and our repository is here. I have not had issues deploying the site locally until today, but have not yet been able to solve the problem after many hours.
I will go through the steps I performed to get me to where I am at.
Cloned repository through GH Desktop
Opened terminal and input brew reinstall node
Moved to project directory and input npm install react-bootstrap bootstrap#4.6.0 and npm install
Finally input npm start
I was met by this:
When I look in '.../node_modules/immer/dist', I see it contains 'immer.d.ts'. Further, when I look in '.../node_modules/react-dev-utils', 'immer.js' is present. I do not know much about Typescript, but the "main" entry looks like it is present, and the files are all present:
I have uninstalled and reinstalled the package manager, repository all day. I even reset my terminal and text editor to test it on a fresh reboot. I have gone through many StackOverflow questions and done things such as removing only the node_modules and package_lock.json files then inputting npm install, with no success.
Does anyone know what is missing? What should I do?
UPDATE
The problem with the 'immer' file was fixed by following the steps provided in the response: clearing the cache, updating the repository, getting a fresh clone, removing the damaged files, and installing npm.
After following these steps, the terminal returned this issue. I have tried troubleshooting this one as well, but feel like I am going in circles. Any directed advice helps.
First and foremost: exclude your node_modules file from git index. There is an entry in .gitignore to exclude it but it looks like you've included node_modules in index before adding that entry. Now you need to run a bit more sophisticated algorithm to get rid of it.
Quick troubleshooting for your problem (a bit redundant to my taste but just to make sure you didn't miss anything important):
# force cleaning npm cache. you may have a broken package there
npm cache clean --force
# clone repository into newly created directory (guaranteed to be clean)
git clone https://github.com/cameron-keene/ACE_Website somedir
# switch to the new directory
cd somedir
# remove broken node_modules
rm -rf node_modules
# remove (possibly) broken package-lock
rm package-lock.json
# fresh dependency install
npm install
Right now it looks like your immer dependency stored in node_modules is broken. As it has a lot of missing files and dist/immer.js is one of. That's why you're getting your error.
This problem was solved with
npm install --legacy-peer-deps
Shoutout to this Stack Overflow answer

Do I commit the package-lock.json file created by npm 5?

npm 5 was released today and one of the new features include deterministic installs with the creation of a package-lock.json file.
Is this file supposed to be kept in source control?
I'm assuming it's similar to yarn.lock and composer.lock, both of which are supposed to be kept in source control.
Yes, package-lock.json is intended to be checked into source control. If you're using npm 5+, you may see this notice on the command line: created a lockfile as package-lock.json. You should commit this file. According to npm help package-lock.json:
package-lock.json is automatically generated for any operations where npm
modifies either the node_modules tree, or package.json. It describes the
exact tree that was generated, such that subsequent installs are able to
generate identical trees, regardless of intermediate dependency updates.
This file is intended to be committed into source repositories, and serves
various purposes:
Describe a single representation of a dependency tree such that teammates, deployments, and continuous integration are guaranteed to install exactly the same dependencies.
Provide a facility for users to "time-travel" to previous states of node_modules without having to commit the directory itself.
To facilitate greater visibility of tree changes through readable source control diffs.
And optimize the installation process by allowing npm to skip repeated metadata resolutions for previously-installed packages.
One key detail about package-lock.json is that it cannot be published, and it
will be ignored if found in any place other than the toplevel package. It shares
a format with npm-shrinkwrap.json, which is essentially the same file, but
allows publication. This is not recommended unless deploying a CLI tool or
otherwise using the publication process for producing production packages.
If both package-lock.json and npm-shrinkwrap.json are present in the root of
a package, package-lock.json will be completely ignored.
Yes, you SHOULD:
commit the package-lock.json.
use npm ci instead of npm install when building your applications both on your CI and your local development machine
The npm ci workflow requires the existence of a package-lock.json.
A big downside of npm install command is its unexpected behavior that it may mutate the package-lock.json, whereas npm ci only uses the versions specified in the lockfile and produces an error
if the package-lock.json and package.json are out of sync
if a package-lock.json is missing.
Hence, running npm install locally, esp. in larger teams with multiple developers, may lead to lots of conflicts within the package-lock.json and developers to decide to completely delete the package-lock.json instead.
Yet there is a strong use-case for being able to trust that the project's dependencies resolve repeatably in a reliable way across different machines.
From a package-lock.json you get exactly that: a known-to-work state.
In the past, I had projects without package-lock.json / npm-shrinkwrap.json / yarn.lock files whose build would fail one day because a random dependency got a breaking update.
Those issue are hard to resolve as you sometimes have to guess what the last working version was.
If you want to add a new dependency, you still run npm install {dependency}. If you want to upgrade, use either npm update {dependency} or npm install ${dependendency}#{version} and commit the changed package-lock.json.
If an upgrade fails, you can revert to the last known working package-lock.json.
To quote npm doc:
It is highly recommended you commit the generated package lock to
source control: this will allow anyone else on your team, your
deployments, your CI/continuous integration, and anyone else who runs
npm install in your package source to get the exact same dependency
tree that you were developing on. Additionally, the diffs from these
changes are human-readable and will inform you of any changes npm has
made to your node_modules, so you can notice if any transitive
dependencies were updated, hoisted, etc.
And in regards to the difference between npm ci vs npm install:
The project must have an existing package-lock.json or npm-shrinkwrap.json.
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.
npm ci can only install entire projects at a time: individual dependencies cannot be added with this command.
If a node_modules is already present, it will be automatically removed before npm ci begins its install.
It will never write to package.json or any of the package-locks: installs are essentially frozen.
Note: I posted a similar answer here
Yes, it's intended to be checked in. I want to suggest that it gets its own unique commit. We find that it adds a lot of noise to our diffs.
Yes, the best practice is to check-in (YES, CHECK-IN)
I agree that it will cause a lot of noise or conflict when seeing the diff. But the benefits are:
guarantee exact same version of every package between your dev and prod environments. This part is the most important when building in different environments at different times. You may use ^1.2.3 in your package.json, but how can you ensure each time npm install will pick up the same version in your dev machine and in the build server, especially those indirect dependency packages? Well, package-lock.json will ensure that. (With the help of npm ci which installs packages based on lock file)
it improves the installation process.
it helps with new audit feature npm audit fix.
I don't commit this file in my projects. What's the point ?
It's generated
It's the cause of a SHA1 code integrity err in gitlab with gitlab-ci.yml builds
Though it's true that I never use ^ in my package.json for libs because I had bad experiences with it.
To the people complaining about the noise when doing git diff:
git diff -- . ':(exclude)*package-lock.json' -- . ':(exclude)*yarn.lock'
What I did was use an alias:
alias gd="git diff --ignore-all-space --ignore-space-at-eol --ignore-space-change --ignore-blank-lines -- . ':(exclude)*package-lock.json' -- . ':(exclude)*yarn.lock'"
To ignore package-lock.json in diffs for the entire repository (everyone using it), you can add this to .gitattributes:
package-lock.json binary
yarn.lock binary
This will result in diffs that show "Binary files a/package-lock.json and b/package-lock.json differ whenever the package lock file was changed. Additionally, some Git services (notably GitLab, but not GitHub) will also exclude these files (no more 10k lines changed!) from the diffs when viewing online when doing this.
Yes, you can commit this file. From the npm's official docs:
package-lock.json is automatically generated for any operations where npm modifies either the node_modules tree, or package.json. It describes the exact tree that was generated, such that subsequent installs are able to generate identical trees, regardless of intermediate dependency updates.
This file is intended to be committed into source repositories[.]
Yes, it's a standard practice to commit package-lock.json.
The main reason for committing package-lock.json is that everyone in the project is on the same package version.
Pros:
If you follow strict versioning and don't allow updating to major versions automatically to save yourself from backward-incompatible changes in third-party packages committing package-lock helps a lot.
If you update a particular package, it gets updated in package-lock.json and everyone using the repository gets updated to that particular version when they take the pull of your changes.
Cons:
It can make your pull requests look ugly :)
npm install won't make sure that everyone in the project is on the same package version. npm ci will help with this.
Disable package-lock.json globally
type the following in your terminal:
npm config set package-lock false
this really work for me like magic
All answers say "YES" but that also depend of the project, the doc says:
One key detail about package-lock.json is that it cannot be published, and it will be ignored if found in any place other than the toplevel package.
This mean that you don't need to publish on npm your package-lock.json for dependency but you need to use package-lock.json in your repo to lock the version of your test dependency, build dependencies…
However, If your are using lerna for managing projects with multiple packages, you should put the package.json only on the root of your repo, not in each subpackage are created with npm init. You will get something like that :
.git
lerna.json
package.json
package-lock.json <--- here
packages/a/package.json
packages/a/lib/index.js
packages/b/package.json
packages/b/lib/index.js
My use of npm is to generate minified/uglified css/js and to generate the javascript needed in pages served by a django application. In my applications, Javascript runs on the page to create animations, some times perform ajax calls, work within a VUE framework and/or work with the css. If package-lock.json has some overriding control over what is in package.json, then it may be necessary that there is one version of this file. In my experience it either does not effect what is installed by npm install, or if it does, It has not to date adversely affected the applications I deploy to my knowledge. I don't use mongodb or other such applications that are traditionally thin client.
I remove package-lock.json from repo
because npm install generates this file, and npm install is part of the deploy process on each server that runs the app. Version control of node and npm are done manually on each server, but I am careful that they are the same.
When npm install is run on the server, it changes package-lock.json,
and if there are changes to a file that is recorded by the repo on the server, the next deploy WONT allow you to pull new changes from origin. That is
you can't deploy because the pull will overwrite the changes that have been made to package-lock.json.
You can't even overwrite a locally generated package-lock.json with what is on the repo (reset hard origin master), as npm will complain when ever you issue a command if the package-lock.json does not reflect what is in node_modules due to npm install, thus breaking the deploy. Now if this indicates that slightly different versions have been installed in node_modules, once again that has never caused me problems.
If node_modules is not on your repo (and it should not be), then package-lock.json should be ignored.
If I am missing something, please correct me in the comments, but the point that versioning is taken from this file makes no sense. The file package.json has version numbers in it, and I assume this file is the one used to build packages when npm install occurs, as when I remove it, npm install complains as follows:
jason#localhost:introcart_wagtail$ rm package.json
jason#localhost:introcart_wagtail$ npm install
npm WARN saveError ENOENT: no such file or directory, open '/home/jason/webapps/introcart_devtools/introcart_wagtail/package.json'
and the build fails, however when installing node_modules or applying npm to build js/css, no complaint is made if I remove package-lock.json
jason#localhost:introcart_wagtail$ rm package-lock.json
jason#localhost:introcart_wagtail$ npm run dev
> introcart#1.0.0 dev /home/jason/webapps/introcart_devtools/introcart_wagtail
> NODE_ENV=development webpack --progress --colors --watch --mode=development
10% building 0/1 modules 1 active ...
Committing package-lock.json to the source code version control means that the project will use a specific version of dependencies that may or may not match those defined in package.json. while the dependency has a specific version without any Caret (^) and Tilde (~) as you can see, that's mean the dependency will not be updated to the most recent version. and npm install will pick up the same version as well as we need it for our current version of Angular.
Note : package-lock.json highly recommended to commit it IF I added any Caret (^) and Tilde (~) to the dependency to be updated during the CI.

yarn - install dependencies for a package in a different folder?

I would like to install the dependencies for some_project. I know I could cd into some_project and then run yarn install
But I was wondering if it's possible without changing the directory?
There's a bug with yarn that prevents the --modules-folder option from working as intended, however I personally don't like the fact that the option has to be provided in the command line; how would you make sure that on future installs they get installed to your chosen folder?
That's why I came up with this sneaky solution for npm since I wanted full control of the install path, not just into a prefixed version of node_modules. It will work just as well with yarn, in fact we use it in production and we haven't had a problem yet (fingers crossed).
In a nutshell, you need to symlink node_modules to your desired folder in the preinstall event (to trick npm or yarn) and then delete the symlink in the postinstall event.
There's one caveats however, which I didn't mention in the linked answer (since I didn't think of it at the time) and that is, things might not go as planned if the install goes horribly wrong; you'll end up with the symlink in place since the postinstall event might not have been triggered, and then the next install might fail since the symlink already exists.

Resources