Конфигурация монорепозитория TypeScript

Монорепозиторий — это модель разработки, при которой несколько проектов размещаются в одном репозитории кода.

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


SVG-диаграмма: структура монорепозитория Background Title Monorepo Project Structure Root directory Root directory (root) package.json | tsconfig.json | lerna.json | turbo.json Package directory packages/ directory Package 1 utils Package 2 ui-components Package 3 hooks Package 4 app Bottom section: Tools Management tools: npm workspaces | yarn workspaces | pnpm | lerna | turbo Arrow marker

Зачем нужен монорепозиторий

Когда проект содержит несколько пакетов (например, библиотеки утилит, библиотеки компонентов и приложения), традиционный подход требует поддержки нескольких репозиториев кода.

Монорепозиторий размещает все пакеты в одном репозитории, что упрощает совместное использование кода и унифицирует управление версиями.

Функция ссылок на проекты в TypeScript делает проверку типов и сборку Monorepo-проектов более эффективной.

Концепция:Monorepo (единый репозиторий) размещает несколько связанных проектов в одном репозитории кода, способствуя совместному использованию кода и скоординированной разработке.


Рабочее пространство pnpm

pnpm — современный менеджер пакетов с нативной поддержкой функций рабочего пространства.

Корневой package.json

{
    "name": "my-monorepo",
    "version": "1.0.0",
    "private": true,

    // Включить рабочее пространство pnpm
    "packages": [
        "packages/*"
    ],

    // Зависимости для разработки
    "devDependencies": {
        "typescript": "^5.0.0"
    },

    // Скрипты
    "scripts": {
        "build": "pnpm -r run build",
        "clean": "pnpm -r run clean",
        "type-check": "pnpm -r run type-check"
    }
}

pnpm:Функция Workspace в pnpm может автоматически связывать пакеты в каталоге packages друг с другом.


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

Создайте структуру каталогов для проекта Monorepo.

Структура каталогов

my-monorepo/
├── packages/
│ ├── utils/# Пакет утилит
│ │ ├── src/
│ │ │ └── index.ts
│ │ ├── package.json
│ │ └── tsconfig.json
│   │
│ ├── ui-components/# Пакет UI-компонентов
│ │ ├── src/
│ │ │ ├── Button.tsx
│ │ │ └── index.ts
│ │ ├── package.json
│ │ └── tsconfig.json
│   │
│ └── app/# Приложение
│ ├── src/
│ │ └── index.tsx
│ ├── package.json
│ └── tsconfig.json
│
├── package.json# Корневая конфигурация
├── tsconfig.base.json# Базовая конфигурация
└── pnpm-workspace.yaml# Конфигурация pnpm

packages:Все пакеты размещаются в каталоге packages, каждый со своим package.json и tsconfig.json.


Базовая конфигурация TypeScript

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

tsconfig.base.json

{
    // Параметры компилятора
    "compilerOptions": {
        // Целевая версия
        "target": "ES2020",

        // Система модулей
        "module": "ESNext",

        // Строгий режим
        "strict": true,

        // Пропустить проверку типов библиотек
        "skipLibCheck": true,

        // Включить совместимость ES-модулей
        "esModuleInterop": true,

        // Обеспечить единообразный регистр в именах файлов
        "forceConsistentCasingInFileNames": true,

        // Разрешение модулей
        "moduleResolution": "bundler",

        // Разрешать JSON-модули
        "resolveJsonModule": true,

        // Изолированные модули
        "isolatedModules": true,

        // Не генерировать выходные файлы
        "noEmit": true
    }
}

Наследование:tsconfig.json каждого пакета наследует базовую конфигурацию и переопределяет только те параметры, которые требуют настройки.


Конфигурация пакета утилит

Настройте TypeScript для пакета утилит.

packages/utils/tsconfig.json

