◐ Shell
reader mode source ↗
Skip to content
Merged
Changes from all commits
File filter
Conversations
Jump to
Diff view
Apply and reload
Show whitespace
Diff view
Apply and reload
42 changes: 21 additions & 21 deletions 1-js/13-modules/03-modules-dynamic-imports/article.md
Original file line number Diff line number Diff line change
@@ -1,36 +1,36 @@
# Dynamic imports

Export and import statements that we covered in previous chapters are called "static". The syntax is very simple and strict.

First, we can't dynamically generate any parameters of `import`.

The module path must be a primitive string, can't be a function call. This won't work:

```js
import ... from *!*getModuleName()*/!*; // Error, only from "string" is allowed
```

Second, we can't import conditionally or at run-time:

```js
if(...) {
import ...; // Error, not allowed!
}

{
import ...; // Error, we can't put import in any block
}
```

That's because `import`/`export` aim to provide a backbone for the code structure. That's a good thing, as code structure can be analyzed, modules can be gathered and bundled into one file by special tools, unused exports can be removed ("tree-shaken"). That's possible only because the structure of imports/exports is simple and fixed.

But how can we import a module dynamically, on-demand?

## The import() expression

The `import(module)` expression loads the module and returns a promise that resolves into a module object that contains all its exports. It can be called from any place in the code.

We can use it dynamically in any place of the code, for instance:

```js
let modulePath = prompt("Which module to load?");
Expand All @@ -40,9 +40,9 @@ import(modulePath)
.catch(err => <loading error, e.g. if no such module>)
```

Or, we could use `let module = await import(modulePath)` if inside an async function.

For instance, if we have the following module `say.js`:

```js
// 📁 say.js
Expand All @@ -55,7 +55,7 @@ export function bye() {
}
```

...Then dynamic import can be like this:

```js
let {hi, bye} = await import('./say.js');
Expand All @@ -64,7 +64,7 @@ hi();
bye();
```

Or, if `say.js` has the default export:

```js
// 📁 say.js
Expand All @@ -73,7 +73,7 @@ export default function() {
}
```

...Then, in order to access it, we can use `default` property of the module object:

```js
let obj = await import('./say.js');
Expand All @@ -83,16 +83,16 @@ let say = obj.default;
say();
```

Here's the full example:

[codetabs src="say" current="index.html"]

```smart
Dynamic imports work in regular scripts, they don't require `script type="module"`.
```

```smart
Although `import()` looks like a function call, it's a special syntax that just happens to use parentheses (similar to `super()`).

So we can't copy `import` to a variable or use `call/apply` with it. It's not a function.
```
Toggle all file notes Toggle all file annotations