use-m: dynamically import any JavaScript module anywhere
use-m
(m
stands for module
) is a utility for dynamically importing any JavaScript module (npm package) at runtime anywhere (browser or server).
It may be useful for standalone scripts that do not require a package.json
. Also it may make your code portable across environments (for example it may require no changes in your code when executed in CommonJS, ES Modules and browser). You can ensure predictable behavior of your code over time by specifying the exact version to import directly in your script, similar to how versions are specified in package.json. You even can import multiple versions of the same library at the same time. You can use use-m
when you don't want your package.json
to be poluted with optional packages. You may keep your package.json
with as little dependencies as needed thanks to use-m
.

- use-m: dynamically import any JavaScript module anywhere
- Dynamic package loading: In
node.js
,use-m
loads and imports npm packages on-demand with global installation (usingnpm i -g
with separate alias for each version), making them available across projects and reusable without needing to reinstall each time. In case of a browseruse-m
loads npm packages directly from CDNs (by defaultesm.sh
is used). - Version-safe imports: Allows multiple versions of the same library to coexist without conflicts, so you can specify any version for each import (usage) without affecting other scripts or other usages (imports) in the same script.
- No more
require
,import
, orpackage.json
: Withuse-m
, traditional module loading approaches likerequire()
,import
statements, andpackage.json
dependencies become effectively obsolete. You can dynamically load any module at runtime without pre-declaring dependencies in separate file. This enables truly self-contained.mjs
files that can effectively replace shell scripts. - Built-in modules emulation: Provides emulation for Node.js built-in modules across all environments (browser, Node.js, Bun, Deno), ensuring consistent behavior regardless of the runtime.
- Relative path resolution: Supports
./
and../
paths for loading local JavaScript and JSON files relative to the executing file, working seamlessly even in browser environments.
Works in CommonJS, ES Modules and browser, and interactive environments.
fetch('https://unpkg.com/use-m/use.js')
.then(async useJs => {
const { use } = eval(await useJs.text());
const _ = await use('[email protected]');
console.log(`_.add(1, 2) = ${_.add(1, 2)}`);
});
Universal execution comes at cost of eval
usage, that is considered potential security threat. In case of this library only single file is evaled, it short, unminified and has no dependencies, so you can check the contents yourself. Once you have use
function instance no more eval
function will be executed by this library. If you don't want to use eval
you can use await import()
in browser or in node.js
. In node.js
you can also just install the package from npm
as usual.
-
Get the
use
function fromuse-m
package:Single line version:
const { use } = eval(await (await fetch('https://unpkg.com/use-m/use.js')).text());
Formatted multiple version:
const { use } = eval( await ( await fetch( 'https://unpkg.com/use-m/use.js' ) ).text() );
-
Import your favorite NPM package from the registry (for example
lodash
):const _ = await use('[email protected]');
-
Use your favorite function from dynamically imported package (for example
add
):_.add(1, 2)
Your output should be similar to the next screenshot.

