Поле module.type и его параметры

## module.type: назначение и роль в системе модульной трансформации SWC Поле `module.type` в конфигурации SWC определяет стратегию преобразования модулей JavaScript/TypeScript при компиляции. Оно управляет тем, в какой модульный формат будет трансформирован исходный код: останется ли он в формате ES Modules или будет преобразован в CommonJS, AMD, UMD либо другие поддерживаемые системы модулей. На уровне компилятора SWC модульная система — один из ключевых этапов трансформации, влияющий на совместимость кода с окружением выполнения (Node.js, браузер, bundler-инструменты). --- ## Расположение в конфигурации SWC Параметр задаётся внутри секции `module` файла конфигурации `.swcrc`: ```json { "module": { "type": "es6" } } ``` Структура секции обычно включает: * `type` — тип выходной модульной системы * дополнительные параметры (в зависимости от выбранного типа и версии SWC) --- ## Основные значения module.type ### es6 (ES Modules) Значение `es6` сохраняет или генерирует код в формате ES Modules (`import` / `export`). #### Поведение: * `import` остаётся без преобразования * `export` сохраняется * подходит для современных bundler’ов (Vite, Rollup, esbuild) * используется в браузерных приложениях с поддержкой ESM #### Пример трансформации: Исходный код: ```js export const sum = (a, b) => a + b; ``` Результат: ```js export const sum = (a, b) => a + b; ``` --- ### commonjs Наиболее часто используемый вариант для Node.js-окружения. #### Поведение: * `import` преобразуется в `require` * `export` преобразуется в `module.exports` или `exports.*` * добавляется runtime-обвязка для совместимости #### Пример: Исходный код: ```js export function sum(a, b) { return a + b; } ``` Результат: ```js "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.sum = sum; function sum(a, b) { return a + b; } ``` --- ### amd Asynchronous Module Definition — формат, используемый в RequireJS и подобных системах. #### Поведение: * оборачивает модуль в `define([...], function(...) {})` * зависимости явно перечисляются * используется редко в современных проектах #### Пример: ```js define(["exports"], function (exports) { "use strict"; exports.sum = sum; function sum(a, b) { return a + b; } }); ``` --- ### umd Universal Module Definition — универсальный формат, поддерживающий сразу несколько окружений: * AMD * CommonJS * глобальный контекст браузера #### Поведение: * генерируется IIFE-обёртка * определяется окружение выполнения * выбирается подходящий механизм экспорта #### Пример структуры: ```js (function (global, factory) { if (typeof module === "object" && typeof module.exports === "object") { module.exports = factory(); } else if (typeof define === "function" && define.amd) { define([], factory); } else { global.MyLib = factory(); } })(this, function () { return {}; }); ``` --- ### systemjs Формат для SystemJS loader. #### Поведение: * используется `System.register` * зависимости и экспорты описываются декларативно * применяется в специфичных сборках legacy-проектов --- ## Поведение трансформации import/export Выбор `module.type` напрямую влияет на то, как SWC обрабатывает синтаксис модулей: ### import * `es6` → без изменений * `commonjs` → `require()` * `amd` → аргументы `define([...])` * `umd` → комбинированная стратегия ### export * именованные экспорты → `exports.name = ...` (commonjs) * default export → `module.exports = ...` * ESM → остаётся неизменным --- ## Взаимодействие с другими параметрами module ### module.noInterop Контролирует поведение interop между CommonJS и ES Modules. При `type: "commonjs"` часто используется совместно: ```json { "module": { "type": "commonjs", "noInterop": false } } ``` #### Влияние: * управляет генерацией `__esModule` * влияет на доступ к default export --- ### module.strict Определяет режим генерации строгой модульной обёртки. #### Влияние: * добавляет `"use strict"` * предотвращает небезопасные конструкции * улучшает совместимость с современными стандартами JS --- ### module.lazy Используется для оптимизации загрузки модулей. #### Поведение: * откладывает инициализацию модулей * может уменьшать стартовую стоимость выполнения * особенно полезно в bundler-цепочках --- ## Влияние module.type на tree-shaking Хотя SWC сам по себе не выполняет полноценный tree-shaking, выбор `module.type` влияет на возможности последующих инструментов: ### es6 * сохраняет статическую структуру модулей * оптимально для tree-shaking в bundler’ах ### commonjs * динамическая система `require` * усложняет статический анализ * снижает эффективность удаления неиспользуемого кода --- ## Совместимость с Node.js ### ESM-режим Node.js При использовании: ```json { "type": "module" } ``` Оптимально: ```json { "module": { "type": "es6" } } ``` ### CommonJS-режим Node.js Без ESM-флагов: ```json { "module": { "type": "commonjs" } } ``` --- ## Частые комбинации конфигураций ### Библиотека для npm (универсальная) ```json { "module": { "type": "commonjs" } } ``` или двойная сборка: * ESM сборка (`es6`) * CJS сборка (`commonjs`) --- ### Фронтенд-приложение ```json { "module": { "type": "es6" } } ``` --- ### Legacy-браузеры и RequireJS ```json { "module": { "type": "amd" } } ``` --- ## Влияние на генерацию кода и runtime-обвязки Выбор `module.type` определяет необходимость дополнительных конструкций: * helper-функции для interop (`__esModule`) * обёртки модулей (IIFE, define, System.register) * преобразование синтаксиса динамических импортов * поведение top-level scope --- ## Особенности обработки default export ### ES6 ```js export default function () {} ``` ### CommonJS ```js module.exports = function () {}; ``` При этом SWC может добавлять вспомогательные поля: ```js exports.default = ... ``` в зависимости от режима interop. --- ## Ограничения и нюансы * `module.type` не управляет bundling — только трансформацией * динамические `require()` не всегда корректно анализируются * tree-shaking зависит от внешнего инструмента * поведение может отличаться между версиями SWC при обновлениях пресетов * некоторые комбинации с TypeScript `isolatedModules` требуют дополнительной настройки --- ## Поведение при отсутствии module.type Если `module.type` не указан: * SWC может сохранять исходный формат (в зависимости от входных файлов) * либо применять дефолтный режим окружения * поведение может отличаться между конфигурациями CLI и интеграциями (Next.js, bundlers) ---