@rollup/plugin-typescript

@rollup/plugin-typescript — официальный плагин экосистемы Rollup, предназначенный для интеграции компилятора TypeScript в процесс сборки. Он позволяет обрабатывать файлы .ts, .tsx, а также использовать настройки из tsconfig.json, объединяя возможности TypeScript и Rollup в единую систему.

Плагин выполняет несколько важных задач:

  • компиляцию TypeScript в JavaScript;
  • обработку JSX/TSX;
  • чтение конфигурации TypeScript;
  • передачу результатов в Rollup для дальнейшего бандлинга;
  • генерацию деклараций типов при соответствующей настройке.

Без данного плагина Rollup не способен самостоятельно анализировать и компилировать исходные файлы TypeScript.


Установка

Для работы требуется установить Rollup, TypeScript и сам плагин:

npm install --save-dev rollup typescript @rollup/plugin-typescript

После установки появляется возможность импортировать плагин в конфигурацию Rollup.


Базовая настройка

Структура проекта:

project/
├── src/
│   └── index.ts
├── dist/
├── rollup.config.js
├── package.json
└── tsconfig.json

Конфигурация Rollup:

import typescript from '@rollup/plugin-typescript';

export default {
    input: 'src/index.ts',

    output: {
        file: 'dist/bundle.js',
        format: 'esm'
    },

    plugins: [
        typescript()
    ]
};

Файл TypeScript:

function greet(name: string): string {
    return `Hello ${name}`;
}

console.log(greet('John'));

После сборки:

npx rollup -c

TypeScript будет преобразован в JavaScript и передан Rollup для создания итогового бандла.


Использование tsconfig.json

Одним из главных преимуществ плагина является автоматическая интеграция с конфигурацией TypeScript.

Пример файла:

{
    "compilerOptions": {
        "target": "ES2022",
        "module": "ESNext",
        "strict": true,
        "sourceMap": true
    }
}

Конфигурация Rollup может остаться минимальной:

import typescript from '@rollup/plugin-typescript';

export default {
    input: 'src/index.ts',
    output: {
        file: 'dist/app.js',
        format: 'esm'
    },
    plugins: [
        typescript()
    ]
};

Плагин самостоятельно обнаружит и загрузит tsconfig.json.


Указание собственного tsconfig

Иногда проект содержит несколько конфигураций TypeScript.

Например:

configs/
├── tsconfig.build.json
└── tsconfig.test.json

Тогда нужный файл можно указать явно:

typescript({
    tsconfig: './configs/tsconfig.build.json'
})

Подобный подход часто применяется при разделении производственной и тестовой сборок.


Передача compilerOptions

Настройки компилятора могут быть переопределены непосредственно через плагин.

Пример:

typescript({
    compilerOptions: {
        target: 'ES2020',
        sourceMap: false
    }
})

Параметры будут иметь более высокий приоритет по сравнению с настройками внутри tsconfig.json.

Это удобно для изменения поведения сборки без создания дополнительных конфигурационных файлов.


Настройка target

Параметр target определяет версию JavaScript, в которую будет компилироваться код.

Пример:

typescript({
    compilerOptions: {
        target: 'ES5'
    }
})

Исходный код:

const sum = (a: number, b: number) => a + b;

Результат:

var sum = function (a, b) {
    return a + b;
};

Более современные значения:

{
    "target": "ES2017"
}
{
    "target": "ES2020"
}
{
    "target": "ES2022"
}

Чем новее целевая платформа, тем меньше преобразований выполняет компилятор.


Работа с TSX

Плагин поддерживает React и другие библиотеки, использующие TSX.

Конфигурация TypeScript:

{
    "compilerOptions": {
        "jsx": "react-jsx"
    }
}

Компонент:

export function Button() {
    return <button>Click</button>;
}

Конфигурация Rollup:

import typescript from '@rollup/plugin-typescript';

export default {
    input: 'src/main.tsx',
    plugins: [
        typescript()
    ]
};

TSX-файлы будут корректно обработаны и переданы в следующую цепочку плагинов.


Поддержка React

Типичная конфигурация React-проекта:

import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import typescript from '@rollup/plugin-typescript';

export default {
    input: 'src/index.tsx',

    output: {
        file: 'dist/app.js',
        format: 'esm'
    },

    plugins: [
        resolve(),
        commonjs(),
        typescript()
    ]
};

Порядок плагинов имеет значение.

Чаще всего используется следующая схема:

plugins: [
    resolve(),
    commonjs(),
    typescript()
]

Либо:

plugins: [
    typescript(),
    resolve(),
    commonjs()
]

Выбор зависит от архитектуры проекта и используемых зависимостей.


Генерация source maps

Source map позволяет связать итоговый JavaScript с исходными TypeScript-файлами.

В tsconfig.json:

{
    "compilerOptions": {
        "sourceMap": true
    }
}

В Rollup:

export default {
    output: {
        file: 'dist/app.js',
        format: 'esm',
        sourcemap: true
    }
};

Важно включать source map как в TypeScript, так и в Rollup.

Только в этом случае получится полноценная цепочка отображения исходников.


Генерация деклараций типов

Для публикации библиотек часто требуются файлы .d.ts.

Настройка:

{
    "compilerOptions": {
        "declaration": true,
        "declarationDir": "dist/types"
    }
}

Исходный файл:

export function add(
    a: number,
    b: number
): number {
    return a + b;
}

