Skip to content

JavaScript Tutorial Modules

Dynamic import()

Lesson 172 of 258 2 min read By Deepak Paswan Updated Oct 4, 2026

A normal import at the top of a file is static: the browser loads it before your code runs. Dynamic import() is a function-like expression that loads a module when you call it, and returns a promise.

script.js
JS
const module = await import("./chart.js");
module.drawChart(data);

Why load code later?

  • A heavy feature (a chart, an editor, a PDF viewer) is only needed after a click, so there is no reason to download it on page load. This is lazy loading, and it makes the first load faster.
  • Load a module only if a condition is true.
  • Choose a module by name at run time.

Try it

index.html
HTML
<button id="load">Load module</button>
<p id="out"></p>
<script type="module">
  // In a real project: await import("./greeting.js")
  const source = "data:text/javascript," + encodeURIComponent(`
    export default function greet(name) { return "Hello from a lazy module, " + name; }
  `);

  document.querySelector("#load").addEventListener("click", async () => {
    document.querySelector("#out").textContent = "Loading…";
    const { default: greet } = await import(source);
    document.querySelector("#out").textContent = greet("Maya");
  });
</script>

The module is not loaded until the button is clicked.

What you get back

A module namespace object: named exports are properties, and the default export is .default.

script.js
JS
const { add, subtract } = await import("./math.js");
const { default: Logger } = await import("./Logger.js");

Handle failures

The network can fail, so a dynamic import can reject.

script.js
JS
try {
  const { renderChart } = await import("./chart.js");
  renderChart(data);
} catch (error) {
  showMessage("Could not load the chart. Please try again.");
}

Load once, reuse

Imported modules are cached, so calling import() again for the same file is cheap. A common pattern keeps the promise:

script.js
JS
let chartModule;
function loadChart() {
  chartModule ??= import("./chart.js");
  return chartModule;
}

Preloading

You can start loading early (on hover, or after the page is idle), so the module is ready by the time the user needs it:

script.js
JS
button.addEventListener("pointerenter", () => import("./editor.js"), { once: true });

Code splitting

Bundlers use dynamic import() as a signal to split your code into separate chunks that load separately. See Code Splitting.

Differences from static import

Static importimport()
Wheretop level onlyanywhere
Loadsbefore the code runswhen called
Returnsbindingsa promise
Patha string literalany expression
lightbulb
Do not overuse it
Lazy loading adds a delay when the feature is first used. Use it for large, rarely used code, not for every small module.