0
0

More than 1 year has passed since last update.

サーバーサイド環境構築(Node.js + Typescript)

Posted at

ss環境構築

まっさらな状態からcurlを叩いて「Hello World」を表示する

src > app.ts

import express from "express"

const app = express()

app.use(express.json())

app.get("/", async (_req, res) => {
  res.end("Hello World")
})

const port = 8080
app.listen(port, () => {
  // eslintでconsoleのエラーが出ないよう下記を追加
  // eslint-disable-next-line no-console
  console.log(`Listening on port ${port}`)
})

dependencies

コマンド

yarn add express:サーバーサイド Javascript の実行環境
yarn add dotenv:見せれない情報を.env ファイルで管理することで公開させない
yarn add winston:複数のトランスポート(出力先)をサポートするロギングライブラリ

devDependencies

コマンド

yarn add -D @types/express:expressの開発にtsを利用する
yarn add -D @types/node:ts を使う時、node_modules の型定義ファイル
yarn add -D cspell:スペルチェック → cspell.json 手書き、cspell.txt 作成
yarn add -D eslint:単純な構文エラーやプロジェクト固有のコーディング規約を定義することができる
→ 自由にルールを設定できる、rules で上書きすることでルールを緩くできる(.eslintrc.js)
yarn add -D eslint-config-prettier:Prettierと競合する可能性のあるルールをすべてオフにする
yarn add -D fixpack:package.json内を並び替え
yarn add -D prettier:ソースコードを整形してくれるツール(コードフォーマッター)
              → eslint では整形できないコードを整形できる
yarn add -D ts-node:ts を毎回 tsc コマンドを叩いて js にコンパイルことをしなくてもよくするやつ
yarn add -D ts-node-dev:ts ファイルを js ファイルにコンパイルすることなく、起動することができ、 さらに監視モードで素早く再起動が使用できる
yarn add -D typescript:Typescriptの使用

tsconfig.json

yarn run tsc --initでjsonを作成

{
  "compilerOptions": {
    "target": "ES2021",
    "lib": ["ES2021"],
    "module": "commonjs",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "outDir": "./dist",
    "noEmit": true,
    "downlevelIteration": true,
    "isolatedModules": true,
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "strictFunctionTypes": true,
    "strictBindCallApply": true,
    "strictPropertyInitialization": true,
    "noImplicitThis": true,
    "useUnknownInCatchVariables": true,
    "alwaysStrict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "exactOptionalPropertyTypes": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,
    "noUncheckedIndexedAccess": true,
    "noImplicitOverride": true,
    "noPropertyAccessFromIndexSignature": true,
    "allowUnusedLabels": true,
    "allowUnreachableCode": true
  },
  "exclude": ["node_modules"],
  "include": ["**/*.ts"]
}

cspell.json

{
  "version": "0.2",
  "language": "en",
  "dictionaries": ["en", "typescript"],
  "dictionaryDefinitions": [
    {
      "name": "en",
      "path": "./cspell.txt"
    }
  ],
  "ignorePaths": ["node_modules/**"]
}

.eslintrc.js

const OFF = 0; // eslint-disable-line no-unused-vars
const WARN = 1; // eslint-disable-line no-unused-vars
const ERROR = 2; // eslint-disable-line no-unused-vars

module.exports = {
  root: true,
  extends: [
    "eslint:recommended",
    "plugin:@typescript-eslint/recommended",
    "prettier",
  ],
  env: {
    node: true,
    es2021: true,
  },
  rules: {
    camelcase: OFF,
    "no-console": ERROR,
    "import/prefer-default-export": OFF,
    "no-underscore-dangle": OFF,
    "@typescript-eslint/camelcase": OFF,
  },
  settings: {
    "import/resolver": {
      node: {
        extensions: [".ts", ".js"],
      },
    },
  },
};

.eslintignore

