Skip to content

Peer dependencies in Hardhat 3 plugins

Hardhat plugins make extensive use of peerDependencies, so it’s important to understand what they are and how to use them.

A peerDependency declares that your package expects the consumer (the project using your package) to have a specific dependency. Your package will use the same instance of that dependency as the consumer. This allows multiple packages in the dependency graph to share a single version and instance of a package, rather than each having their own separate copy.

By sharing the same instance, all consumers of that package see the exact same code and share any state held by that package, which is crucial for packages that rely on global state.

For example, if a Hardhat project has multiple plugins with hardhat as a peerDependency, all the plugins can trust that import hre from "hardhat" will return the same instance of Hardhat Runtime Environment.

You should use a peerDependency when you expose part of a dependency in your public API. This can happen in multiple scenarios:

  • Reexporting a type or value from a dependency
  • Accepting a type from a dependency in a public API
  • Returning a type from a dependency in a public API

For example, if you use viem and expose its WalletClient type, you should declare viem as a peerDependency.

In the context of Hardhat plugins, this means that:

  • Hardhat must be a peerDependency of your plugin
  • If your plugin depends on a package that the user may import directly (e.g. viem), it should be a peerDependency
  • If your plugin depends on a package that the user may run directly (e.g. mocha), it should be a peerDependency
  • If your plugin exposes a part of a dependency in any other way, it should be a peerDependency
  • If your plugin depends on a package that has peer dependencies, you should also declare those as peerDependencies (peer dependencies are not transitive and must be declared explicitly)

Common misconceptions about peerDependencies:

  • They’re optional dependencies. This is incorrect. Most package managers will automatically install them.
  • They let users choose dependency versions. While this is possible, the essence of peerDependencies is to ensure multiple packages share the same installation of a dependency.

Development experience of peerDependencies

Section titled “Development experience of peerDependencies”

When using peerDependencies, also declare them as devDependencies in your package.json file with the same version range. This is a good practice that improves the development experience, though requirements may vary by package manager.