importx

Unified tool for importing TypeScript modules at runtime.
Motivation
It's a common need for tools to support importing TypeScript modules at runtime. For example, to support configure files written in TypeScript.
There are so many ways to do that, each with its own trade-offs and limitations. This library aims to provide a simple, unified API for importing TypeScript modules and swap loaders as ease.
By default, it also provides a smart "auto" mode that decides the best loader based on the environment:
- Use native
import()
for runtimes that support directly importing TypeScript modules (Deno, Bun, or ts-node
, tsx
CLI). - Use
tsx
for modern module environments. - Use
jiti
for older Node.js that don't support tsx
. - Use
bundle-require
when you want to import a module without the ESM cache.
Usage
npm i importx
const mod = await import('importx').then(x => x.import('./path/to/module.ts', import.meta.url))
Loaders
auto
Automatically choose the best loader based on the environment.
graph TD
A[Auto] --> IsTS{{"Is importing TypeScript file?"}}
IsTS --> |No| Cache{{"Import cache?"}}
Cache --> |Yes| B([native import])
Cache --> |No| tsx1[tsx]
IsTS --> |Yes| Cache2{{"Import cache?"}}
Cache2 --> |Yes| D{{"Supports native TypeScript?"}}
Cache2 --> |No| tsx2[tsx]
D --> |Yes| E([native import])
D --> |No| F{{"Is Node.js version range supports tsx?"}}
F --> |Yes| G[tsx]
F --> |No| H[jiti]
native
Use the native import()
to import the module.
tsx
Use tsx
's tsImport
API to import the module. Under the hood, it registers Node.js loader API and uses esbuild to transpile TypeScript to JavaScript.
Pros
- Native Node.js loader API, consistent and future-proof.
Limitations
- Requires Node.js
^18.18.0
, ^20.6.0
or above.
jiti
Use jiti
to import the module. It uses a bundled Babel parser to transpile modules. It runs in CJS mode and has its own cache and module runner.
Pros
- Self-contained, does not dependents on esbuild.
- Own cache and module runner, better and flexible cache control.
Limitations
bundle-require
Use bundle-require
to import the module. It uses esbuild
to bundle the entry module, saves it to a temporary file, and then imports it.
Pros
- Get the file list of module dependencies. Helpful for hot-reloading or manifest generation.
Limitations
- It creates a temporary bundle file on importing (will external
node_modules
). - Can be inefficient where there are many TypeScript modules in the import tree.
- Always import a new module, does not support module cache.
Cache
By definition, ESM modules are always cached by the runtime, which means you will get the same module instance when importing the same module multiple times. In some scenarios, like a dev server watching for config file changes, the cache may not be desired as you want to get the new module with the latest code on your disk.
importx
allows you to specify if you want to have the module cache or not, by providing the cache
option:)
const mod = await import('importx')
.then(x => x.import('./path/to/module.ts', {
cache: false,
parentURL: import.meta.url,
}))
Setting cache: null
(default) means you don't care about the cache (if you only import the module once).
Note that some loaders always have a cache, and some loaders always have no cache. With the auto
loader, we will choose the best loader based on your need. Otherwise, an unsupported combination will throw an error. For example:
const mod = await import('importx')
.then(x => x.import('./path/to/module.ts', {
cache: true,
loader: 'bundle-require',
parentURL: import.meta.url,
}))
Runtime-Loader Compatibility Table
Generated with version v0.0.1 at 2024-05-11T03:58:02.482Z
| native | tsx | jiti | bundle-require |
---|
node | Import: ❌ Cache: ❌ No cache: ❌ | Import: ✅ Cache: ❌ No cache: ✅ | Import: ✅ Cache: ✅ No cache: ✅ | Import: ✅ Cache: ❌ No cache: ✅ |
tsx | Import: ✅ Cache: ✅ No cache: ❌ | N/A | N/A | N/A |
deno | Import: ✅ Cache: ✅ No cache: ❌ | N/A | N/A | N/A |
bun | Import: ✅ Cache: ✅ No cache: ❌ | N/A | N/A | N/A |
License
MIT License © 2023-PRESENT Anthony Fu