Skip to main content

Dynamic import

What dynamic import is

Dynamic import is a call to the import() function, which returns a Promise and lets you load modules at runtime, rather than at build time.

Example:

javascript
// Dynamic import const module = await import('./utils.js'); module.sayHello();

Difference from a static import:

javascript
// Static import import { sayHello } from './utils.js';

With a static import, the entire module loads immediately at startup. With a dynamic one, it loads only when it's actually needed.


Syntax

javascript
import(modulePath) .then(module => { // the module is loaded module.default(); }) .catch(err => console.error(err));

or with await:

javascript
const module = await import('./math.js'); const { sum } = module; console.log(sum(2, 3));

What import() returns

import() returns a Promise that resolves with the module object:

javascript
// math.js export function add(a, b) { return a + b; } export const PI = 3.14;
javascript
const math = await import('./math.js'); console.log(math.add(2, 3)); // 5 console.log(math.PI); // 3.14

Example: conditional import

You can dynamically load different modules depending on the situation:

javascript
if (navigator.language.startsWith('fr')) { const messages = await import('./lang/fr.js'); console.log(messages.default.hello); } else { const messages = await import('./lang/en.js'); console.log(messages.default.hello); }

This is great for multilingual interfaces, plugins, heavy dependencies, and lazy loading of pages.


Example: handling load errors

javascript
try { const module = await import('./missing.js'); } catch (err) { console.error('Error loading the module:', err); }

Example: loading on a user action

javascript
button.addEventListener('click', async () => { const { openModal } = await import('./modal.js'); openModal(); });

The modal.js module will load only on the first click, not when the site starts - saving traffic and speeding up startup.


Dynamic import with variables

You can use dynamic paths, which is impossible with static imports:

javascript
const theme = 'dark'; const module = await import(`./themes/${theme}.js`); module.applyTheme();

Important: the bundler (for example, Webpack) still needs to be able to predict the path pattern - otherwise it won't include the required files in the build.


When to use dynamic import

ScenarioWhy it's useful
Lazy loading componentsLoad a component only when navigating to the page that needs it
Translations / localizationImport the required language dynamically
Heavy dependenciesDeferred loading of large libraries (chart.js, moment, three.js)
Plugins / modular architectureLoad functionality on demand
SSR + Code splittingIn Next.js, Vite, Webpack - automatic bundle splitting
Feature flags / A/B testsLoad different modules depending on a flag

How it works under the hood

Bundlers (Webpack, Rollup, Vite, ESBuild):

  1. Analyze import('./path') expressions.
  2. Do code splitting - split the project into chunks.
  3. Load the required chunk over the network when import() is called.

Example (Webpack output):

javascript
main.js (main code) vendors~chart.js (library) chart.js (loads on click)

Difference from require()

Criterionimport()require()
TypeAsynchronous (Promise)Synchronous
Works inESM (browser, Node)CommonJS (Node)
Can be used dynamicallyYesLimited
Supports tree-shakingYesNo
Supported by bundlers (code-splitting)YesNo

Example: in React / Next.js

javascript
import dynamic from 'next/dynamic'; const Chart = dynamic(() => import('../components/Chart'), { ssr: false, loading: () => <p>Loading...</p>, }); export default function Page() { return ( <div> <h1>Data</h1> <Chart /> </div> ); }

The <Chart> component will load only in the browser, and only when the user opens the page.


Summary

What it doesLoads modules asynchronously (on demand)
ReturnsA Promise with the module object
Works inES Modules (Node, browser)
Used forLazy loading, code splitting, A/B tests, dynamic localization
Syntaxconst module = await import('./file.js')

The main idea:

Dynamic import is "lazy" module loading. Instead of shipping the whole application at once, you load only what's needed, when it's needed.

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.