JavaScript Dynamic Imports

Updated Mar 11, 2023#javascript#guides

In JavaScript, dynamic imports refer to the imports using function-like expression import(moduleName) to load modules dynamically at runtime. This syntax looks like a function but not an actual function, returns a promise, and contrast to standard static imports which evaluated at load time.

// used with then-based callback
import('/path/to/module.js').then((module) => {
  // good to use module now
})

// or with async/await
const module = await import('/path/to/module.js')

// compute moduleName
const locale = getCurrentLocale()
const languagePack = await import(`/path/to/${locale}.js`)

// load multiple modules
const [moduleA, moduleB, moduleC] = await Promise.all([
  import('/path/to/module-a.js'),
  import('/path/to/module-b.js'),
  import('/path/to/module-c.js')
])

This syntax is powerful and unlocks many capabilities which are impossible to do with static imports:

  • Import a module conditionally on-demand anywhere in your code, powerful to lazy-load heavy modules, currently used heavily by web frameworks and module bundlers to support code splitting.
  • Compute moduleName at runtime.
  • Works in regular scripts without script type="module".
  • Load all or race multiple modules at the same time with Promise API.

Remember that this syntax does not establish a dependency which can be statically analyzed and must be fetched and evaluated before the containing module is evaluated. The exact mechanism for retrieving the module is left up to the host environments (browsers, Node.js, etc.).

Use dynamic imports only when necessary. The static imports are preferable for loading initial dependencies, and can benefit more readily from static analysis tools and tree shaking.