install
A minimal CommonJS module loader that lets you install and synchronously require a tree of modules in any JavaScript environment.
Repository Health
Technical Analysis
install is a tiny CommonJS module loader created by Ben Newman that lets you register a nested tree of module factory functions and directories, then require them synchronously - the same way Node does, but without touching the filesystem. It became best known as the runtime powering Meteor’s client-side module system, where synchronous require semantics needed to work inside the browser.
Under the hood, makeInstaller() builds a virtual file tree of File objects representing directories and modules, resolves identifiers using the same relative/absolute/node_modules rules as Node’s own module resolution, and evaluates each module lazily on first require. A fallback option lets missing modules be resolved by another loader (e.g., Node’s native require), and a prefetch/install.fetch API supports asynchronously fetching modules that haven’t been installed yet - useful for streaming code to the browser on demand.
What You Get
- A
makeInstaller(options)factory for creating isolated module registries, so multiple independent module trees can coexist without polluting global state. - Node-compatible module resolution - relative paths, absolute paths,
node_modulespackage lookup,package.jsonmain/browserfields, andindex.jsfallback - reimplemented without touching the real filesystem. - A
fallbackhook so unresolved identifiers can be handed off to another loader (commonly Node’s nativerequire) instead of throwing. - An async
module.prefetch/install.fetchAPI for lazily fetching and installing modules that weren’t part of the original tree, useful for on-demand code delivery in the browser.
Common Use Cases
- Bundler runtime output - bundlers can compile a whole dependency graph into the nested-object format
install()expects and ship this file as the tiny runtime that stitches modules together in the browser. - Meteor-style synchronous browser modules - apps that need Node’s synchronous
requiresemantics to work client-side without a full async module loader. - Sandboxed/dynamic module trees - testing or plugin systems that need to construct an isolated
requirescope from an in-memory tree of factory functions rather than real files on disk. - Incremental/on-demand loading - combining
prefetchwith a custominstall.fetchimplementation to stream additional modules to a running application only when they’re actually required.
Under The Hood
Architecture
Read install.js: the File constructor represents either a directory or a module in a virtual tree; fileMergeContents recursively merges nested objects/arrays/functions into that tree; fileResolve implements Node-style identifier resolution (relative, absolute, and node_modules walk-up, with package.json main/browser field and index.js fallback, guarded against re-visiting the same directory via a seenDirFiles list); fileEvaluate lazily invokes a module’s factory function with (require, exports, module) and caches the result on module.exports. All state - the filesByModuleId cache, the root File, defaultExtensions, fallback, mainFields - lives in closures inside makeInstaller(options), so each call produces a fully isolated registry. The whole implementation is one ~550-line file with no submodules, so changes to the core File/Module abstractions have repo-wide blast radius, since every other function is built directly on top of them. It is compact and single-responsibility but tightly coupled through closures over shared mutable state (filesByModuleId, missing, lastPrefetchPromise) rather than explicit dependency injection.
Tech Stack
package.json shows plain vanilla JavaScript with no TypeScript and no build step for the library itself - main points straight at install.js, which ships as-is. devDependencies are mocha for the test suite, docco for generating API docs (scripts/docs.sh runs docco against install.js into docs/index.html), reify (the author’s own ES module interop library) to enable import/export syntax inside tests only, and terser to produce a minified install.min.js at publish time (scripts/prepublish.sh). CI is a .travis.yml matrix running Node 4 through 12, reflecting the project’s 2013-2019 active period.
Code Quality
test/run.js is a single 1173-line mocha spec covering relative/absolute/node_modules resolution edge cases, package.json main/browser field handling, dynamic prefetch, and fallback behavior - broad coverage relative to the ~550-line source, though concentrated in one file rather than split by concern. There is no TypeScript or type checking anywhere in the codebase. Error handling is explicit: makeMissingError() builds descriptive Cannot find module errors, and the fallback mechanism gives callers an escape hatch rather than silently swallowing failures. Naming is consistent throughout (fileXxx/moduleXxx prefixes tie helper functions to the object type they operate on). There is no linter configuration and no lint/type-check step in CI, which just runs npm test.
What Makes It Unique
The specific technical trick is resolving and evaluating an in-memory tree of module factory functions using the same identifier-resolution algorithm Node uses for the real filesystem - relative/absolute paths, extensions, node_modules walk-up, package.json main/browser fields, index.js fallback - without ever touching disk. That is what let Meteor give browser bundles synchronous, Node-compatible require() semantics years before bundler-level dynamic import() became commonplace. The prefetch/install.fetch hook for asynchronously fetching modules not present in the original tree is a distinctive, comparatively early take on on-demand code delivery. It is not novel in a research sense - module loaders are a well-trodden problem - but faithfully emulating Node resolution in a virtual filesystem inside one small, dependency-free file is a focused, clever piece of engineering for its era.
Used by 11 apps in this directory
AutoGen
AI Development · Automation
Build autonomous and human-in-the-loop multi-agent AI systems with a layered, event-driven Python and .NET framework pioneered at Microsoft Research.
Enso
Analytics · Data Engineering · Low Code Platforms
A visual and textual programming platform for data prep and analysis where the node graph and the underlying Enso code are always perfectly in sync, built by an Alteryx co-founder on a GraalVM engine.
Flowfile
Data Engineering
Visual ETL that compiles to Polars — build pipelines on a canvas, export as standalone Python, and run anywhere without platform lock-in.
fountain-ink
Blogging
A self-hostable, decentralized blogging platform built on Lens Protocol — own your content, audience, and distribution forever.
GitButler
Developer Tools · Devops · AI Development
Git, but better — a modern version control client with stacked branches, parallel workflows, unlimited undo, and first-class support for AI-powered development.
Huly Platform
Project Management · Team Chat · Collaboration
Open-source all-in-one workspace that replaces Linear, Jira, Slack, and Notion for product and engineering teams.
Novu
Developer Tools
Open-source communication infrastructure that connects your products and AI agents to every channel your users live on — Inbox, Email, SMS, Push, Chat, and more.
Payload CMS
Developer Tools · Blogging · CMS
The open-source, Next.js-native headless CMS that lives inside your /app folder and gives you a full TypeScript backend instantly.
Phase Console
Security · Devops
End-to-end encrypted secrets management for engineering teams — from local dev to Kubernetes production.