Для начала разберемся с динамической структурой: то, что импортируется и экспортируется, может меняться во время рантайма (англ. runtime).
Когда мы используем статическую структуру, это значит, что мы можем определить все импорты и экспорты только один раз, во время компиляции (модулей в бандл - большой общий файл грубо говоря).
Также при статической структуре модулей нам не надо выполнять код модуля, чтобы найти все импорты и экспорты. Они располагаются на верхнем уровне, потому что система модулей ES6
заставляет нас располагать импорты и экспорты в глобальном скоупе (англ. scope). Мы просто смотрим на исходный код и видим, что экспортируется и импортируется и
самое главное что это неизменно на протяжении всего рантайма.
Инструкции import и export также не должны иметь динамических частей.
В конце покажу два примера НЕстатической структуры (чтобы стало понятно, как отличать одно от другого):
Мы должны выполнить этот код, чтобы понять, что он будет импортировать:
let my_lib;
if (Math.random()) {
my_lib = require('foo');
} else {
my_lib = require('bar');
}
Во втором примере мы должны запустить код, чтобы узнать, что он экспортирует:
if (Math.random()) {
exports.baz = ···;
}
Этот подход является менее гибким, чем динамический, но у него есть много своих преимуществ. Почитать о них и посмотреть примеры можно вот
здесь: , пункт "16.8 Design goals for ES6 modules".