JavaScript Dynamic Imports

Last updated Sep 10, 2021javascriptguides

Dynamic imports refer to the imports using new stage-4 proposal syntax import(specifier) to load modules dynamically at runtime in JavaScript. This syntax looks like a function but not an actual function, returns a promise, and contrast to standard pre-runtime static imports.

// 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 specifier
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 module specifier 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.