Install & Compatibility
Where this runs
tested against v? · npm install
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslnode 18–226 runs
build_error
glibcnode 18–226 runs
build_error
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
CLI Runtime Hook
✓ node -r esbuild-register file.ts
This is the primary way to use esbuild-register for CommonJS modules or when 'type': 'commonjs' in package.json. It hooks into Node.js's require system.
ESM Loader
✓ node --loader esbuild-register/loader -r esbuild-register ./file.ts
✗ node -r esbuild-register ./file.ts (when 'type': 'module')
Required for projects with 'type': 'module' in package.json to correctly load TypeScript files as ES Modules. The `--loader` flag enables the experimental Node.js ESM loader.
Programmatic Register
✓ const { register } = require('esbuild-register/dist/node')
✗ import { register } from 'esbuild-register/dist/node'
The programmatic API for `register` and `unregister` is exposed via a CommonJS module located at `dist/node`, hence `require` is the correct way to import it, even in an ESM context via a wrapper.
Demonstrates running a simple TypeScript HTTP server using both the `require` hook and the experimental ESM loader.
/* file.ts */
import { createServer } from 'http';
interface Greeter {
greet(name: string): string;
}
const myGreeter: Greeter = {
greet(name: string): string {
return `Hello, ${name}! This is esbuild-register running TypeScript.`;
},
};
const server = createServer((req, res) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end(myGreeter.greet('World') + '\n');
});
const PORT = process.env.PORT ?? '3000';
server.listen(Number(PORT), () => {
console.log(`Server running at http://localhost:${PORT}/`);
console.log('Try running with: node -r esbuild-register file.ts');
console.log('Or for ESM projects: node --loader esbuild-register/loader -r esbuild-register file.ts');
});
Debug
Known issues
breakingThe experimental ESM loader (esbuild-register/loader) stopped working in Node.js 20.6.0 due to internal changes in Node.js's ESM loader implementation. This often manifested as 'SyntaxError: Cannot use import statement outside a module'. While potential fixes or workarounds might exist, relying on experimental Node.js features carries inherent risks of breakage in minor updates.fixAs per discussions, the fix might involve updating Node.js or esbuild-register if a new version addresses this, or restructuring code to avoid the affected patterns. Users might need to downgrade Node.js or consider alternatives like `tsx` for robust ESM support.
affects: Node.js >=20.6.0 (when using --loader)
gotchaesbuild-register's peer dependency `esbuild` (current range `^0.12.0 <1`) is subject to frequent breaking changes in its own minor versions (e.g., esbuild v0.17 introduced breaking changes to `watch()`, `rebuild()`, and `serve()` APIs). While `esbuild-register` might generally work with newer `esbuild` versions within its peer dependency range, specific features or underlying API calls might break if esbuild-register has not been updated to accommodate `esbuild`'s breaking changes.fixCarefully manage `esbuild` version pinned to the version `esbuild-register` was last tested with, or consult `esbuild-register`'s issues for compatibility notes with specific `esbuild` versions. Be prepared for potential breakage when updating `esbuild`.
affects: >=3.0.0 (esbuild-register) with newer `esbuild` versions within the peer dependency range.
gotchaesbuild-register is a runtime transpiler, meaning it transpiles code on demand when Node.js encounters it. While significantly faster than other runtime transpilers, it still incurs overhead compared to a dedicated build step using `esbuild` directly as a bundler. For production deployments or large-scale applications, pre-compilation is generally recommended for optimal performance.fixFor performance-critical applications, consider a build step with `esbuild` directly, `tsc`, or a bundler like Webpack/Rollup with an esbuild loader, rather than relying solely on runtime transpilation.
affects: All versions
deprecatedThe Node.js `--loader` flag used by `esbuild-register/loader` is still considered experimental by Node.js, even if `esbuild-register` exposes it. This means its behavior can change in future Node.js versions without adhering to semantic versioning, potentially leading to unexpected breakages.fixMonitor Node.js release notes for updates on its loader API. For more stable ESM runtime execution, consider `tsx` which aims to provide a more robust experience, often by integrating similar loading mechanisms.
affects: All versions
Errors
Common errors & fixes
SyntaxError: Cannot use import statement outside a module
Using `node -r esbuild-register file.ts` in an ESM project (`"type": "module"` in package.json) or when Node.js's experimental loader behavior changed in 20.6.0.
fixFor ESM projects, use `node --loader esbuild-register/loader -r esbuild-register ./file.ts`. If on Node.js 20.6.0+, this error might indicate incompatibility due to Node.js's loader changes; consider a Node.js version downgrade or an alternative loader.
Error: Cannot find module 'esbuild'
The peer dependency `esbuild` was not installed alongside `esbuild-register`.
fixInstall `esbuild` explicitly: `npm install esbuild esbuild-register -D` (or `yarn add esbuild esbuild-register --dev`, `pnpm add esbuild esbuild-register -D`).
TypeError: (0 , esbuild_register_dist_node_1.register) is not a function
Attempting to `import { register } from 'esbuild-register/dist/node'` in an ESM context when the module is CJS-only or doesn't provide a named ESM export for `register`.
fixUse CommonJS `require` for programmatic access: `const { register } = require('esbuild-register/dist/node')`. Audit
Dependencies
esbuildrequiredCore transpilation engine. Must be installed alongside esbuild-register as a peer dependency.