Dynamic Module Loading: import() Function
Learn the interview-ready mental model, practical trade-offs, and production patterns for this web fundamentals topic.
Topic content
The dynamic import() function loads JavaScript modules at runtime and returns a Promise. It is the primary mechanism for code splitting and lazy loading in modern applications. Unlike static imports, dynamic imports are evaluated at runtime, allowing you to defer non-critical code until it is actually needed.
Static imports are like pre-ordering everything before the party starts (larger initial bundle). Dynamic import() is like ordering only what guests actually want when they arrive — smaller initial load, but you pay a small delay when the feature is requested.
1Basic Usage
Dynamic import returns a Promise that resolves to the module namespace object. It supports await syntax and .then() chaining.
async function loadFeature() {
const module = await import('./heavy-feature.js');
module.default.init();
}
// Destructuring examples
const { default: Component } = await import('./Component.jsx');
const { util1, util2 } = await import('./utils.js');2Code Splitting & Lazy Loading
Bundlers treat import() as a split point and create separate chunks. This moves non-critical code out of the initial bundle, reducing startup time.
3Conditional & Interaction-Driven Loading
Best used for route-based loading, modals, admin panels, heavy libraries, or user-triggered features. Supports parallel loading with Promise.all().
4Advanced Patterns & Caveats
Modules are cached after first load. Fully dynamic paths (variables) are harder for bundlers to optimize. Always handle errors and show loading states.
- ✓import() is the foundation of code splitting and lazy loading
- ✓Use it for optional, heavy, route-based, or user-triggered features
- ✓Always pair with loading UI and proper error handling
- ✓Modules are cached after first load
- ✓Balance bundle reduction with interaction latency — measure real impact