📖

Node.js プロジェクトでコードを書き始めるまでにやること

9 min read

npm initでプロジェクト初期化

プロジェクトディレクリを作成して、そのディレクトリ内で以下のコマンドを実行します。

$ npm init -y
$ mkdir src
$ touch src/app.ts
# または
# touch src/index.ts
# または
# touch src/main.ts

TypeScript の実行環境を作る

以下のコマンドを実行します。

$ npm i -D typescript ts-node ts-node-dev
$ npx tsc --init

package.jsonscripts に以下を登録します。

package.json
"scripts": {
    "dev": "ts-node-dev --respawn ./src/app.ts",
    "start": "ts-node --transpile-only ./src/app.ts",
}

Node + express のプロジェクトを始める場合

$ npm i -D @types/node
$ npm i express
$ npm i -D @types/express

参考

知識ゼロから始めるTypeScript 〜基本編〜

ESLint と Prettier を導入する

ESLint のインストール

$ npm i --save-dev eslint typescript @typescript-eslint/parser @typescript-eslint/eslint-plugin
$ npx eslint --init

Prettier のインストール

ESLint はコードの正しさを保つのに対し、 Prettier はコードの読みやすさを保つためのツールです。

$ npm install --save-dev prettier
$ npm install --save-dev eslint-config-prettier
# または
# $ npm install --save-dev eslint-config-prettier eslint-plugin-prettier

$ touch .prettierrc.js
# または
# $ touch .prettierrc  

eslint-config-prettierは ESLintのルールのうち、Prettier と相容れないものを無効化する共有設定です。

eslint-plugin-prettierは Prettierのルールを ESLint のルールに統合するためのプラグインです。

.eslintrc.js
module.exports = {
  env: {
    browser: true,
    es2021: true
  },
  extends: [
    'standard',
+    'prettier',
  ],
  parser: '@typescript-eslint/parser',
  parserOptions: {
    ecmaVersion: 12,
    sourceType: 'module'
  },
  plugins: [
    '@typescript-eslint'
  ],
  rules: {
  }
}

'module' is not definedと表示された場合:

.eslintrc.js
module.exports = {
  env: {
    browser: true,
    es2021: true,
+      node: true,
  },
.prettierrc.js
module.exports = {
  singleQuote: true,
  trailingComma: 'es5',
  printWidth: 100,
  semi: false,
}
package.json
  "scripts": {
    "dev": "ts-node-dev --respawn",
+    "eject": "expo eject",
+    "lint": "eslint './src/**/*.{js,ts,tsx}'",
+    "lint:fix": "eslint --fix './src/**/*.{js,ts,tsx}'",
+    "format": "prettier --check ./src",
+    "format:fix": "prettier --write ./src"
  },

"scripts"にも書いていますが、--checheオプションをつけて実行すると、Prettier はコードの内容をチェックするだけで整形はしません。

--writeオプションをつけると、.prettierrc.prettierrc.js)の設定に基づいてコードが整形されます。

なお、『React ハンズオンラーニング』では、ESLint と Prettier を併用するために .eslintrc.jsonを以下のように書いています。

.eslintrc.json
{
    "env": {
        "browser": true,
        "es2021": true
    },
    "extends": [
        "eslint:recommended",
        "plugin:react/recommended",
+        "plugin:prettier/recommended"
    ],
    "parserOptions": {
        "ecmaFeatures": {
            "jsx": true
        },
        "ecmaVersion": 12,
        "sourceType": "module"
    },
    "plugins": [
        "react",
        "react-hooks",
+        "prettier"
    ],
    "rules": {
        "react-hooks/rules-of-hooks": "error",
        "react-hooks/exhaustive-deps": "warn",
+        "prettier/prettier": "error"
    }
}

が、この通りに使ってみると WebStorm 上で ESLint: Error: Failed to load plugin 'prettier' declared in '.eslintrc.json': Cannot find module 'eslint-plugin-prettier'が出ます。

以下の行を消せばエラーは消えるのですが、釈然としません。

.eslintrc.json
{
    "env": {
        "browser": true,
        "es2021": true
    },
    "extends": [
        "eslint:recommended",
        "plugin:react/recommended",
-        "plugin:prettier/recommended"
    ],
    "parserOptions": {
        "ecmaFeatures": {
            "jsx": true
        },
        "ecmaVersion": 12,
        "sourceType": "module"
    },
    "plugins": [
        "react",
        "react-hooks",
-        "prettier"
    ],
    "rules": {
        "react-hooks/rules-of-hooks": "error",
        "react-hooks/exhaustive-deps": "warn",
-        "prettier/prettier": "error"
    }
}

