LogoPear Docs
About PearPlatform foundations

Dependencies

Why Pear ships with npm as the install path, and what your dependencies actually do at stage and runtime.

A question that comes up enough during onboarding: why does Pear use npm at all when applications run on Bare, not Node? The answer is a deliberate trade-off between developer ergonomics and the platform's clean-room ideals.

Looking for what your IP address discloses when you join a swarm? That's covered in Peer-to-peer, demystified.

Why npm for dependencies

npm is a great package manager for JavaScript, and most JavaScript developers already know how to use it. All of Holepunch's modules—Hypercore, Hyperdrive, Hyperbee, the lot—are published there. Reinventing a peer-to-peer package manager would have meant reinventing every developer's habits at the same time, for very little upside.

The bootstrap relationship is what's interesting: npm and Node.js are required to install Pear initially (npm install -g pear), but once the platform is set up neither is needed at runtime. The pear command after install is using Bare, not Node, to run your application; npm was just the delivery mechanism.

What dependencies your application declares stays meaningful, though. When you pear stage, every dependency in your package.json is bundled into the application's hyperdrive and replicated to peers along with your code. A few practical implications follow:

  • Audit before you ship. Run pear stage --dry-run to review the file list before announcing a release; this is where you'd catch a dependency that ballooned in size or pulled in something unexpected.
  • Updates ship fully replicated. If you update a dependency, you're not merely changing a package-lock.json—you're shipping the actual new code to every running peer. Ordinary semver discipline applies, but the consequence is more direct than on a server-rendered web app.

Dependency layout for Pear apps

Bare loads modules from node_modules the same way Node does during development, and Pear replicates those trees into the application hyperdrive at stage time. A few layout rules keep staging predictable:

  1. Use node_modules for dependencies—Pear picks them up during development and includes them when you stage.
  2. Use package.json—Pear reads it for application metadata and dependency lists.
  3. Do not bundle dependencies into a single file—bundlers that inline node_modules fight Pear's model of replicating discrete packages. Ship source and dependencies as separate files instead.

TypeScript is supported. Not every Holepunch module ships its own typings yet; the community holepunch-types project aggregates coverage. An IDE with TypeScript language service helps even for plain JavaScript projects.

If you compile TypeScript locally, keep dependencies external. With Bun:

bun build index.ts --packages=external --outdir=.

The --packages=external flag compiles your application code without inlining node_modules. Avoid bundling dependencies into the output artifact you stage.

Never load JavaScript over HTTP(S). Loading code from an external source is dangerous—if that source is compromised or malicious, your app can be exploited, and the risk is worse for apps with native API access. Pear blocks HTTP and HTTPS code loading by default to prevent this supply-chain risk. Ship dependencies with the app (as above) instead of fetching them at runtime.

See also

On this page