PackShip v2 is now available! 🚀 Learn more

Dependencies

Managing dependencies is a crucial aspect of package development. This guide explains how to handle different types of dependencies in your PackShip project.

Types of Dependencies

In a Node.js package, there are three main types of dependencies:

dependencies

These are packages that your package needs to function in production. They are installed along with your package when someone installs it.

"dependencies": {
  "lodash": "^4.17.21",
  "prop-types": "^15.8.1"
}

devDependencies

These are packages that you need during development and testing, but not in production. They are not installed when someone installs your package.

"devDependencies": {
  "@babel/core": "^7.18.6",
  "webpack": "^5.73.0",
  "typescript": "^4.7.4",
  "jest": "^28.1.2"
}

peerDependencies

These are packages that your package needs but expects the consumer to provide. They are not installed automatically when someone installs your package.

"peerDependencies": {
  "react": "^17.0.0 || ^18.0.0",
  "react-dom": "^17.0.0 || ^18.0.0"
}

For React component libraries, React and ReactDOM should typically be peerDependencies, not dependencies. This prevents multiple versions of React from being installed in the consumer's project.

Managing Dependencies

Adding Dependencies

To add a runtime dependency:

npm install --save package-name

To add a development dependency:

npm install --save-dev package-name

To add a peer dependency:

npm install --save-peer package-name

You'll also need to install the peer dependency as a dev dependency to use it during development:

npm install --save-dev package-name

Removing Dependencies

To remove a dependency:

npm uninstall package-name

Updating Dependencies

To update all dependencies to their latest versions according to the version ranges in your package.json:

npm update

To update a specific dependency:

npm update package-name

Version Ranges

npm uses semantic versioning (SemVer) for package versions. Here's how to specify version ranges in your package.json:

  • ^1.2.3: Compatible with 1.x.x, where x >= 2 (will not update to 2.0.0)
  • ~1.2.3: Compatible with 1.2.x, where x >= 3 (will not update to 1.3.0)
  • 1.2.3: Exact version
  • *: Any version (not recommended)
  • >=1.2.3: Version 1.2.3 or higher
  • 1.2.3 - 1.5.0: Range of versions
  • ^1.2.3 || ^2.0.0: Multiple ranges (either 1.x.x or 2.x.x)

Best Practices

Minimize Dependencies

Keep your dependencies to a minimum to reduce package size and potential security issues. Before adding a new dependency, consider:

  • Is this functionality essential to your package?
  • Could you implement this functionality yourself with a small amount of code?
  • Is the dependency well-maintained and secure?
  • What is the size impact of adding this dependency?

Use Specific Version Ranges

Use specific version ranges to avoid unexpected breaking changes:

  • For dependencies, use ^ to allow minor and patch updates
  • For critical dependencies, consider using ~ to allow only patch updates
  • For peerDependencies, use a wider range to be compatible with more consumer setups

Regularly Update Dependencies

Regularly update your dependencies to get bug fixes and security patches. Tools like npm audit can help identify security issues in your dependencies:

npm audit

To fix security issues automatically:

npm audit fix

Use package-lock.json

The package-lock.json file ensures that the same dependencies are installed consistently across different environments. Always commit this file to your version control system.

Troubleshooting

Dependency Conflicts

If you encounter dependency conflicts, you can try using the --legacy-peer-deps flag:

npm install --legacy-peer-deps

Clearing npm Cache

Sometimes, clearing the npm cache can resolve dependency issues:

npm cache clean --force

Reinstalling Dependencies

If all else fails, you can try removing the node_modules directory and reinstalling all dependencies:

# Remove node_modules
rm -rf node_modules

# Reinstall dependencies
npm install