MEANスタック入門(3) Expressを利用したバックエンド開発

今回はAngular CLIで作成したAngularのディレクトリ階層を足場にして、Expressを活用したバックエンドの開発を行います。
言語はTypeScriptで書いていきますので、トランスパイルの方法などにも触れていきます。

TypeScriptのインストール

基本的にコードはTypescriptで書くのでtypescriptをインストールします。
--save-devオプションを指定すると、package.jsondevDependenciesに書き込まれます。

npm install --save-dev typescript

ローカルインストールしたのでtscnode_modules/.bin/配下にあります。
node_modules/.bin/にパスを通しておくか、以下のように実行します。

$ node_modules/.bin/tsc

ここから先はパスを通した前提で進めます。

Expressのインストールとバックエンドの実装

まずはexpressとリクエストデータを処理するためのbody-parserをインストールします。 --saveオプションを指定すると、package.jsondependenciesに書き込まれます。

$ npm install --save express body-parser

ルートディレクトリにserverディレクトリを作成し、以下のような構成にします。

server
│  app.ts
│  config.ts
│  tsconfig.json
│
├─bin
│    www.ts
│
└─routes
     users.ts

エントリポイントはbin配下のwww.tsです。 server直下のapp.tsconfig.tsを参照します。

www.ts

import * as http from "http";
import { app } from "../app";
import { serverPort } from "../config";

const port = process.env.PORT || serverPort;
app.set("port", port);

const server = http.createServer(app);

server.listen(port);

設定ファイルconfig.tsにポート番号を記載します。

config.ts

export const serverPort = 4300;

www.tsの中でhttp.createServerに渡しているapp.tsには、サーバーでリクエストを受け取った時の処理を書きます。

ルーティングはここで実行し、実際の処理はroutes配下のファイルに振ります。

ちなみに開発中にAngularをng serverで実行している場合はdist/clientは空なので、ルートにアクセスしても404になります。

app.ts

import * as express from "express";
import * as path from "path";
import { json, urlencoded } from "body-parser";
import * as compression from "compression";

import { usersRouter } from "./routes/users";

const app: express.Application = express();
app.disable("x-powered-by");

app.use(json());
app.use(compression());
app.use(urlencoded({ extended: true }));

app.use(express.static(path.join(__dirname, "../client")));

app.use("/api/users", usersRouter);

app.get("/", (req, res) => {
  res.sendFile(path.join(__dirname, '../client/index.html'));
});

export { app };

users.tsを作成してapiの実体を書きます。 ここでは/api/usersにGETでアクセスがあった場合、ダミーデータのjsonを返すようにします。

users.ts

import { Request, Response, Router } from "express";

const usersRouter: Router = Router();

let users = {users: [
  {
    id: 0,
    address: "NA6IF2OMBSTK2NEMXMYDQYXT32IGPKHSMULWLAKE"
  },
  {
    id: 1,
    address: "NDSNEM2HC4IEPQXGVDOWYMJ2MIPENUXN6HFJDHYZ"
  }
]};

usersRouter.get("/", (request: Request, response: Response) => {
  response.json(users);
});

export { usersRouter };

トランスパイルとサーバーの実行

これでロジックは完成なので、トランスパイルの設定をserver直下のtsconfig.jsonに書きます。 outDirで出力先を設定します。

tsconfig.json

{
  "compilerOptions": {
    "declaration": false,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "lib": ["es6", "dom"],
    "module": "commonjs",
    "moduleResolution": "node",
    "outDir": "../dist/server",
    "target": "es6",
    "typeRoots": [
      "../node_modules/@types"
    ]
  }
}

tsc-pオプションで上記で作成したtsconfig.jsonの位置を指定して実行します。

$ tsc -p ./server

トランスパイルされたwww.jsを実行すると、config.tsに設定したポートでサービスが提供されます。

$ node dist/server/bin/www.js

動作確認

http://localhost:4300/api/usersにアクセスすると、apiからレスポンスが返ってきます。 f:id:tadajam:20170503233422p:plain

これでExpress側の準備は一旦完了です。