How to manage packages with package.json

 This writing explains how to manage packages with package.json. It includes dependencies between packages, package-lock.json, devDependencies, peerDependencies etc.



1. Dependencies

  • If you install some packages, you will see the name of package will be listed in dependencies in package.json. For example if you install Express;
$ npm install express

{
  "name": "npmtest",

  ...

  "license": "ISC",
  "dependencies": {
    "express": "^4.21.2"
  }
}
  • In addition, folder named node_modules is created. There are the installed packages. You clearly only installed Express, but it contains multiple packages. These are the packages that Express depends on.
  • Even a single package depends on many other packages, and those packages depend on yet more packages. This complex dependency relationship is why package.json is needed.


2. Package-lock.json

  • Package-lock.json is also created when you install some packages. In addition to the directly installed express, it contains the exact versions and dependencies of the packages in node_modules.
{
  "name": "npmtest",
  "version": "0.0.1",
  ...
    "node_modules/accepts": {
      "version": "1.3.8",
      "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
      "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
      "license": "MIT",
      "dependencies": {
        "mime-types": "~2.1.34",
        "negotiator": "0.6.3"
      },
      "engines": {
        "node": ">= 0.6"
      }
    },
    "node_modules/array-flatten": {
      "version": "1.1.1",
      "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
      "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==",
      "license": "MIT"
    },
    ...
  • Whenever you install, modify, or remove a package with npm, it stores the exact internal dependencies between the packages in this file. In other words, package.json is a file that records the packages you installed directly, and pckage-lock.jsoon is a file that specifies the dependencies between packages.


3. devDependencies

  • You can install the packages only for development purpose. These are packages that are only used during development and are not used during actual distribution. You can install it with this command: npm install --save-dev [package] [...]
  • It can be shorten as -D: npm install -D [package] [...]
$ npm install --save-dev nodemon

$ npm install -D nodemon
  • There's a new property in package.json. The new devDependencies property manages only development packages.
{
  "name": "npmtest",
  ...
  "dependencies": {
    "express": "^4.21.2"
  },
  "devDependencies": {
    "nodemon": "^3.1.9"
  }
}


4. peerDependencies

  • Sometimes you can see peerDependencies in your package.json as below.
{
  ...
  "peerDependencies": {
    "jQuery": "^3.0.0"
  }
}
  • It means this library is written assuming that jQuery version 3 is installed. Therefore, if you have installed a version other than jQuery version 3, an error will occur: ERESOLVE unable to resolve dependency tree
  • There would be 3 cases you can solve this error.
  1. The best is you install the packages again according to peerDependencies
  2. If A package has peerDependencies: jQuery2, and B package has peerDependencies: jQuery3, then you would be not sure which version you should install. In such case you can install both version by: npm i --force
  3. Or you can ignore peerDependencies: npm i --legacy-peer-deps
  • To avoid such complicate situation you need to check if there is any peerDependencies when you install some packages.


5. Global installation

  • npm also has an option called global install, which installs the package into the folder where npm is installed, rather than into node_modules in the current folder. For Windows: C:\Users\user name\AppData\Roaming\npm, For Mac: \usr\local\lib\node_modules
  • Most of the time, you install it globally for command-line use.
  • npm install --global [package] or shorten: npm install -g [package]
$ npm install --global rimraf

$ npm install -g rimraf

  • On Linux or Mac, you may need administrator authority. In that case, you should add it with sudo.
$ sudo npm install --global rimraf

  • Packages installed globally are not recorded in package.json. Some of developers avoid global installation because it is not recorded in package.json and it is hard to install packages again in such case. For this case people use npx.
$ npm install --save-dev rimraf
$ npx rimraf node_modules
  • rimraf module is recorded in devDependencies property, and you can also use it with npx. npx(Node Package eXecute) allows you to use it without installing it. With above method you can use it as it is installed globally and also the package is recorded so it is easy to manage the version.


6. How to manage packages

  • rimraf is the package that you can use command to delete some files or folders. For example you can delete node_module folder as below. Then there will be only package.json and package-lock.json left.
$ rimraf node_modules

    • node_modules can be installed again anytime because all the packages are recorded in package.json and package-lock.json. That's why people doesn't commit node_modules in such as GitHub. With those 2 files, package.json and package-lock.json, you can install node_modules by: npm install
    $ npm install
    
    added 111 packages, and audited 112 packages in 829ms
    
    18 packages are looking for funding
      run `npm fund` for details
    
    found 0 vulnerabilities
    

    • npm i installs packages based on package.json and allows change of some version, but npm ci installs packages based on package-lock.json and does not allow any change of version so for distribution purpose people use npm ci.
    Comparison Itemnpm installnpm ci
    Installation basis
    package.json
    (Allows version ranges)
    package-lock.json
    (Fixed versions)
    When node_module
    exists
    Installs while keeping existing
    packages
    Deletes existing folder and
    reinstalls
    SpeedRelatively slowerFaster
    Changes to
    package-lock.json
    Modifies if neededNever modifies
    Use casesGeneral development
    CI/CD, deployment, ensuring a
    consistent environment


    7. patch-package

    • Sometimes you want to edit the internal source code in some packages. You can edit it but if you enter npm install, it will be initialised. For the permanent edit you can use "patch-package" package.
    • Edit the package.json as below and install the "patch-package" package.
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1",
        "postinstall": "patch-package"
      },
    

    $ npm i patch-package
    (You edit the internal source code in some package.)
    $ npm patch-package [edited package name]
      • Then patches folder is created and also file with patch extension. After this if you enter npm i, patch-package read patch file and apply the edited contents.



      Next step

      • The next one is about Package version and some of npm commands.

      Comments

      Mostly viewed post

      Web-app dev4, Google AdMob (Banner and Interstitial ads)

      About this blog