.eslintrc.js
/node_modules
.cache/*
dist/*

.fixpackrc

{
  "sortToTop": [
    "name",
    "version",
    "author",
    "private",
    "main",
    "scripts",
    "dependencies",
    "devDependencies",
    "browser"
  ]
}

prettier.config.js

module.exports = {
  printWidth: 120,
  semi: false,
  trailingComma: "all",
};

.gitignore

gitで管理するためignore入れてます。

.env
/node_modules
.DS_Store
credential.json
/.vscode

ロガーのディレクトリ名 > index.ts, type.ts

index.ts
import { createLogger, format, transports } from "winston"
import { CreateCustomLoggerData, CustomInfoLogger, CustomErrorLogger, InitLoggerReturn } from "./type"

const displayFormat = format.printf(({ level, message }) => {
  return `${level}: ${message}`
})
const color = format.colorize({ all: true })
/**
 * @typedef InitLogger
 * @description ロガーのインスタンス生成
 * @param filePath ログ実行時ファイルパス
 * @returns InitLoggerReturn
 */
type InitLogger = (filePath: string) => InitLoggerReturn
export const initLogger: InitLogger = (filePath) => {
  const createCustomLoggerData: CreateCustomLoggerData = (logLevel, message, data) => {
    const logger = createLogger({
      level: logLevel,
      format: format.combine(color, displayFormat),
      transports: [new transports.Console()],
    })

    return {
      logger,
      msg: JSON.stringify({
        message,
        data,
        filePath,
      }),
    }
  }

  const infoLogger: CustomInfoLogger = (message, data) => {
    const { logger, msg } = createCustomLoggerData("info", message, data)
    logger.info(msg)
  }
  const errorLogger: CustomErrorLogger = (message, error) => {
    const stringError = JSON.stringify(error, Object.getOwnPropertyNames(error))

    const { logger, msg } = createCustomLoggerData("error", message, { error: stringError })
    logger.error(msg)
  }

  return { infoLogger, errorLogger }
}
type.ts
import { Logger } from "winston"

/**
 * @typedef CustomLogger
 * @description カスタムロガーの型定義
 * @param message ログメッセージ
 * @param data ログ出力データ
 */
export type CustomInfoLogger = (message: string, data?: Record<string, unknown>) => void
export type CustomErrorLogger = (message: string, error: unknown) => void
/**
 * @typedef InitLoggerReturn
 * @description InitLoggerの戻り値の型
 */
export type InitLoggerReturn = {
  infoLogger: CustomInfoLogger
  errorLogger: CustomErrorLogger
}

/**
 * @typedef CreateCustomLoggerDataReturn
 * @description CreateCustomLoggerDataの戻り値の型
 */
export type CreateCustomLoggerDataReturn = { logger: Logger; msg: string }

/**
 * winston準拠のログレベル
 */
type LogLevel = "error" | "warn" | "info" | "http" | "verbose" | "debug" | "silly"

/**
 * @typedef CreateCustomLoggerData
 * @description カスタムロガーと文字列化された出力メッセージ
 * @param logLevel ログレベル
 * @param message メインメッセージ
 * @param data オプショナルデータ
 */
export type CreateCustomLoggerData = (
  logLevel: LogLevel,
  message: string,
  data?: Record<string, unknown>,
) => CreateCustomLoggerDataReturn

 使う時

下記のようにimportして使うことができる。(console使うとeslintエラー出るのでwinstonを使用)

import { initLogger } from "./shared/initLogger"

const { infoLogger, errorLogger } = initLogger("src/index.ts")

infoLogger("infoLoggerです")

errorLogger("errorLoggerです", { error: "失敗" })

最後に

yarn run ts-node-dev src/app.tsでサーバーが立ち上がる。
package.jsonのscriptに下記の設定をすることでyarn devのコマンドで上記と同じように起動する。
"dev": "ts-node-dev src/app.ts"

Listening on port 8080が表示されたら、別のターミナルで
curl http://localhost:8080を叩くと「Hello World」が表示されます!

これで最低限の設定が完了し、実装に進められます。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0