Dynamic Imports & Code Splitting0%

Dynamic Imports & Code Splitting

Beginner12 min read•Updated: Jul 11, 2026
Study Materials

Dynamic Imports & Code Splitting in Modern JavaScript

As web applications grow, loading an entire monolithic bundle upon the user's initial page visit degrades First Contentful Paint (FCP) and Time to Interactive (TTI). Dynamic Imports using the function-like import() syntax enable Code Splitting—downloading chunks of JavaScript on-demand only when actually needed.


1. Static vs. Dynamic Imports

JavaScript
// STATIC IMPORT: Must be at top of file, blocks initial bundle load
import { HeavyChart } from './components/HeavyChart.js';
 
// DYNAMIC IMPORT: Can be invoked inside any function, event handler, or condition
const loadChartBtn = document.querySelector('#btn-show-chart');
 
loadChartBtn.addEventListener('click', async () => {
// Downloads 'HeavyChart.js' chunk over network ONLY when button is clicked!
const { HeavyChart } = await import('./components/HeavyChart.js');
const chart = new HeavyChart();
chart.render('#chart-target');
});

2. Architectural Mechanics of Code Splitting

When modern bundlers (Webpack, Vite, Rollup, Next.js) encounter import('./path'):

  1. 1
    They automatically split that module and its private dependencies into an isolated chunk file (e.g. HeavyChart.chunk-a98f12.js).
  2. 2
    The main bundle size is significantly reduced.
  3. 3
    At runtime, the browser initiates a network fetch for the chunk only when the import() expression is reached.
Output
┌──► app.js (Main Initial Bundle: 45KB)
│
Application Build ──┼──► analytics.chunk.js (Downloaded on Idle: 20KB)
│
└──► checkout.chunk.js (Downloaded on Route Change: 120KB)

3. Route-Based Code Splitting

In Single Page Applications (SPAs), loading views for pages the user may never visit is wasteful. Route-based splitting dynamically loads view controllers:

JavaScript
const routes = {
'/': () => import('./views/HomeView.js'),
'/dashboard': () => import('./views/DashboardView.js'),
'/settings': () => import('./views/SettingsView.js')
};
 
async function navigateTo(path) {
const loadRoute = routes[path] || routes['/'];
showLoadingSpinner();
try {
const { default: ViewComponent } = await loadRoute();
const view = new ViewComponent();
view.mount('#app-root');
} catch (err) {
showErrorPage('Failed to load page chunk.');
} finally {
hideLoadingSpinner();
}
}

4. Chunk Prefetching & Preloading

To eliminate user wait times after code splitting, modern applications instruct the browser to prefetch chunks during idle network bandwidth:

Magic Comments in Webpack / Vite

JavaScript
// Webpack Magic Comments:
const module = await import(
/* webpackChunkName: "admin-panel" */
/* webpackPrefetch: true */
'./admin/AdminPanel.js'
);

Interactive Quiz

Practice Quiz

Question 1
What does the dynamic import('path') expression return?
Question 2
How do you access the default export from a dynamically imported module?
Question 3
What is the primary performance benefit of Code Splitting?
Question 4
Which link rel attribute hints to the browser to download a script in the background during idle network time?
Question 5
Can dynamic import() be used conditionally inside an if block or try...catch?
Next Lesson

Tree Shaking & Module Bundling Concepts

Continue learning with hands-on practice, examples, and exercises in the upcoming topic.

Practice Quiz

Test your understanding of this lesson with 5 questions. Each question has one correct answer.

PrevNext