Три различия между требованием и импортом в Node.js
Эти различия относятся к оператору import
, а не к выражению import
(см. Эту страницу для получения дополнительной информации о последнем, который можно использовать для динамического импорта модулей).
Это первая часть из четырех частей, посвященных модулям JavaScript.
- Три различия между требованием и импортом в Node.js
- Использование модулей ES с модулями CommonJS в Node.js
- Использование модулей ES с модулями CommonJS в браузере
- Использование модулей ES с модулями CommonJS с webpack
Ознакомьтесь с полными примерами кода здесь: https://github.com/arcticmatt/javascript_modules/tree/master/import_vs_require.
- При использовании
import ... from ...
путь к модулю должен быть строковым литералом. При использованииrequire
путь к модулю может быть динамическим.
Например, это работает:
const name = "module2";
const obj = require(`./${name}`);
Но это приведет к ошибке SyntaxError: Unexpected template string
при запуске с node
.
const name = "module2";
import { func } from `./${name}`;
Код типа import { func } from ("./partial/path" + someVariable);
также приведет к синтаксической ошибке.
Почему это? Смотрите следующий пункт.
2. Порядок исполнения различается. require
будет запущен встроенным после выполнения приведенного выше кода. import
запускается перед остальной частью скрипта.
Предположим, что module2.js
имеет console.log("require module2");
вверху, тогда, если мы запустим этот код:
console.log("require module1"); const obj = require("./module2"); console.log(`module2 = ${obj.module2}`);
это приводит к следующему:
require module1 require module2 module2 = require module2
С другой стороны, с модулями ES…
console.log("require module1"); import module2 from "./module2.js"; console.log(`module2 = ${module2}`);
Выполнение этого приводит к следующему:
require module2 require module1 module2 = require module2
Модули ES: Глубокое погружение в мультфильм рассматривает эту тему гораздо глубже.
3. Вы можете оставить .js
расширение при импорте локального модуля с require
, но не можете сделать то же самое при использовании import
.
Это верно по умолчанию в браузере и в Node.js. Например, require("./module2")
работает, но эквивалент с использованием import
должен быть записан как import module2 from "./module2.js"
. Если вы опустите расширение в Node.js, вы получите сообщение об ошибке вида: Error [ERR_MODULE_NOT_FOUND]: Cannot find module …
В Node.js вы можете использовать параметр --experimental-specifier-resolution=node
, чтобы обойти это поведение, т.е. это позволит вам опускать .js
расширения при использовании import
.
Кроме того, в webpack есть опция, изменяющая это поведение. В частности, если resolve.enforceExtension
равно true
, требуются расширения. По умолчанию для этого параметра установлено значение false
, что объясняет, почему во многих фреймворках (например, Next.js, который негласно использует webpack) вы можете использовать import
без указания расширений файлов.