How to dynamically import JavaScript modules

By

Learn how to dynamically import a JavaScript module when the path is built at runtime, using the await import() syntax instead of a static import statement.

~~~

Have you ever felt the need to load a JavaScript module dynamically?

Maybe you’re trying to load something from a folder but you don’t know the name of the folder. You generate it at runtime.

A static import needs a fixed string, because the engine resolves it before running any code. This does not work:

import test from folder + '/test.js'

Neither does this:

import test from `${folder}/test.js`

You need a dynamic import. import() is a function-like call, and you can pass it any string you build at runtime:

const mod = await import(folder + '/test.js')

import() returns a promise, so you await it (inside an async function, or at the top level of an ES module). When it resolves you get a module namespace object with the exports of that file.

If the module has a default export, you read it from .default:

const mod = await import(folder + '/test.js')
const test = mod.default

Named exports sit on the same object, so you can destructure them:

const { formatDate, parseDate } = await import(folder + '/dates.js')

If the path might be wrong or the file missing, wrap the call in try/catch, because the promise rejects:

try {
  const mod = await import(folder + '/test.js')
  mod.default()
} catch (error) {
  console.error('Could not load module', error)
}

Use a static import when you always need the module. Use import() when the path depends on runtime data, or when you want to load some code only after an action, like a click.

import() works in every current browser and in Node.js. I wrote more about it in JavaScript Dynamic Imports.

Want me to talk about your product? You can sponsor this site.

~~~

Related posts about js: