Repository navigation
perf: lazy-load heavy dependencies in hardhat-utils - #8201
Conversation
Convert top-level imports of 6 heavy dependencies to cached dynamic imports, loaded only when the consuming function is first called: - ethereum-cryptography (crypto.ts) — crypto init overhead - fast-equals (internal/lang.ts) — only needed for deepEqual - rfdc (internal/lang.ts) — only needed for deepClone - @streamparser/json-node (fs.ts) — only for readJsonFileAsStream - json-stream-stringify (fs.ts) — only for writeJsonFileAsStream - env-paths (internal/global-dir.ts) — rarely called at bootstrap Follows the cached await import() pattern already used by undici in this package. No public API changes. Fixes NomicFoundation#8162
|
schaable
left a comment
There was a problem hiding this comment.
Looks good. I made some minor cleanup and restored the type imports, since they don't affect performance.
There was a problem hiding this comment.
Pull request overview
This PR improves Hardhat startup performance by lazy-loading several heavy dependencies in @nomicfoundation/hardhat-utils, deferring their initialization until the relevant utility functions are actually used.
Changes:
- Replaces eager imports of heavy deps with
await import()in crypto, fs streaming JSON helpers, deep clone/equality helpers, and global-dir path generation. - Updates
request.ts’s Undici type aliasing and usespipelinedirectly fromnode:stream/promises. - Minor import-style adjustments in
synchronization.ts(node built-ins).
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/hardhat-utils/src/synchronization.ts | Switches some node built-in imports (e.g., hostname) to more granular/default imports. |
| packages/hardhat-utils/src/request.ts | Small Undici typing rename and uses pipeline directly; keeps Undici lazy-loading behavior. |
| packages/hardhat-utils/src/lang.ts | Adapts deepClone/deepEqual to await new async internal helpers. |
| packages/hardhat-utils/src/internal/lang.ts | Lazy-loads rfdc and fast-equals on first use and caches results. |
| packages/hardhat-utils/src/internal/global-dir.ts | Lazy-loads env-paths and caches the default export. |
| packages/hardhat-utils/src/fs.ts | Moves streaming JSON deps behind dynamic imports within the stream-based helpers. |
| packages/hardhat-utils/src/crypto.ts | Lazy-loads ethereum-cryptography hashing implementations on first use. |
Summary
Convert top-level imports of 6 heavy dependencies to cached
await import(), loaded only on first use:ethereum-cryptographycrypto.tsfast-equalsinternal/lang.tsdeepEqualrfdcinternal/lang.tsdeepClone@streamparser/json-nodefs.tsreadJsonFileAsStreamjson-stream-stringifyfs.tswriteJsonFileAsStreamenv-pathsinternal/global-dir.tsFollows the cached
await import()pattern already established byundiciinrequest.tsin this same package. No public API changes — all consuming functions were already async.Fixes #8162
Test plan
npx hardhat --help— should be noticeably fasternpx hardhat compile— crypto functions still worknpx hardhat test— all tests passreadJsonFileAsStream/writeJsonFileAsStreamstill function