Modules & Bundlingmedium

Dynamic import()

import(moduleSpecifier) is a runtime function that loads an ESM module asynchronously and returns a Promise resolving to the module's namespace object. It enables code splitting and conditional loading.

Memory anchor

Dynamic import() is ordering food delivery instead of cooking at home. You only pay (download) when you are actually hungry (need the module), not when you wrote the grocery list (build time). Each import() call is a separate delivery order (chunk).

Expected depth

Dynamic import works in both ESM and CJS (as a syntax feature, not a function). It returns a Promise of the module namespace — use destructuring: const { default: Component } = await import('./Component.js'). Use cases: route-based code splitting in SPAs, conditionally loading polyfills, loading locale files, lazy-loading heavy libraries. Bundlers (Webpack, Vite, Rollup) use import() as a split point — everything in the dynamic import chain becomes a separate chunk.

Deep — senior internals

Dynamic import is a language syntax, not a real function — you can't do const importFn = import; import is not an identifier. This means you can't apply/call it or pass it as a value. The module specifier can be dynamic (a variable or expression), but bundlers analyze static strings at build time for splitting — computed/variable specifiers result in 'dynamic' imports that bundlers handle with magic patterns or glob imports. In Vite: import.meta.glob('./components/*.vue') generates an object of all matching files as dynamic imports. Preloading: <link rel='modulepreload'> or bundler hints like /* webpackChunkName: 'name' */ improve loading performance.

🎤Interview-ready answer

Dynamic import() loads modules asynchronously at runtime, returning a Promise of the module namespace. This enables route-level code splitting (only load what's needed for the current page), conditional polyfill loading, and lazy-loading heavy dependencies. Bundlers treat import() as a code-split point — everything below it becomes a separate chunk downloaded on demand.

Common trap

import() is syntax, not a function — you cannot assign it to a variable, spread it, or use .call/.apply. Also: dynamic import of a default export requires .default from the namespace object: const mod = await import('./foo'); mod.default() — not mod().

Related concepts