If you don't want to use eval
in the browser, you can import use-m
like this:
const { use } = await import("https://esm.sh/use-m");
const _ = await use('[email protected]');
console.log(`_.add(1, 2) = ${_.add(1, 2)}`);
Only 2 lines and now have an interactive playground for JavaScript and almost any NPM library directly in your browser's console. No more cloud based sandboxes required. Sorry VSCode, you don't have such super powers yet.
use-m
works seamlessly with Deno! It automatically detects the Deno runtime and uses esm.sh
as the default CDN.
// Import use-m from CDN
const { use } = await import('https://esm.sh/use-m');
// Use any npm package
const _ = await use('[email protected]');
console.log(`_.add(1, 2) = ${_.add(1, 2)}`);
// Import multiple packages
const [lodash3, lodash4] = await use.all('lodash@3', 'lodash@4');
Run with Deno:
deno run --allow-net example.mjs
use-m
works seamlessly with Bun! It automatically detects the Bun runtime and provides optimized module loading.
// Import use-m from CDN
const { use } = await import('https://esm.sh/use-m');
// Use any npm package
const _ = await use('[email protected]');
console.log(`_.add(1, 2) = ${_.add(1, 2)}`);
// Import multiple packages
const [lodash3, lodash4] = await use.all('lodash@3', 'lodash@4');
Run with Bun:
bun run example.mjs
It is possible to use --experimental-network-imports
to enable the same style of imports as in browser version. See the example.
-
Create file named
example.mjs
:const { use } = await import('https://unpkg.com/use-m/use.mjs'); const _ = await use('[email protected]'); console.log(`_.add(1, 2) = ${_.add(1, 2)}`);
-
Execute the script using
--experimental-network-imports
option:node --experimental-network-imports example.mjs
If you need to use use-m
without adding it to a project locally, you can load it directly from unpkg
using fetch
. This is particularly useful for creating self-contained scripts without any package.json
, node_modules
, etc.
command-stream is a modern shell utility library with streaming, async iteration, and EventEmitter support. It provides the most advanced command execution capabilities including virtual commands, built-in cross-platform commands, and real-time streaming.
-
Create a file named
example.mjs
:const { use } = eval( await fetch('https://unpkg.com/use-m/use.js').then(u => u.text()) ); const { $ } = await use('command-stream'); const _ = await use('lodash'); // Use command-stream's advanced features for await (const chunk of $`ls -la`.stream()) { if (chunk.type === 'stdout') { const files = chunk.data.toString(); console.log('Files:', _.filter(files.split('\n'), f => f.includes('.js'))); } } // Built-in cross-platform commands await $`mkdir -p build`; await $`echo "Build complete" > build/status.txt`;
-
Execute:
node example.mjs
Bun provides a built-in $
shell API that works seamlessly with use-m
:
-
Create a file named
example.mjs
:#!/usr/bin/env bun const { use } = eval( await fetch('https://unpkg.com/use-m/use.js').then(u => u.text()) ); const _ = await use('lodash'); // Use Bun's built-in $ directly const { stdout } = await $`ls`.pipe($`grep js`); const files = _.filter( _.split(stdout.toString(), '\n'), (item) => !_.isEmpty(item) ); console.log(files);
-
Execute with Bun:
bun run example.mjs
-
Install zx globally
npm install -g zx
-
Create a file named
example.mjs
:#!/usr/bin/env zx --verbose const { use } = eval( await fetch('https://unpkg.com/use-m/use.js').then(u => u.text()) ); const _ = await use('lodash@latest'); const { stdout } = await $`ls`.pipe`grep js`; const files = _.filter( _.split(stdout, '\n'), (item) => !_.isEmpty(item) ); console.log(files);
-
Give execution permissions
chmod +x example.mjs
-
Execute:
./example.mjs
-
Create a file named
example.mjs
:#!/usr/bin/env node const { use } = eval( await fetch('https://unpkg.com/use-m/use.js').then(u => u.text()) ); const _ = await use('lodash'); const { $: $$ } = await use('execa'); const $ = $$({ verbose: 'full' }); const { stdout } = await $`ls`.pipe`grep js`; const files = _.filter( _.split(stdout, '\n'), (item) => !_.isEmpty(item) ); console.log(files);
Note: in ES Module environments where __filename
and require
are not defined, you may need to add meta
option into use
function constructor, as it is not possible to access import.meta
inside eval
.
-
Execute:
node example.mjs
You can still install and import use-m
in node.js
as usual. For example if you don't want to use eval
in node.js
.
Add use-m
to your project with Yarn:
yarn add use-m
Or NPM:
npm i use-m
Load use-m
to dynamically import the lodash
package from npm:
const { use } = require('use-m');
(async () => {
const _ = await use('[email protected]');
console.log(`_.add(1, 2) = ${_.add(1, 2)}`);
})();
or
import('use-m')
.then(async ({ use }) => {
const _ = await use('[email protected]');
console.log(`_.add(1, 2) = ${_.add(1, 2)}`);
});
import { use } from 'use-m';
const _ = await use('[email protected]');
console.log(`_.add(1, 2) = ${_.add(1, 2)}`);
or
const { use } = await import('use-m');
const _ = await use('[email protected]');
console.log(`_.add(1, 2) = ${_.add(1, 2)}`);
You can check out usage examples source code. You can also explore our tests to get even more examples.
If you have any questions or issues, please write us on GitHub. Together we can ensure this package will have highest quality possible. Your feedback is valuable and helps improve the project.
We welcome contributions! To contribute please open Pull Request with any suggested changes.
This project is licensed under the Unlicense (public domain). That means you are absolutely free to use this library, there is no conditions or limitations on how this library and its code can be used.