После сборки:

dist/
└── types/
    └── index.d.ts

Содержимое:

export declare function add(
    a: number,
    b: number
): number;

emitDeclarationOnly

Иногда необходимо генерировать только типы.

Конфигурация:

{
    "compilerOptions": {
        "declaration": true,
        "emitDeclarationOnly": true
    }
}

В таком режиме JavaScript-файлы создаваться не будут.

Подход применяется в сложных пайплайнах, где код компилируется другим инструментом, а TypeScript отвечает исключительно за типизацию.


Исключение файлов

Настройка через TypeScript:

{
    "exclude": [
        "tests",
        "stories",
        "**/*.spec.ts"
    ]
}

Также возможно управление через параметры плагина:

typescript({
    exclude: [
        'tests/**',
        '**/*.spec.ts'
    ]
})

Это уменьшает объём обрабатываемого кода и ускоряет сборку.


Ограничение обрабатываемых файлов

Параметр include позволяет указать только необходимые файлы.

Пример:

typescript({
    include: [
        'src/**/*.ts',
        'src/**/*.tsx'
    ]
})

Плагин будет игнорировать всё остальное содержимое проекта.


Работа с путями aliases

TypeScript поддерживает пути через paths.

Пример:

{
    "compilerOptions": {
        "baseUrl": ".",
        "paths": {
            "@core/*": ["src/core/*"],
            "@utils/*": ["src/utils/*"]
        }
    }
}

Использование:

import { Logger } from '@core/logger';

Однако сам Rollup не понимает такие алиасы автоматически.

Часто дополнительно используется плагин алиасов:

import alias from '@rollup/plugin-alias';

plugins: [
    alias({
        entries: [
            {
                find: '@core',
                replacement: './src/core'
            }
        ]
    }),
    typescript()
]

Необходимо синхронизировать настройки TypeScript и Rollup.


Incremental Compilation

TypeScript поддерживает инкрементальную компиляцию.

Настройка:

{
    "compilerOptions": {
        "incremental": true
    }
}

После первой сборки появляется файл:

tsconfig.tsbuildinfo

Он содержит информацию о предыдущей компиляции и позволяет существенно ускорять повторные сборки.


Работа с strict режимом

Строгая типизация является одной из наиболее востребованных возможностей TypeScript.

Настройка:

{
    "compilerOptions": {
        "strict": true
    }
}

Пример ошибки:

let user: string = null;

Компилятор сообщит о нарушении правил типизации ещё до формирования итогового бандла.


noEmitOnError

Параметр предотвращает выпуск файлов при наличии ошибок.

{
    "compilerOptions": {
        "noEmitOnError": true
    }
}

Если код содержит ошибки:

const value: number = 'test';

Сборка завершится неудачей и файлы не будут созданы.

Такой режим особенно полезен для CI/CD-конвейеров.


Использование вместе с Babel

В крупных проектах часто применяется комбинация TypeScript и Babel.

Схема работы:

TypeScript
      ↓
Babel
      ↓
Rollup Output

Конфигурация:

import babel from '@rollup/plugin-babel';
import typescript from '@rollup/plugin-typescript';

export default {
    input: 'src/index.ts',

    output: {
        file: 'dist/index.js',
        format: 'esm'
    },

    plugins: [
        typescript(),

        babel({
            babelHelpers: 'bundled',
            extensions: [
                '.js',
                '.ts'
            ]
        })
    ]
};

В подобной архитектуре TypeScript обеспечивает типизацию, а Babel выполняет дополнительные преобразования кода.


Использование в библиотеках

Типичная конфигурация библиотеки:

import typescript from '@rollup/plugin-typescript';

export default {
    input: 'src/index.ts',

    output: [
        {
            file: 'dist/index.esm.js',
            format: 'esm'
        },
        {
            file: 'dist/index.cjs.js',
            format: 'cjs'
        }
    ],

    plugins: [
        typescript()
    ],

    external: [
        'react',
        'react-dom'
    ]
};

Исходный код компилируется один раз, после чего Rollup создаёт несколько вариантов выходных файлов.


Использование в монорепозиториях

В монорепозиториях часто встречается структура:

packages/
├── core
├── ui
├── api
└── shared

Каждый пакет может иметь собственный файл:

packages/ui/tsconfig.json

Конфигурация:

typescript({
    tsconfig: './packages/ui/tsconfig.json'
})

Такой подход обеспечивает независимую настройку каждого пакета.


Диагностика ошибок TypeScript

При возникновении ошибок плагин выводит сообщения компилятора непосредственно в консоль Rollup.

Пример:

const id: number = 'abc';

Ошибка:

Type 'string' is not assignable to type 'number'.

Сообщения включают:

  • имя файла;
  • номер строки;
  • номер столбца;
  • описание ошибки;
  • код диагностического сообщения.

Это делает процесс поиска проблем значительно проще.


Ограничения плагина

Несмотря на широкие возможности, существуют некоторые особенности:

  • плагин не заменяет полноценный компилятор TypeScript;
  • разрешение алиасов требует дополнительной настройки;
  • сложные сценарии генерации типов иногда требуют специализированных инструментов;
  • для некоторых крупных проектов может потребоваться комбинация с Babel или SWC;
  • производительность зависит от настроек TypeScript и количества файлов.

Понимание этих ограничений позволяет проектировать сборочный процесс более предсказуемо и эффективно.