フロントエンド環境構築(Typescript)

## fe環境構築

以前作成した下記記事に加えて、開発で導入したものを記載します。

https://qiita.com/sh19982580/items/5f71856c7949c494d769

## dependencies

##### コマンド

`yarn add dotenv`：見せれない情報を.env ファイルで管理することで公開させない
`yarn add winston`：複数のトランスポート（出力先）をサポートするロギングライブラリ

## devDependencies

##### コマンド

`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 にコンパイルことをしなくてもよくするやつ

## 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

## .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入れる

    .DS_Store
    .env
    node_modules
    dist

## ロガーのディレクトリ名 > 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: "失敗" })

## 最後に

前回のReactで「Hello World」を表示する記事では長くなってしまうため、今回はローカル開発で導入したもの全てを記載しました。