2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

私のNodeJS+TypeScriptプロジェクト初期設定手順

Last updated at Posted at 2022-06-20

この記事について

NodeJS環境で実行するサーバサイドアプリケーション開発において
新規プロジェクト(リポジトリ)に TypeScript、フォーマッタ(Prettier)、リンタ(ESLint)、単体テストツール(Jest)を導入する手順のメモ
※適宜加筆修正を行っていく予定

手順

package.json の生成

npm init -y

TypeScript の導入

TypeScript本体とNodeJS組み込み機能の型定義パッケージをインストール

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

tsconfig.json を設定

以下のコマンドで、コメント付きの tsconfig.json ファイルが生成されるのでいくつか設定を変更する

npx tsc --init

以下の設定例ではソースコードを src ディレクトリ、生成物を dist ディレクトリに配置する設定となっている

tsconfig.json 設定例
{
    "compilerOptions": {
        "incremental": true,
        "tsBuildInfoFile": "./.tsbuildinfo",

        "target": "ES2021",
        "lib": ["ES2021"],
        "experimentalDecorators": true,
        "emitDecoratorMetadata": true,

        "module": "commonjs",
        "moduleResolution": "node",
        "rootDir": "./src",
        "baseUrl": "./src",
        "paths": {
            "~/*": ["./*"]
        },
        "resolveJsonModule": true,
        "allowJs": true,
        "checkJs": true,
        "outDir": "./dist",

        "isolatedModules": true,
        "esModuleInterop": true,
        "forceConsistentCasingInFileNames": true,

        "strict": true,
        "noUnusedLocals": true,
        "noUnusedParameters": true,
        "exactOptionalPropertyTypes": true,
        "noImplicitReturns": true,
        "noFallthroughCasesInSwitch": true,
        "noUncheckedIndexedAccess": true,
        "noImplicitOverride": true,
        "noPropertyAccessFromIndexSignature": true,
        "allowUnusedLabels": false,
        "allowUnreachableCode": false,

        "skipLibCheck": true
    },
    "include": ["./src"],
    "exclude": ["node_modules", "./dist"]
}
tsconfig.json 各設定値について補足

"target": "ES2021",
"lib": ["ES2021"],

NodeJSのバージョンに合わせて設定、(現在LTSの)NodeJS v16では ES2021 までサポートしている

"experimentalDecorators": true,
"emitDecoratorMetadata": true,

デコレータを利用する必要がある場合 true にしておく

"rootDir": "./src",

ソースコードを src ディレクトリ内に置くプロジェクトレイアウトの場合はこのようにしておく

"baseUrl": "./src",
"paths": { "~/": ["./"] },

パスエイリアスの設定。どの階層のファイルからも src/ を ~/ と見做して import できるようにしている

"outDir": "./dist",

コンパイルした JS の出力先。
ソースコードと同じディレクトリに混在しないよう dist ディレクトリ配下に出力する設定にする
webpack や esbuild などのバンドルツールを利用する場合は効果がないので注意

"strict": true,
から
"allowUnreachableCode": false,

これらの厳密な構文チェックの設定は最初にすべて有効にしておき、支障がある場合のみ無効化している

各項目のさらに詳しい説明は公式ドキュメントを参照

TypeScriptでの開発中に簡易に実行するためのツールを追加

npm install --save-dev ts-node ts-node-dev tsconfig-paths

ts-node …TSファイルを直接実行できる
ts-node-dev …(サーバプログラム開発などで)実行しながらコード修正時に自動で再起動(watch)させる
tsconfig-paths …実行時にパスエイリアスを解決させる
を大抵の場合TypeScriptのプロジェクトに追加している

以下のように -r tsconfig-paths/register を渡すことでパスエイリアスを解決させて実行できる

ts-node -r tsconfig-paths/register src/main.ts
ts-node-dev -r tsconfig-paths/register src/main.ts

# パスエイリアスを使用したTSをコンパイルしたJS実行時に
TS_NODE_BASEURL=dist node -r tsconfig-paths/register dist/main.js

package.json の scripts に追加

短いコマンド npm run dev でメインスクリプトを起動できるよう package.json の scripts に登録しておく

package.json
  "scripts": {
      ...
+     "dev": "ts-node-dev -r tsconfig-paths/register src/main.ts",
      ...
  },

フォーマッタ(Prettier)の導入

フォーマッタツールPrettierをプロジェクトに追加する

npm install --save-dev prettier

.prettierrc.js を設定

プロジェクトの規約に沿って設定値を変える

