JavaScript Dynamic Modules
JavaScript Dynamic Import
Dynamic Import was introduced in ECMAScript 2020
Dynamic import is one of the most powerful features for modular and efficient code.
Dynamic Import is a way to load JavaScript modules at runtime, rather than at the start of your program.
Modern Software
Modern software splits imports into separate chunks.
Modules are downloaded only when requested - this method has many names:.
- Dynamic Import
 - Code Splitting
 - Lazy Loading
 - Conditional Loading
 
Unlike Static Import (which must appear at the top of a file), Dynamic Import can be used anywhere - inside functions, conditionals, event handlers, etc.
Syntax
- The argument must be a string or expression that resolves to a path
 - You must run the import inside a module script (<script type="module">)
 
| Type | Example | When Loaded | 
|---|---|---|
| Static | import { add } from './math.js'; | 
At load time | 
| Dynamic | const math = await import('./math.js'); | 
When needed | 
Improved Performance
Modules can improve performance by allowing tools to implement "code splitting". This means that a user's browser only needs to load the JavaScript modules required for the specific features they are using at a given moment, rather than the entire application's code at once.
While modules themselves are a language feature, when combined with bundlers like Webpack or Rollup, they can lead to performance improvements through optimizations like tree-shaking (eliminating unused code), code splitting, and minification.
How Dynamic Import Works
Dynamic Modules use modern async/await:
Example
const module = await import("./math.js");
let result = module.add(2, 3);
}
run();
math.js
export function add(a, b) {
return a + b;
}
Example Explained
- The script starts running
 - It defines and calls run()
 - Inside run(), it dynamically loads math.js
 - Once loaded, it gets access to the exported function add()
 - It calls add(2, 3) and gets 5
 - It displays the result
 
| Step | Code | Explained | 
|---|---|---|
| 1 | async function run() | Define a function that can use await | 
| 2 | await import("./math.js") | Load the module file only when needed | 
| 3 | module.add(2, 3) | Use the exported function from the module | 
| 4 | run() | Start the process | 
Step 1. Define a function that can use await:
- This line defines an asynchronous function called run()
 - The async keyword means the function can use await inside it
 - The await keyword pauses the function until a Promise is resolved
 - In this case, the Promise is the import of the module
 
Step 2. Load the module file only when needed:
- import("./math.js") defines a dynamic import
 - The module math.js is loaded on demand
 - math.js returns a Promise that resolves to its exported content
 - The await keyword waits until the module is fully loaded
 - Once loaded, the variable module contains the data exported from math.js
 
Step 3. Use the exported function from the module:
- Calls the exported function add() from the imported module
 - Passes in 2 and 3 as arguments
 - The function adds them and returns 5
 - The result is stored in result
 
Step 4. Start the process - Call the Function:
When it runs:
- It loads the module math.js dynamically
 - It waits for the module to finish loading
 - It calls the add() function of the module
 - It displays the result
 
Another Example
Example
const module = await import("./temperatures.js");
let celsius = module.toCelsius(x);
document.getElementById("demo").textContent = celsius + " Celcius";
}
run(50);
temperatures.js
export function toCelsius(farenheit) {
return (farenheit - 32) * 5 / 9;
}
// Convert Celsius to Fahrenheit
export function toFahrenheit(celsius) {
return (celsius * 9 / 5) + 32;
}
Dynamic Import Key Features
- Lazy Loading - Load code only when it is needed
 - Performance Optimization - Reduce initial load size for faster page load
 - Conditional Imports - Import different modules based on conditions.
 
Conditional Loading
const adminTools = await import("./admin-tools.js");
adminTools.init();
}