Монорепо сейчас в моде. Современные проекты используют NX для создания монорепо. Но зачем внедрять такой сложный инструмент в свой технологический стек, если зачастую достаточно чего-то простого?
И Yarn, и NPM включают в свой набор функций управление рабочими пространствами. Таким образом, вы можете управлять несколькими проектами в одном рабочем пространстве. Кроме того, один из инструментов всегда доступен в вашем проекте, так почему бы не использовать его?
Фантастический проект
Вы работаете над фантастическим проектом, который вы случайно назвали fantastic
. Как креативно, не правда ли?
fantastic
— это приложение командной строки, которое покажет, как настроить монорепо TypeScript с помощью рабочих пространств NPM. Проект fantastic
имел огромный успех как приложение CLI, и многие пользователи хотели иметь графический интерфейс для его использования. Поэтому вы решили создать веб-интерфейс. В настоящее время ваш код находится в одном модуле, содержащем основную логику и точку входа CLI.
Поэтому вы решили разделить проект на три отдельных пакета:
Инициализация проекта
Давайте создадим пустой каталог и инициализируем пакет NPM:
mkdir fantastic
cd fantastic
npm init -y
Теперь создадим пакеты:
npm init -y --scope @fantastic -w packages/core
npm init -y --scope @fantastic -w packages/web
npm init -y --scope @fantastic -w packages/cli
Определите зависимости между пакетами:
npm install @fantastic/core -w @fantastic/web
npm install @fantastic/core -w @fantastic/cli
Протестируйте!
Теперь, когда у нас есть основа, давайте добавим немного кода для тестирования:
packages/core/index.js
console.log("Hello from Core!");
packages/web/index.js
require("@fantastic/core");
console.log("Hello from Web!");
packages/cli/index.js
require("@fantastic/core");
console.log("Hello from CLI!");
Запуск CLI выводит следующее:
node packages/cli/index.js
Hello from Core!
Hello from CLI!
Это подтверждает, что установка работает нормально.
А вот и TypeScript
Пора перевести этот проект с JavaScript на TypeScript!
Прежде всего, установите typescript
в качестве dev-зависимости в проект рабочей области:
npm install -D typescript
Каждый пакет требует свой собственный файл tsconfig.json
. Поскольку проект fantastic
использует одну и ту же конфигурацию для всех трех пакетов, создайте общий файл tsconfig.base.json
в корневом каталоге.
tsconfig.base.json
{
"compilerOptions": {
"incremental": true,
"target": "es2020",
"module": "commonjs",
"declaration": true,
"sourceMap": true,
"strict": true,
"moduleResolution": "node",
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"composite": true
}
}
Это обычный файл tsconfig.json
, за исключением одной опции компилятора: composite
. Эта опция позволяет TypeScript быстро определить, был ли проект уже собран.
Теперь у вас есть общий файл конфигурации TS, но вы его еще не используете. Создайте файл tsconfig.json
в корневом каталоге каждого пакета:
packages/core/tsconfig.json
{
"extends": "../../tsconfig.base.json"
}
Пакеты cli
и web
немного отличаются. Вам нужно перечислить все ваши зависимости в свойстве references
:
packages/cli/tsconfig.json и packages/web/tsconfig.json
{
"extends": "../../tsconfig.base.json",
"references": [{ "path": "../core" }]
}
Теперь, когда независимые пакеты настроены, создайте tsconfig.json
в корневом каталоге:
tsconfig.json
{
"files": [],
"references": [
{ "path": "packages/core" },
{ "path": "packages/cli" },
{ "path": "packages/web" }
]
}
Пустой массив files
указывает TypeScript игнорировать все файлы, кроме тех, что находятся в ссылках.
Переименуйте все файлы .js
в .ts
и замените require
на import
:
require("@fantastic/core");
на
import "@fantastic/core";
Вы готовы к компиляции:
npx tsc --build
Флаг --build
необходим, поскольку проект содержит несколько проектов.
Теперь, когда вы закончили все эти изменения, протестируйте ваше приложение еще раз:
$ node packages/cli/index.js
Hello from Core!
Hello from CLI!
$ node packages/web/index.js
Hello from Core!
Hello from Web!
Разделение исходного кода и вывода сборки
Прежде всего, удалите все выходные данные сборки из предыдущего шага. Следующая команда удалит все файлы .js
, .js.map
, .d.ts
и .tsbuildinfo
в каталоге packages
.
rm packages/**/{*.js,*.js.map,*.d.ts,*.tsbuildinfo}
Размещение исходного кода и вывода сборки в разных каталогах является хорошей практикой. Поэтому переместите исходный код каждого пакета в каталог src
, а каталог вывода сборки измените на dist
.
Расширьте ваши файлы packages/*/tsconfig.json
следующим фрагментом:
"compilerOptions": {
"rootDir": "src",
"outDir": "dist"
},
В качестве примера, вот как теперь выглядит packages/web/tsconfig.json
:
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"rootDir": "src",
"outDir": "dist"
},
"references": [{ "path": "../core" }]
}
Это сообщает TypeScript, что ваши файлы исходного кода находятся в каталоге src
, а вывод сборки должен находиться в каталоге dist
. Эти данные относятся к вашему файлу tsconfig.json
.
Переместите файлы index.ts
в соответствующий каталог src
. На данном этапе у вас должно быть следующее дерево каталогов:
├── package-lock.json
├── package.json
├── packages
│ ├── cli
│ │ ├── package.json
│ │ ├── src
│ │ │ └── index.ts
│ │ └── tsconfig.json
│ ├── core
│ │ ├── package.json
│ │ ├── src
│ │ │ └── index.ts
│ │ └── tsconfig.json
│ └── web
│ ├── package.json
│ ├── src
│ │ └── index.ts
│ └── tsconfig.json
├── tsconfig.base.json
└── tsconfig.json
Перед сборкой проекта настройте свойство main
в package.json
каждого пакета. Измените index.js
на dist/index.js
, поскольку именно там он сейчас находится.
Теперь соберите свой проект и запустите CLI-приложение:
npx tsc --build
node packages/cli/dist/index.js
Вы должны увидеть обычный результат:
Hello from Core!
Hello from CLI!
Вы сделали это! Отличная работа!
Теперь, когда вы заложили основу для своего проекта, продолжайте и создайте что-то необычное!
Исходный код проекта доступен на GitHub. Репозиторий содержит несколько небольших изменений. Не стесняйтесь, изучайте!
Если вы хотите узнать больше о рабочих пространствах NPM и TypeScript, посмотрите эти ссылки:
- Документация по NPM Workspaces
- Документация по TypeScript Project References
PS. NX — это потрясающий инструмент! Но иногда лучше использовать инструменты, которые уже есть в вашем распоряжении. Пожалуйста, не торопитесь принимать решение об использовании NX или рабочих пространств NPM / Yarn.