Поле jsc.paths и baseUrl

### Роль `baseUrl` в разрешении модулей В конфигурации компилятора SWC параметр `baseUrl` определяет базовую директорию, относительно которой вычисляются неквалифицированные пути импортов. Это поведение соответствует логике TypeScript и используется при трансляции модулей, где требуется унификация структуры импортов без обязательного использования относительных путей. При отсутствии явных алиасов все импорты, не начинающиеся с `./`, `../` или абсолютных URL, интерпретируются относительно значения `baseUrl`. Это позволяет формировать более плоскую и предсказуемую структуру импортов в больших проектах. Типичная конфигурация: ```json { "jsc": { "baseUrl": "./src" } } ``` В таком случае импорт: ```javascript import Button from "components/Button"; ``` будет разрешён как: ``` ./src/components/Button ``` Ключевой особенностью является то, что `baseUrl` не создаёт псевдонимы сам по себе, а лишь задаёт корневую точку разрешения. Любые дополнительные правила требуют явного описания через `paths`. --- ### Поле `jsc.paths` и система алиасов модулей `jsc.paths` представляет собой механизм сопоставления логических путей импорта с физическими расположениями файлов. По своей семантике он повторяет `compilerOptions.paths` из TypeScript, но применяется на этапе трансформации SWC. Основная задача `paths` заключается в создании абстракций над структурой каталогов, позволяя заменять длинные относительные цепочки импортов на стабильные логические идентификаторы. Базовая структура: ```json { "jsc": { "baseUrl": "./src", "paths": { "@components/*": ["components/*"], "@utils/*": ["utils/*"] } } } ``` --- ### Механизм разрешения путей При обработке импортов SWC использует последовательность шагов: 1. Проверка, является ли путь относительным (`./`, `../`) или абсолютным URL 2. Если путь не относительный, применяется `paths`-маппинг 3. При совпадении шаблона выполняется подстановка 4. Результат соединяется с `baseUrl` (если он задан) Пример: ```javascript import formatDate from "@utils/date/format"; ``` При конфигурации: ```json { "jsc": { "baseUrl": "./src", "paths": { "@utils/*": ["utils/*"] } } } ``` результирующее разрешение: ``` ./src/utils/date/format ``` --- ### Шаблоны и wildcard-матчинг `jsc.paths` поддерживает использование `*` как универсального символа подстановки. Он обозначает сегмент пути, который должен быть сохранён при трансформации. Формат: ``` "@alias/*": ["target/*"] ``` Правило замены: * часть пути, совпавшая с `*`, переносится в целевой шаблон * количество wildcard-сегментов должно быть согласованным между ключом и значением Пример: ```json { "jsc": { "baseUrl": "./src", "paths": { "@store/*": ["state/store/*"] } } } ``` Импорт: ```javascript import reducer from "@store/user/profile/reducer"; ``` Результат: ``` ./src/state/store/user/profile/reducer ``` --- ### Несколько вариантов сопоставления `paths` допускает массив значений для одного ключа. Это позволяет задавать приоритетные и резервные маршруты поиска модулей. ```json { "jsc": { "baseUrl": "./src", "paths": { "@lib/*": [ "lib/internal/*", "lib/external/*" ] } } } ``` Алгоритм обработки: * проверяется первый путь * при отсутствии файла проверяется следующий * выбирается первый существующий вариант Такой механизм полезен при миграции библиотек или разделении кода на версии API. --- ### Взаимодействие `baseUrl` и `paths` `baseUrl` и `paths` работают совместно, но выполняют разные роли: * `baseUrl` задаёт корневую точку файловой системы проекта * `paths` определяет логические псевдонимы внутри этой структуры Сценарий без `baseUrl`: ```json { "jsc": { "paths": { "@components/*": ["src/components/*"] } } } ``` Импорт: ```javascript import Header from "@components/Header"; ``` Результат: ``` src/components/Header ``` Сценарий с `baseUrl`: ```json { "jsc": { "baseUrl": "./src", "paths": { "@components/*": ["components/*"] } } } ``` Результат становится короче и логически чище: ``` ./src/components/Header ``` --- ### Ограничения системы `paths` Несмотря на гибкость, система имеет ряд структурных ограничений: * отсутствие поддержки регулярных выражений в ключах * невозможность динамического вычисления путей * строгое соответствие шаблону `*` * отсутствие runtime-резолвинга (вся логика применяется на этапе трансформации) Это означает, что SWC не изменяет поведение Node.js или браузера напрямую. Результат трансформации должен быть совместим с окружением исполнения, где resolution модулей остаётся стандартным. --- ### Особенности поведения при сборке При использовании SWC как транспилятора в связке с bundler-ом (например, Webpack, Vite, Rollup) важно учитывать: * `paths` применяется до этапа бандлинга * итоговые пути могут дополнительно трансформироваться резолверами бандлера * несоответствие `baseUrl` и настроек бандлера приводит к ошибкам поиска модулей Типичная проблема: ```text Module not found: Can't resolve '@components/Button' ``` Причина часто заключается в том, что SWC преобразовал импорт, но бандлер не имеет аналогичной конфигурации алиасов. --- ### Применение в монорепозиториях В монорепозиториях `jsc.paths` используется для унификации доступа к пакетам внутри общей структуры: ```json { "jsc": { "baseUrl": "./", "paths": { "@app/*": ["packages/app/src/*"], "@shared/*": ["packages/shared/src/*"], "@ui/*": ["packages/ui/src/*"] } } } ``` Такой подход позволяет: * исключить глубокие относительные пути * стандартизировать импорт между пакетами * уменьшить связанность модулей с физической структурой репозитория --- ### Поведение при конфликтующих правилах При пересечении шаблонов применяется первое совпадение по порядку объявления. Это создаёт важное правило при проектировании конфигурации: более специфичные алиасы должны располагаться выше. Пример конфликтной ситуации: ```json { "jsc": { "baseUrl": "./src", "paths": { "@*": ["common/*"], "@utils/*": ["utils/*"] } } } ``` Импорт: ```javascript import x from "@utils/math"; ``` В зависимости от реализации разрешения, более общий шаблон `@*` может перехватить импорт, что приведёт к некорректному пути. Поэтому приоритет всегда должен отдаваться узким совпадениям. --- ### Влияние на структуру проекта Использование `baseUrl` и `paths` изменяет архитектурные характеристики кода: * уменьшается количество относительных переходов `../. ./. ./` * повышается стабильность импортов при рефакторинге * появляется логическая сегментация доменов через алиасы * снижается связность модулей с физической иерархией файлов Фактически система превращает файловую структуру из единственного источника истины в одну из возможных проекций логической модели приложения.