{
    // Наследовать базовую конфигурацию
    "extends": "../../tsconfig.base.json",

    // Параметры компилятора
    "compilerOptions": {
        // Каталог вывода
        "outDir": "./dist",

        // Каталог файлов объявлений
        "declarationDir": "./dist/types",

        // Генерировать файлы объявлений
        "declaration": true,

        // Генерировать объявления для входных файлов
        "declarationMap": true,

        // Формат экспорта модуля
        "module": "ESNext",

        // Включить ссылки на проекты
        "composite": true
    },

    // Включаемые файлы
    "include": ["src/**/*"],

    // Исключаемые файлы
    "exclude": ["node_modules", "dist", "**/*.test.ts"]
}

composite:После включения ссылок на проекты TypeScript может инкрементально компилировать этот пакет.


Конфигурация приложения

Настройте TypeScript для основного приложения и укажите ссылки на другие пакеты.

packages/app/tsconfig.json

{
    // Наследовать базовую конфигурацию
    "extends": "../../tsconfig.base.json",

    // Параметры компилятора
    "compilerOptions": {
        // Каталог вывода
        "outDir": "./dist",

        // Конфигурация JSX
        "jsx": "react-jsx",

        // Псевдонимы путей
        "baseUrl": ".",
        "paths": {
            "@my-utils/*": ["../utils/src/*"],
            "@my-ui/*": ["../ui-components/src/*"]
        }
    },

    // Ссылки на проекты
    "references": [
        { "path": "../utils" },
        { "path": "../ui-components" }
    ],

    // Включаемые файлы
    "include": ["src/**/*"],

    // Исключаемые файлы
    "exclude": ["node_modules", "dist"]
}

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


Зависимости между пакетами

Объявите зависимости от пакетов в том же репозитории в package.json.

packages/app/package.json

{
    "name": "@my-org/app",
    "version": "1.0.0",
    "private": true,

    "dependencies": {
        // Ссылки на пакеты в том же репозитории
        "@my-org/utils": "workspace:*",
        "@my-org/ui-components": "workspace:*",

        // Внешние зависимости
        "react": "^18.2.0",
        "react-dom": "^18.2.0"
    },

    "devDependencies": {
        // Зависимости для разработки
        "@types/react": "^18.2.0",
        "typescript": "^5.0.0"
    }
}

workspace:Используйте workspace:* для указания на другие пакеты в том же репозитории, и pnpm автоматически разрешит их.


Скрипты сборки

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

Корневой package.json

{
    "scripts": {
        // Собрать все пакеты
        "build": "pnpm -r run build",

        // Очистить все артефакты сборки
        "clean": "pnpm -r run clean",

        // Проверка типов
        "type-check": "pnpm -r run type-check",

        // Тестирование всех пакетов
        "test": "pnpm -r run test",

        // Инкрементальная сборка
        "build:watch": "pnpm -r --parallel run build:watch",

        // Запуск приложения
        "dev": "pnpm --filter @my-org/app run dev"
    }
}

pnpm -r:Рекурсивно выполнять скрипты с одинаковым именем во всех пакетах.


Примечания

  • Соглашение об именовании пакетов:Используйте формат @org-name/package
  • Независимые версии:Каждый пакет может версионироваться независимо
  • Протокол workspace:Используйте workspace:* для ссылок на пакеты в том же репозитории
  • Порядок сборки:Пакеты, от которых зависят другие, должны быть собраны первыми

Лучшие практики:Монорепозиторий подходит для управления несколькими связанными проектами и может значительно повысить переиспользование кода и эффективность разработки.


Итог

Монорепозиторий — рекомендуемый паттерн для управления современными фронтенд-проектами.

  • pnpm Workspace:Нативная поддержка монорепозитория
  • Ссылки на проекты:Включение инкрементальной компиляции
  • Псевдонимы путей:Удобно ссылаться на пакеты в том же репозитории
  • Единое управление:Совместное использование конфигурации и зависимостей

Рекомендация:Когда проект содержит несколько связанных пакетов, сначала рассмотрите подход Monorepo.

Другие расширения