.prettierrc.js雛形
/** @type {import("prettier").Config} */
module.exports = {
    printWidth: 120,
    tabWidth: 4,
    useTabs: false,
    semi: true,
    singleQuote: false,
    quoteProps: "consistent",
    jsxSingleQuote: false,
    trailingComma: "all",
    bracketSpacing: true,
    bracketSameLine: false,
    arrowParens: "always",
};
各設定項目の補足
.prettierrc.js
/** @type {import("prettier").Config} */
module.exports = {
    // 1行の最大長
    printWidth: 120,
    // インデント幅
    tabWidth: 4,
    // インデントにスペースを使用
    useTabs: false,
    // 文末にセミコロンをつける
    semi: true,
    // 文字列リテラルをダブルクォーテーションで囲む
    singleQuote: false,
    // オブジェクトリテラルのプロパティ名のクォーテーションに一貫性をもたせる
    quoteProps: "consistent",
    // JSX属性値をダブルクォーテーションで囲む
    jsxSingleQuote: false,
    // 配列(オブジェクト)リテラルの最後の要素(プロパティ)の後ろにもカンマを付ける
    trailingComma: "all",
    // 波括弧の内側にスペースを入れる
    bracketSpacing: true,
    // 複数行のHTML要素・JSXタグの「>」を単独で新しい行に置く
    bracketSameLine: false,
    // アロー関数の引数が1つの場合も丸括弧で囲む
    arrowParens: "always",
};

※更に詳しい各設定項目の説明は公式ドキュメントを参照

package.json の scripts を追加

チェックのみを行う lint スクリプトと、訂正を行う fixスクリプトを package.json に追加しておく

package.json
  "scripts": {
      ...
+     "lint": "prettier -l src",
+     "fix": "prettier -w src",
      ...
  }

テストツール (Jest) の導入

Jestをプロジェクトに追加する
あわせて TypeScript に対応させるための ts-jest と型定義も追加

npm install --save-dev jest @types/jest ts-jest

設定ファイル jest.config.js の追加

TypeScript用の設定ファイルを生成する

npx ts-jest config:init

生成された jest.config.js を、
パスエイリアスに対応させるため以下のように修正

jest.config.js
const { pathsToModuleNameMapper } = require("ts-jest");
const { loadConfig } = require("tsconfig-paths");

const tsconfig = loadConfig();

/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */
module.exports = {
    preset: "ts-jest",
    testEnvironment: "node",

    // paths
    moduleNameMapper: pathsToModuleNameMapper(tsconfig.paths, {
        prefix: tsconfig.absoluteBaseUrl,
    }),
};

package.json の scripts を追加

npm run test で実行できるように package.json に追加しておく
(オプションを追加しなければ npx jest より長くなるのであまり意味がないかもしれない…)

package.json
  "scripts": {
      ...
+     "test": "jest",
      ...
  }

コードチェックツール ESLint の導入

ESLintを追加

TypeScriptに対応させるための typescript-eslint
import 順序のルールを追加する eslint-plugin-import
prettier と競合する eslint ルールを無効化する eslint-config-prettier
jest 用のルールを追加する eslint-plugin-jest なども追加する

npm install --save-dev eslint \
  @typescript-eslint/parser @typescript-eslint/eslint-plugin \
  eslint-plugin-import eslint-import-resolver-typescript \
  eslint-config-prettier eslint-plugin-jest

設定ファイル .eslintrc.js を追加

以下のように各プラグインの推奨ルールを extends に入れておき、
プロジェクト開発に合わないものや足りないものを rules で無効化/追加する

.eslintrc.js
/** @type {import("eslint").Linter.Config} */
module.exports = {
    env: {
        node: true,
        commonjs: true,
        es2021: true,
        jest: true,
    },
    plugins: [
        //
        "@typescript-eslint",
        "import",
        "jest",
    ],
    parser: "@typescript-eslint/parser",
    parserOptions: {
        project: "./tsconfig.json",
    },
    settings: {
        "import/parsers": {
            "@typescript-eslint/parser": [".ts", ".tsx"],
        },
        "import/resolver": {
            typescript: true,
        },
    },
    extends: [
        "eslint:recommended",
        "plugin:@typescript-eslint/recommended",
        "plugin:import/recommended",
        "plugin:import/typescript",
        "plugin:jest/recommended",
        "prettier",
    ],
    rules: {},
};
rulesに追加する一例

ESLintrules追加の例

.eslintrc.jsのrules抜粋
// 単一行のifブロックの波括弧省略禁止
"curly": "error",

// ifブロックで必ずreturnする場合のelse記述禁止
"no-else-return": "error",

// 厳密比較の強制
"eqeqeq": "error",

// 関数の最大行数(トップレベルの関数除く)
"max-statements": ["error", 40, { ignoreTopLevelFunctions: true }],

// ひとつの var/const/letで複数の変数を宣言することを禁止
"one-var": ["error", "never"],

import のルール追加例

.eslintrc.jsのrules抜粋
    // import文をファイルの先頭に置く
    "import/first": "error",

    // import 記述順のルール
    "import/order": ["error", {
        // アルファベット順に並べる
        "alphabetize": { order: "asc", caseInsensitive: false },
        // グループごとに並べる NodeJSビルトインモジュール→外部モジュール→内部モジュール→親ディレクトリ
        "groups": ["builtin", "external", "internal", "parent", "sibling"],
        // グループ間に空行を入れる
        "newlines-between": "always",
    }],

package.json の scripts を修正

npm run lint で ESLint によるチェックも実行されるようにする
npm run fix で ESLint ルール違反の訂正(自動でできるものに限る)も実行されるようにする

package.json
  "scripts": {
      ...
-     "lint": "prettier -l src",
+     "lint": "prettier -l src && eslint src",
-     "fix": "prettier -w src",
+     "fix": "prettier -w src && eslint src --fix",
      ...
  }
2
1
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
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?