Создание приложения Node.js с TypeScript
Рассмотрим, как настроить TypeScript для сборки приложения Node. Для этого будем использовать:
- pnpm для управления пакетами.
- Node.js для выполнения нашего кода.
- TypeScript для обеспечения безопасности типов и сборки кода.
- ES Modules в качестве модульной системы.
Если вас интересует настройка с ESBuild, ознакомьтесь с моим руководством по ESBuild Build a Node App With TypeScript & ESBuild.
Понимание инструментов
Для подготовки приложения Node к продакшену понадобится несколько вещей:
- Скрипт
dev
для локального запуска кода и проверки ошибок TypeScript. - Скрипт
build
для сборки кода для продакшена и проверки на ошибки TypeScript. - Скрипт
start
для запуска собранного кода в продакшне.
Добавление файлов конфигурации
package.json
Начнём с пустого репозитория и инициализируем его с помощью npm init -y
. Это создаст файл package.json
.
"type": "module" в package.json
Затем добавьте "type": "module"
в файл package.json
.
{
// ...другие свойства
"type": "module"
// ...другие свойства
}
Это указывает Node.js использовать ES Modules вместо модулей CommonJS.
Зависимости
Если у вас не установлен pnpm, установите его.
Далее установим зависимости:
pnpm add -D typescript @types/node
Это добавит typescript
и @types/node
в package.json
.
Также будет создан файл pnpm-lock.yaml
. Этот файл отслеживает точные версии зависимостей, чтобы сделать установку более быстрой и предсказуемой.
Конфигурация TypeScript
Добавьте в корень проекта файл tsconfig.json со следующей конфигурацией:
{
"compilerOptions": {
/* Базовые опции: */
"esModuleInterop": true,
"skipLibCheck": true,
"target": "es2022",
"allowJs": true,
"resolveJsonModule": true,
"moduleDetection": "force",
"isolatedModules": true,
/* Строгость */
"strict": true,
"noUncheckedIndexedAccess": true,
/* Если транспилируете с TypeScript: */
"moduleResolution": "NodeNext",
"module": "NodeNext",
"outDir": "dist",
"sourceMap": true,
/* Если код не запускается в DOM DOM: */
"lib": ["es2022"]
}
}
Эта конфигурация взята из Шпаргалка по TSConfig.
Одна из важных опций, на которую следует обратить внимание, — moduleResolution
: она гарантирует, что TypeScript использует то же разрешение модулей, что и Node.js. Если вы не привыкли к этому, это может вызвать удивление — ведь вам придётся добавлять расширения .js
к своим импортам. Но его использование значительно улучшает время запуска приложения Node, что очень важно для лямбд.
.gitignore
Добавьте файл .gitignore
со следующим содержимым:
node_modules
dist
node_modules
содержит все файлы, которые мы получаем из npm. dist
содержит все файлы, которые мы получаем из tsc.
Каталог src
Создайте каталог src
в корне проекта.
В каталоге src
создайте файл index.ts
со следующим содержимым:
console.log("Hello, world!");
Добавление скриптов
Скрипт build
Добавьте скрипт build
в package.json
:
{
// ...другие свойства
"scripts": {
"build": "tsc"
}
// ...другие свойства
}
Этот скрипт превращает TypeScript код в JavaScript с помощью tsc, а также проверяет наличие ошибок.
Попробуйте заменить console.log
на console.lg
в src/index.ts
. Затем запустите pnpm build
— он сообщит о некорректном коде. Он также создаст .js
-файл в каталоге dist
.
Скрипт start
Добавьте скрипт start
в package.json
:
{
// ...другие свойства
"scripts": {
"start": "node dist/index.js"
}
// ...другие свойства
}
Этот скрипт запускает собранный код с помощью Node.js.
Попробуйте запустить pnpm build && pnpm start
. Это позволит собрать и запустить наш код.
В консоль должно вывестись сообщение Hello, world!
.
Скрипт dev
Скрипт dev
будет самым сложным. Запуская его, мы будем делать несколько действий одновременно:
tsc --watch
для сборки TypeScript-кода и проверки на наличие ошибок.node --watch
для перезапуска приложения при его изменении.
Для каждого из них мы добавим отдельный npm-скрипт, а затем запустим их одновременно с помощью pnpm.
tsc --watch
Добавьте скрипт dev:tsc
в package.json
:
{
// ...другие свойства
"scripts": {
"dev:tsc": "tsc --watch --preserveWatchOutput"
}
// ...другие свойства
}
Флаг --watch
указывает TypeScript на необходимость перезапуска при изменении кода.
Флаг --preserveWatchOutput
указывает TypeScript не очищать вывод консоли при перезапуске.
node --watch
Добавьте скрипт dev:node
в package.json
:
{
// ...другие свойства
"scripts": {
"dev:node": "node --enable-source-maps --watch dist/index.js"
}
// ...другие свойства
}
--enable-source-maps
означает, что трассировка стека ошибок будет указывать на файлы TypeScript, а не на JavaScript. Это возможно благодаря параметру "sourceMap": true
в tsconfig.json
.
run "/dev:/"
Добавьте скрипт dev
в файл package.json
:
{
// ...другие параметры
"scripts": {
"dev": "pnpm run \"/dev:/\""
}
// ...другие параметры
}
Этот скрипт запускает параллельно все скрипты, начинающиеся с dev:
.
Попробуйте запустить pnpm dev
. Вы увидите, что проверка типа, сборка и выполнение происходят одновременно.
Заключение
Поздравляю! Теперь у вас есть полностью функциональная установка TypeScript и Node.
Эта настройка может обрабатывать любой Node.js код, который вы в неё отправите, от серверов express до Lambda.
Если хотите посмотреть рабочий пример, загляните в этот репозиторий.
Если у есть вопросы, пишите на мой Discord сервер, и я расскажу как это исправить.