03.04.2024

Создаем приложение на Node.JS, Express и Typescript

Пошаговая инструкция создания приложения на Node.JS, которое использует typescript и express. Пригодится для Backend'а нового приложения.

Создание файла package.json

Создадим директорию с проектом, встанем в нее и командой создадим файл package.json:

mkdir app
cd app
npm init --yes

Установка Typescript

npm install --save-dev typescript @types/node
npm install reflect-metadata

Создаем файл конфигурации /tsconfig.json:

{
  "compilerOptions": {
    "target": "es6",
    "module": "commonjs",
    "lib": ["es6"],
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "outDir": "./dist",
    "baseUrl": "./",
    "rootDir": "./src",
    "sourceMap": false,
    "allowJs": true,
    "strict": true,
    "noImplicitAny": true,
    "resolveJsonModule": true,
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
  },
  "include": [
    "src/**/*.ts"
  ],
  "exclude": [
    "node_modules"
  ]
}

Расшифровка конфигурации:

allowSyntheticDefaultImports - позволяет менять схему импорта.
Если true, то

import express from 'express'

Если false, то

import * as express from 'express'

esModuleInterop - устранение проблем с транслитерацией кода. За счёт добавления болерплейта в выходной код, позволяет импортировать CommonJS пакеты как ES6. Также если она в значение true, то автоматически включается allowSyntheticDefaultImports

Создание сервера Express с минимальной конфигурацией

После инициализации файла package.json, установим пакеты для express'а:

npm install dotenv express cors
npm install --save-dev @types/express @types/cors

Далее создадим файл src/index.ts:

import express, { Express, Request, Response } from 'express'
import dotenv from 'dotenv'
dotenv.config()
const app: Express = express()
const port = process.env.PORT
app.get('/', (req: Request, res: Response) => {
   res.send('Express + Typescript Server')
})
app.listen(port, () => {
   console.log(`⚡️[server]: Server is running at http://localhost:${port}`);
})

Настройка сборки в package.json

Установка пакетов:

npm install --save-dev rimraf concurrently nodemon ts-node

Добавляем файл /nodemon.json:

{
 "watch": ["src"],
 "ext": ".ts,.js",
 "ignore": [],
 "exec": "npx ts-node ./src/index.ts"
}

Изменяем /package.json:

 ...
 
 "main": "dist/index.js",
 "scripts": {
   "start": "npm run build && node ./dist/index.js",
   "build": "rimraf ./dist && npx tsc",
   "dev": "nodemon"
 },
 
 ...  

Добавление типизации для .env и файла с конфигом 

Установка пакетов:

npm install if-env --save

Изменим /package.json

 "scripts": {
   "start": "if-env ENV=production ?? npm run start:prod || npm run start:dev",
   "start:dev": "nodemon",
   "start:prod": "npm run build && node ./dist/index.js",
   "build": "rimraf ./dist && npx tsc"
 },

Добавляем файл /.env:

PORT=9000
ENV=development

Создаем файл ./src/types/environment.d.ts:

export {}
declare global {
   namespace NodeJS {
       interface ProcessEnv {
           ENV: 'development' | 'production';
           PORT: string;
       }
   }
}

Добавляем в настройки ./tsconfig.json:

"typeRoots": ["./node_modules/@types", "./src/types"]

Создаем файл ./src/config/index.ts

import path from "path"
import dotenv from "dotenv"
dotenv.config({
   path: path.resolve(__dirname, '../../.env')
})
interface ENV {
   PORT: number | undefined;
   ENV: string | undefined;
}
interface Config {
   PORT: number;
   ENV: string;
}
const getConfig = (): ENV => {
   return {
       PORT: process.env.PORT ? Number(process.env.PORT) : undefined,
       ENV: process.env.ENV ? String(process.env.ENV) : undefined
   }
}
const getSanitizedConfig = (config: ENV): Config => {
   for (const [key, value] of Object.entries(config)) {
       if (value === undefined) {
           throw new Error(`Missing key ${key} in .env`)
       }
   }
   return config as Config
}
const config = getConfig()
const sanitizedConfig = getSanitizedConfig(config)
export default sanitizedConfig

Пример применения ./src/index.ts:

import express, { Express, Request, Response } from 'express'
import config from './config'
const app: Express = express()
const port = config.PORT
app.get('/', (req: Request, res: Response) => {
   res.send('Express + Typescript Server')
})
app.listen(port, () => {
   console.log(`⚡️[server]: Server is running at http://localhost:${port}`);
})

 

Загрузка комментариев...