Příkazy exportu a importu, které jsme uvedli v předchozích kapitolách, se nazývají „statické“. Jejich syntaxe je velmi jednoduchá a striktní.
Za prvé, žádné parametry příkazu import nemůžeme dynamicky generovat.
Cesta k modulu musí být primitivní řetězec, ne volání funkce. Tohle nebude fungovat:
import ... from vraťNázevModulu(); // Chyba, povoleno je jen from "řetězec"
Za druhé, nemůžeme importovat podmíněně nebo za běhu skriptu:
if(...) {
import ...; // Chyba, tohle není dovoleno!
}
{
import ...; // Chyba, nemůžeme umístit import do bloku
}
Je to proto, že záměrem příkazů import/export je poskytnout páteř struktury kódu. To je dobrá věc, protože strukturu kódu můžeme analyzovat, moduly můžeme speciálními nástroji shromažďovat a spojovat do jednoho souboru, nepoužité exporty můžeme odstraňovat („třesení stromem“). To je možné jen proto, že struktura importů a exportů je jednoduchá a pevná.
Jak ale můžeme importovat modul dynamicky, na požádání?
Výraz import()
Výraz import(modul) načte modul a vrátí příslib, který se splní do objektu modulu obsahujícího všechny jeho exporty. Může být volán z kteréhokoli místa v kódu.
Můžeme jej používat dynamicky na kterémkoli místě kódu, například:
let cestaModulu = prompt("Který modul načíst?");
import(cestaModulu)
.then(obj => <objekt modulu>)
.catch(chyba => <chyba při načítání, např. když takový modul neexistuje>)
Nebo můžeme použít let modul = await import(cestaModulu), jsme-li uvnitř asynchronní funkce.
Například jestliže máme následující modul řekni.js:
// 📁 řekni.js
export function ahoj() {
alert(`Ahoj`);
}
export function nashle() {
alert(`Nashle`);
}
…Pak dynamický import může vypadat takto:
let {ahoj, nashle} = await import('./řekni.js');
ahoj();
nashle();
Nebo jestliže řekni.js obsahuje výchozí export:
// 📁 řekni.js
export default function() {
alert("Modul načten (výchozí export)!");
}
…Pak můžeme pro přístup k němu použít vlastnost default objektu modulu:
let obj = await import('./řekni.js');
let řekni = obj.default;
// nebo na jednom řádku: let {default: řekni} = await import('./řekni.js');
řekni();
Zde je celý příklad:
export function ahoj() {
alert(`Ahoj`);
}
export function nashle() {
alert(`Nashle`);
}
export default function() {
alert("Modul načten (výchozí export)!");
}<!doctype html>
<script>
async function načti() {
let řekni = await import('./say.js');
řekni.ahoj(); // Ahoj!
řekni.nashle(); // Nashle!
řekni.default(); // Modul načten (výchozí export)!
}
</script>
<button onclick="načti()">Klikni na mě</button>Dynamické importy fungují i v běžných skriptech, nevyžadují script type="module".
Ačkoli import() vypadá jako volání funkce, je to speciální syntaxe, která prostě jen používá závorky (podobně jako super()).
Nemůžeme tedy kopírovat import do proměnné nebo s ním používat call/apply. Není to funkce.
Komentáře
<code>, pro několik řádků je obalte značkou<pre>, pro více než 10 řádků vložte odkaz na pískoviště (plnkr, jsbin, codepen…)