Modules

Modules, introduction

import { sayHi } from "./sayHi.js";

Core module features:

<!DOCTYPE html>
<script type="module" src="hello.js"></script>
// 📁 alert.js
alert("Module is evaluated!");
// Import the same module from different files
// 📁 1.js
import "./alert.js"; // Module is evaluated!

// 📁 2.js
import "./alert.js"; // (shows nothing)
<script type="module">
  alert(import.meta.url); // script URL
  // for an inline script - the URL of the current HTML-page
</script>
<script>
  alert(this); // window
</script>

<script type="module">
  alert(this); // undefined
</script>

Dynamic imports

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:

import ... from getModuleName(); // Error, only from "string" is allowed

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

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

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

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.

let modulePath = prompt("Which module to load?");

import(modulePath)
  .then(obj => console.log(obj));
  .catch(err => console.log("loading error, e.g. if no such module"));

// We could import like this if inside any async function
let module = await import(modulePath);