Поле 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` изменяет архитектурные характеристики кода:
* уменьшается количество относительных переходов `../. ./. ./`
* повышается стабильность импортов при рефакторинге
* появляется логическая сегментация доменов через алиасы
* снижается связность модулей с физической иерархией файлов
Фактически система превращает файловую структуру из единственного источника истины в одну из возможных проекций логической модели приложения.