WebStorm の自動フォーマットの設定

私の場合は WebStorm を使っているので、 WebStorm の設定について記載しますが、 Visual Studio Code にも同様の機能があります。

WebStorm > Preferences > Languages & Frameworks > JavaScript > Code Quality Tools > ESLint

WebStorm > Preferences > Languages & Frameworks > JavaScript > Prettier

React Hooks のバグを検出する

『React ハンズオンラーニング』の10章に ESLint についての記事があったので追記します。
React Hooksのバグを検出するためのプラグインについてです。

$ npm install eslint-plugin-react-hooks --save-dev

.eslintrc.jsや、.eslintrc.jsonに以下を追記します。

.eslintrc.json
"plugins": [
   "react",
+  "react-hooks"
],
"rules": {
+  "react-hooks/rules-of-hooks": "error",
+  "react-hooks/exhaustive-deps": "warn"
}

react-hooks プラグインは use で始まる関数を React フックとみなし、一定のルールに従っているかをチェックします。

参考

React NativeをTypeScript + ESLint + Prettier + Storybookで環境構築

E2Eテスト

Playwright をインストールします。

$ npm i -D @playwright/test
$ npx playwright install

# スクレイピングなどに playwright を使う場合
$ npm i playwright

参考

Getting Started - Playwright

単体テスト

$ npm i jest @types/jest ts-jest -D
$ touch jest.config.js
jest.config.js
module.exports = {
  "roots": [
    "<rootDir>/src"
  ],
  "testMatch": [
    "**/__tests__/**/*.+(ts|tsx|js)",
    "**/?(*.)+(spec|test).+(ts|tsx|js)"
  ],
  "transform": {
    "^.+\\.(ts|tsx)$": "ts-jest"
  },
}

参考

Jest - TypeScript Deep Dive

Node.js のバージョンを固定する

プロジェクトのルートディレクトリに .node-version を作成します。

$ touch .node-version

.node-version ファイルに Node.js のバージョンを記載します。

ディレクトリ構造

Node + Express で API サーバーを作る場合

Project structure for an Express REST API when there is no "standard way" を参考にする場合。

$ cd src
$ mkdir {controllers,db,routes,services,tests,utils}
$ touch {controllers/index.ts,db/index.ts,routes/index.ts,services/index.ts,utils/index.ts}

A better project structure with Express and Node.Js を参考にする場合。

$ cd src
$ mkdir {controllers,routes,models,middleware}
$ touch {controllers/index.ts,routes/index.ts,models/index.ts,middleware/index.ts}

Node.js + express サーバーを動かす

src/app.ts
import express from 'express'

const app: express.Express = express()

app.get('/', (req, res) => {
  res.send('Hello world')
})

app.listen(3000, () => {
  console.log('Node.js app listening on port 3000!')
})
 $ npm run dev

ブラウザで http://localhost:3000/ を叩くと Hello World が表示されます。

環境変数を利用する

$ npm install dotenv --save
$ touch .env
TEST_ENV='This is test config!'
src/app.ts
import dotenv from 'dotenv'

dotenv.config()
const env = process.env.TEST_ENV
console.log('env:', env) // env: This is test config!

cron を利用する

$ npm i cron
$ npm i -D @types/cron
services/cronService.ts
import { CronJob } from 'cron'

export const useCronService = () => {
  const cronJob = new CronJob('10 * * * * *', () => {
    console.log('Hello Cron!')
  })

  return {
    cronJob,
  }
}

参考

How to make a Cron job for a typescript class method

React で TypeScriptのプロジェクトを始める

$ npx create-react-app my-type-app --template typescript

React Hooks ESLint プラグイン

$ npm install eslint-plugin-react-hooks --save-dev
// Your ESLint configuration
{
  "plugins": [
    // ...
    "react-hooks"
  ],
  "rules": {
    // ...
    "react-hooks/rules-of-hooks": "error", // Checks rules of Hooks
    "react-hooks/exhaustive-deps": "warn" // Checks effect dependencies
  }
}

フックのルール

モックサーバーの準備

$ npm i json-server --dev
$ npx json-server --watch db.json --port 3100

  \{^_^}/ hi!

db.json
{
  "todos":[
    {
      "id": 1,
      "content": "Install Create React App",
      "done": true
    },
    {
      "id": 2,
      "content": "モックサーバーを準備する",
      "done": false
    },
    {
      "id": 3,
      "content": "継続的デプロイの準備をする",
      "done": false
    }
  ]
}

http://localhost:3100/todosでJSONを取得できるようになります。

Discussion

ログインするとコメントできます