Создание приложения 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
distnode_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 сервер, и я расскажу как это исправить.