Dynamic import import()
1. What dynamic import is
import()is a loader function that lets you import a module at runtime, rather than statically at the top of a file.
Unlike regular import, which only works at the top level and is parsed synchronously at startup,
import():
- can be called anywhere in the code (for example, inside an
if, a function, a handler); - returns a Promise that resolves to the module's exports object.
2. Syntax
const module = await import('./file.js');or with .then():
import('./file.js').then((module) => {
console.log(module);
});3. An example in Node.js (ESM)
math.js
export function add(a, b) {
return a + b;
}
export function multiply(a, b) {
return a * b;
}app.mjs
const { add } = await import('./math.js');
console.log(add(2, 3)); // 5Works when:
- your project is ESM (
"type": "module"inpackage.json), - or the file has the
.mjsextension.
4. An example with conditional loading
if (process.env.NODE_ENV === 'production') {
const analytics = await import('./analytics.js');
analytics.init();
} else {
console.log('Analytics disabled in development mode');
}analytics.js won't load until the condition is true.
That saves resources, a great technique for lazy-loading.
5. An example inside a function
async function loadAndUseModule() {
const { greet } = await import('./greetings.js');
greet('Tim');
}
loadAndUseModule();greetings.js
export function greet(name) {
console.log(`Hello, ${name}!`);
}6. Importing the whole module
const math = await import('./math.js');
console.log(math.add(2, 2));
console.log(math.multiply(2, 3));math holds every export:
{
add: [Function: add],
multiply: [Function: multiply]
}7. Importing via a variable
Unlike static import, dynamic import() can use variables:
const moduleName = './features/' + process.argv[2] + '.js';
const feature = await import(moduleName);
feature.run();This isn't possible with regular import, since it requires a static path:
import './' + path; // A syntax error8. Importing JSON files (Node.js 20+)
Node.js now lets you import JSON via import():
const data = await import('./config.json', { assert: { type: 'json' } });
console.log(data.default);assert is required:
{ type: 'json' }tells Node.js to load the JSON as a module.
9. Dynamically importing CommonJS modules
If you're in an ESM project but want to import a CommonJS module (the old require):
const { readFileSync } = await import('fs');
const chalk = await import('chalk');
console.log(chalk.default.green('OK!'));Node.js automatically "wraps" the CJS module,
so it's available through default by default.
10. Importing inside a loop
Dynamic import is useful for bulk loading modules:
const features = ['auth', 'billing', 'analytics'];
for (const f of features) {
const mod = await import(`./modules/${f}.js`);
mod.init?.();
}11. Example: lazy loading in practice
routes.mjs
export async function handleRoute(route) {
if (route === '/admin') {
const admin = await import('./routes/admin.mjs');
return admin.handler();
}
const home = await import('./routes/home.mjs');
return home.handler();
}This is an ideal pattern for large servers (Express, Fastify, Next.js SSR):
- only the needed handlers get loaded;
- no wasted memory at runtime.
12. Features and differences from require()
| Criterion | require() (CJS) | import() (ESM) |
|---|---|---|
| Loading | Synchronous | Asynchronous (Promise) |
| Context | CommonJS | ES Modules |
| Caching | Yes | Yes |
| Live bindings | No | Yes |
| Can be called anywhere | Yes | Yes |
| Supports await | No | Yes |
| In browsers | No | Yes |
13. A combined example (Node.js + ESM)
package.json
{
"type": "module"
}app.js
async function start() {
const env = process.env.NODE_ENV || 'dev';
const { default: config } = await import(`./config.${env}.js`);
console.log('Config loaded:', config);
}
start();config.dev.js
export default { db: 'sqlite', debug: true };config.prod.js
export default { db: 'postgres', debug: false };→ at startup, the correct config is picked up with no redundant imports.
14. Under the hood
When import() is called, Node.js:
- Parses the URL (including relative and absolute ones);
- Loads the module asynchronously;
- Caches it;
- Returns a Promise that resolves to the exports object.
In other words, import() ≈ a "lazy" version of import plus await require().
Quick summary
| What it does | Returns | When it runs |
|---|---|---|
import() | A Promise with the module's exports | At runtime |
import (static) | Instantly links the module during parsing | Before the code runs |
In one sentence
Dynamic import (
import()) is an asynchronous way to load ES Modules "on the fly", returning aPromisewith the exports and enabling conditional, lazy, or parameterized code loading at runtime.
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.