バックエンド側 node.js Express/TypeScript 環境作成

2023-11-04

パクリ16発目!

パクリ元

内容

前回まででなんとなくのバックエンド側構成が出来上がったので json を返すような API サーバを遅まきながらやったことのない node.js でお勉強する。経験のある Apache Laravel とはシングルスレッド/マルチスレッド、同期非同期やらの違いがあるらしいが、やる事の基本は変わらないだろう。

一応これだけやっておけばいいだろう、という以下一覧を完了させて ECS リリースさせることで今回を終わりとする。

  • 開発環境構築     ←←← 今回ココから
  • プロジェクト作成・最適なフォルダ構成
  • (認証・認可) フロントエンドとの連携が必要なので今回省略。
  • セッションチェック
  • バリデーション
  • DB参照・更新
  • API取得
  • API取得待ち合わせ
  • 長時間処理を非同期処理で
  • メール送信
  • CSVアップロード
  • ファイルダウンロード
  • EXCEL/PDF作成
  • ログ処理
  • 環境ファイルによる振り分け
  • APIによってはIPチェックやHeaderチェック
  • テスト
  • AWS環境へデプロイ

開発環境構築

パクリ元1つ目を参考に WSL2(Ubuntu) に node をインストールする。

~$ sudo apt update && sudo apt upgrade
・・・
~$ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash
・・・
=> Close and reopen your terminal to start using nvm or run the following to use it now:

一度ターミナルを落として再度立ち上げ。

~$ nvm install node
・・・
~$ nvm current
v20.8.0

プロジェクト作成

パクリ元2つ目を参考にプロジェクトを作成していく。なぜこのページを選んだかというと、、よく分からないが node.js を使用してバックエンドを作成する場合は Express や TypeScript というキーワードがいろんなページに載っていたから。パクリ学習は参考ページが間違っていることは想定していないのでただ信じて進むのみ。

~$ mkdir nodetest
~$ cd nodetest/
~/nodetest$ npm init -y
・・・
~/nodetest$ npm install --save express
・・・
npm notice Run npm install -g npm@10.2.0 to update!
npm notice
npm ERR! code ETIMEDOUT
npm ERR! syscall read
・・・

なんかエラーが出た。npm のバージョンが古い?らしいので指定されたコマンドを打ってみる。npm 自身はグローバルインストールでいいのかな?ここらへんも把握してないが進む。

~/nodetest$ npm install -g npm@10.2.0
・・・
~/nodetest$ npm install --save express
・・・
~/nodetest$ mkdir src
~/nodetest$ vi src/index.js
~/nodetest/src/index.js
const express = require('express');
const app = express();
const port = 3001;

app.get('/', (req, res) => res.send('Hello World!'));
app.listen(port, () => console.log(`Example app listening on port ${port}!`));

サーバを起動して確かめる。

~/nodetest$ node src/index.js
Example app listening on port 3001!

ここまではOK。

TypeScript

TypeScript はどうやらきれいな javascript を吐き出すためのジェネレータのようで、実行時ではなく開発時にしか関係ないようなので –save-dev をつけてインストールするのか、とか思いながらインストールする。出たエラーに対しては指定されたコマンドを打ってみる。

~/nodetest$ npm install --save-dev typescript
・・・
~/nodetest$ mv src/index.js src/index.ts
~/nodetest$ npx tsc src/index.ts
src/index.ts:1:17 - error TS2580: Cannot find name 'require'. Do you need to install type definitions for node? Try `npm i --save-dev @types/node`.
1 const express = require('express');
                  ~~~~~~~
Found 1 error in src/index.ts:1
~/nodetest$ npm i --save-dev @types/node
・・・
~/nodetest$ npx tsc src/index.ts

TypeScript でコンパイルすることで ts ファイルから js ファイルを作成することができた。

Express

Express は Web アプリケーションフレームワークだとのこと。

~/nodetest$ npm install --save-dev @types/express
・・・

これで express を require でなく import で呼び出せば ts ファイル上で型が定義されるので js ファイル上で何が入っているか分からないようなことがなくなるとの事。ここまでOK。

ts ファイルと js ファイルが同じ位置にできても管理しにくいので js ファイルを削除してからtsconfig.json を作成して出力フォルダを指定することで回避する。

~/nodetest$ ls
node_modules  package-lock.json  package.json  src
~/nodetest$ ls src/
index.js  index.ts
~/nodetest$ rm src/index.js
~/nodetest$ npx tsc --init
・・・
~/nodetest$ ls
node_modules  package-lock.json  package.json  src  tsconfig.json
~/nodetest/tsconfig.json
    // "outDir": "./",  /* Specify an output folder for all emitted files. */
    "outDir": "./dist",  /* Specify an output folder for all emitted files. */

再度コンパイルすると dist フォルダに js ファイルが出来上がっているのを確認。

~/nodetest$ npx tsc
~/nodetest$ ls
dist  node_modules  package-lock.json  package.json  src  tsconfig.json
~/nodetest$ ls dist/
index.js

ts-node

node で js ファイルを指定するのではなく、ts-node で ts ファイルを指定してサーバを起動する。

~/nodetest$ npm install --save-dev ts-node
~/nodetest$ npx ts-node src/index.ts
Example app listening on port 3001!

nodemon

サーバを立ち上げた状態で ts ファイルを更新したら即反映させるため nodemon インストール。package.json にコマンドを入れることで開発用サーバ起動を npm run dev に統一する。

~/nodetest$ npm install --save-dev nodemon
~/nodetest/package.json
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "nodemon src/index.ts"
  },
~/nodetest$ npm run dev
・・・
Example app listening on port 3001!

src/index.ts を変更してもブラウザ再読み込みすれば反映されている。

最適なフォルダ構成

パクリ元3つ目にある、Express generator というものがあるらしいがいまいちよく分からないので適当にフォルダ構成を作ることとする。パクリ元4つ目を参考にまずはルーティング。以下のようにする。

┗━ src
   ┣━ index.ts
   ┗━ routes
       ┗━ users.ts
~/nodetest$ mkdir src/routes
~/nodetest/src/routes/users.ts
import * as Express from 'express';
const router = Express.Router();
router.get("/", (req, res, next) => {
    res.json([{"id":1}]);
  });
export default router;
~/nodetest/src/index.ts
import express from 'express';
import type { Express, Request, Response } from 'express';
import users from './routes/users';
const app: Express = express();
const port = 3001;
app.use('/users', users);
app.listen(port, () => console.log(`Example app listening on port ${port}!`));

http://localhost:3001/users にアクセスすると [{“id":1}] が返ってくるのを確認。

雑感

先は長い。