В системе модульного разрешения JavaScript и TypeScript важную роль играет порядок, в котором сборщик пытается сопоставить импортируемые пути с реальными файлами. В esbuild эта логика управляется параметром resolveExtensions, который определяет, какие расширения файлов будут учитываться при разрешении импортов и в каком порядке.
При встрече импорта вида:
import utils from "./utils"
esbuild должен определить, какой именно файл соответствует этому пути. Возможные варианты:
./utils.js./utils.ts./utils.jsx./utils.tsx./utils.jsonОпция resolveExtensions задаёт список расширений, которые будут проверяться при отсутствии явного расширения в импорте.
По умолчанию esbuild использует следующий набор расширений:
resolveExtensions: [".ts", ".tsx", ".js", ".jsx", ".json"]
Алгоритм разрешения работает последовательно:
resolveExtensions.Порядок элементов в массиве критически важен. esbuild не анализирует «тип проекта» или предпочтения пользователя — он строго идёт сверху вниз.
Пример конфигурации:
{
resolveExtensions: [".ts", ".js"]
}
При наличии двух файлов:
utils.ts
utils.js
импорт:
import utils from "./utils"
разрешится в utils.ts, потому что .ts имеет
приоритет.
Если изменить порядок:
resolveExtensions: [".js", ".ts"]
результатом станет utils.js.
В TypeScript-экосистеме порядок расширений часто используется для контроля поведения при смешанных кодовых базах.
resolveExtensions: [".ts", ".tsx", ".js"]
Это позволяет:
Опция resolveExtensions тесно связана с двумя другими механизмами esbuild:
Loader определяет, как интерпретировать конкретные расширения:
loader: {
".ts": "ts",
".js": "js",
".json": "json"
}
resolveExtensions лишь выбирает файл, а loader определяет, как его обработать.
Платформа влияет на допустимые расширения и поведение резолва:
browser — ориентирован на фронтенд, часто включает
.jsxnode — учитывает Node.js-экосистемуНо именно resolveExtensions задаёт приоритет поиска.
Основной сценарий работы resolveExtensions проявляется при импортах без расширений.
import config from "./config"
esbuild пробует:
./config.ts
./config.tsx
./config.js
./config.jsx
./config.json
в зависимости от конфигурации.
Если импорт содержит расширение, resolveExtensions полностью игнорируется:
import data from "./data.json"
В этом случае:
Хотя resolveExtensions кажется простой опцией, её неправильная настройка может влиять на скорость сборки.
Пример неоптимальной конфигурации:
resolveExtensions: [
".jsx",
".tsx",
".ts",
".js",
".mjs",
".cjs",
".json"
]
Здесь поиск может становиться более дорогим в больших проектах, особенно при глубокой файловой структуре.
В монорепозиториях resolveExtensions часто используется для унификации поведения разных пакетов.
Пример:
resolveExtensions: [".ts", ".tsx", ".js", ".jsx"]
Особенности:
При наличии файлов с одинаковыми именами, но разными расширениями, resolveExtensions определяет исход конфликта.
Структура:
service.ts
service.js
service.json
Импорт:
import service from "./service"
Результат зависит от порядка:
.ts → TypeScript версия.js → JavaScript версия.json → конфигурационный объектВ зависимости от типа модулей resolveExtensions участвует в разных сценариях:
.js,
.mjs, .ts.js, .cjsesbuild не различает семантику модулей при resolveExtensions, но порядок влияет на итоговую интерпретацию.
Если ни один вариант расширения не найден, esbuild:
Пример:
Could not resolve "./utils"
Типичная конфигурация для универсального проекта:
require("esbuild").build({
entryPoints: ["src/index.ts"],
bundle: true,
outdir: "dist",
resolveExtensions: [".ts", ".tsx", ".js", ".jsx", ".json"]
})
Для чистого Node.js проекта:
resolveExtensions: [".js", ".mjs", ".cjs", ".json"]
Для фронтенд React-проекта:
resolveExtensions: [".tsx", ".ts", ".jsx", ".js"]
Хотя resolveExtensions отвечает за расширения, он часто используется вместе с:
Плагины могут перехватывать резолв раньше, чем применяется логика расширений, что делает resolveExtensions вторичным в цепочке обработки.
При глубокой структуре каталогов:
src/modules/user/profile/service
resolveExtensions применяется одинаково на каждом уровне резолва, без изменения логики.
Импорт:
import service from "./modules/user/profile/service"
поиск расширений происходит в каждом каталоге независимо.
resolveExtensions: [".ts", ".js"]
resolveExtensions: [".ts", ".tsx", ".js", ".jsx", ".json"]
resolveExtensions: [".js", ".mjs", ".cjs"]
resolveExtensions: [".js"]
При импортах директорий:
import utils from "./utils"
и структуре:
utils/index.ts
utils/index.js
resolveExtensions участвует после проверки index-файлов, влияя на выбор между различными реализациями index.
Опция resolveExtensions формирует линейный список приоритетов расширений, который esbuild использует при разрешении импортов без явного указания файла. Она не изменяет семантику модулей, но определяет точку входа в файловой системе при неоднозначности.