A simple Express application with LoopBack 4 REST API
Page Contents
Page Contents

Overview

Express は、特定の形式に固執しないNode.jsのフレームワークです。 LoopBack REST APIは、Expressアプリケーションにマウントして、ミドルウェアとして使用できます。こうして、ユーザーはニーズに合わせて両方のフレームワークの機能を組み合わせることが可能です。

このチュートリアルでは、LoopBack 4アプリケーションの土台・‘モデル’‘データソース’‘レポジトリ’‘コントローラー’の背景知識があることを前提としています。各機能のアプリ内での働きについては、Todo チュートリアルをご参照ください.

Try it out

先に、このチュートリアルの最終結果である、アプリケーション例を見たい場合は、次の手順に従ってください。

  1. lb4 example コマンドを実行、エクスプレス構成リポジトリを選択してクローンを作成します。

    lb4 example express-composition
    
  2. ディレクトリを切り替えます。

    cd loopback4-example-express-composition
    
  3. アプリケーションを起動します

    $ npm start
    
    Server is running at http://127.0.0.1:3000
    

LoopBackアプリケーションを作成する

土台の構築

lb4 app note を実行し、下記のプロンプトを入力してアプリケーションの土台を作成します。

$ lb4 app note
? Project description: An application for recording notes.
? Project root directory: (note)
? Application class name: (NoteApplication)
 ◉ Enable eslint: add a linter with pre-configured lint rules
 ◉ Enable prettier: install prettier to format code conforming to rules
 ◉ Enable mocha: install mocha to run tests
 ◉ Enable loopbackBuild: use @loopback/build helpers (e.g. lb-eslint)
 ◉ Enable vscode: add VSCode config files
❯◯ Enable docker: include Dockerfile and .dockerignore
 ◉ Enable repositories: include repository imports and RepositoryMixin
 ◉ Enable services: include service-proxy imports and ServiceMixin
 # npm will install dependencies now
 Application note was created in note.

Note モデルを追加する

プロジェクトフォルダー内で、lb4 modelを実行し、Noteモデルを構築します。idプロパティのデータ型はnumbertitleプロパティはstringcontentプロパティはstringEntityを作成します。

データソースを追加する

lb4 datasource dsコマンドと./data/ds.jsonファイルパスを実行して、メモリ内データソースを作成します。

Todo チュートリアルの例と同様、アプリケーションのルート内にデータフォルダを作成し、ds.jsonを作成します。 

$ mkdir data
$ touch data/ds.json

次に、以下をコピーしてds.jsonファイルに貼り付けます。

{
  "ids": {
    "Note": 3
  },
  "models": {
    "Note": {
      "1": "{\"title\":\"Things I need to buy\",\"content\":\"milk, cereal, and waffles\",\"id\":1}",
      "2": "{\"title\":\"Great frameworks\",\"content\":\"LoopBack is a great framework\",\"id\":2}"
    }
  }
}

Note レポジトリを追加する

lb4 repositoryコマンドを実行して、リポジトリを作成します。 データソースは DsDataSource、モデルは Noteモデル、 リポジトリのベースクラスはDefaultCrudRepository を選択します。

Note コントローラーを追加する

lb4 controller noteコマンドを実行して、Noteアプリケーションを完了させます。各項目で、REST Controller with CRUD functions タイプ、Noteモデル、およびNoteRepositoryリポジトリを選択します。idタイプのデータ型はnumber、ベースHTTPパス名は、デフォルトの/notesを選択します。

Facade Express アプリケーションを作成する

まず、expressモジュールの依存関係をインストールします。

npm install --save express
npm install --save-dev @types/express

新しいクラスsrc/server.tsを作成して、Express classを作成します。

src/server.ts

import express from 'express';

export class ExpressServer {
  constructor() {}
}

Expressアプリケーションインスタンスと、LoopBackアプリケーションインスタンスの2つのプロパティを作成します。

import {NoteApplication} from './application';
import {ApplicationConfig} from '@loopback/core';
import express from 'express';

export class ExpressServer {
  private app: express.Application;
  private lbApp: NoteApplication;

  constructor(options: ApplicationConfig = {}) {
    this.app = express();
    this.lbApp = new NoteApplication(options);
  }
}

次に、コンストラクター内でベースパスを追加し、Expressを介してフロントエンドアセットを公開します。

this.app.use('/api', this.lbApp.requestHandler);

public/index.html を修正して、base pathを更新します。

public/index.html

<h3>OpenAPI spec: <a href="/api/openapi.json">/openapi.json</a></h3>
<h3>API Explorer: <a href="/api/explorer">/explorer</a></h3>

カスタムExpressルートも、以下の通り追加します。

import {Request, Response} from 'express';
import path from 'path';

export class ExpressServer {
  private app: express.Application;
  private lbApp: NoteApplication;

  constructor(options: ApplicationConfig = {}) {
    // earlier code

    // Custom Express routes
    this.app.get('/', function(_req: Request, res: Response) {
      res.sendFile(path.resolve('public/express.html'));
    });
    this.app.get('/hello', function(_req: Request, res: Response) {
      res.send('Hello world!');
    });
  }
}

また、public/express.html ファイルをプロジェクトに追加します。

p-event をインストールし、サーバーがListenしているか確認しましょう。

npm install --save p-event

最後に、 Note applicationとExpressアプリケーションを起動する機能を追加しましょう。

import pEvent from 'p-event';

export class ExpressServer {
  private app: express.Application;
  private lbApp: NoteApplication;

  constructor(options: ApplicationConfig = {}) {
    //...
  }

  async boot() {
    await this.lbApp.boot();
  }

  public async start() {
    await this.lbApp.start();
    const port = this.lbApp.restServer.config.port || 3000;
    const host = this.lbApp.restServer.config.host || '127.0.0.1';
    this.server = this.app.listen(port, host);
    await pEvent(this.server, 'listening');
  }

  // For testing purposes
  public async stop() {
    if (!this.server) return;
    await this.lbApp.stop();
    this.server.close();
    await pEvent(this.server, 'close');
    this.server = undefined;
  }
}

src/server.ts ファイルは準備完了しました。src/index.ts を修正して、アプリケーションを起動させましょう。

src/index.ts

import {ExpressServer} from './server';
import {ApplicationConfig} from '@loopback/core';

export {ExpressServer, NoteApplication};

export async function main(options: ApplicationConfig = {}) {
  const server = new ExpressServer(options);
  await server.boot();
  await server.start();
  console.log('Server is running at http://127.0.0.1:3000');
}

index.js

const application = require('./dist');

module.exports = application;

if (require.main === module) {
  // Run the application
  const config = {
    rest: {
      port: +process.env.PORT || 3000,
      host: process.env.HOST || 'localhost',
      openApiSpec: {
        // useful when used with OpenAPI-to-GraphQL to locate your application
        setServersFromRequest: true,
      },
      // Use the LB4 application as a route. It should not be listening.
      listenOnStart: false,
    },
  };
  application.main(config).catch(err => {
    console.error('Cannot start the application.', err);
    process.exit(1);
  });
}

[注意]ExpressサーバーをListenさせるためにLB4アプリケーションを起動した際、LB4 アプリケーションがHTTPをListenしないようにするために、listenOnStartfalse に設定されていることを確認してください。 

それでは、アプリケーションを起動してhttp://127.0.0.1:3000 にアクセスしてみましょう。

npm start

Server is running at http://127.0.0.1:3000

Explorerで、Loopbackアプリケーションへのリクエストを行うことができます。なお、サーバーはhttp://127.0.0.1:3000/api であることに注意してください 。

/helloExpressルートを表示するには、http://127.0.0.1:3000/helloにアクセスしてください。「Hello world!」が表示されます。

アプリケーションで静的ファイルを提供するには、コンストラクタの最後に次を追加します。

Explorerを開くと、 Loopbackアプリケーションからリクエストを送ることができます。サーバーはhttp://127.0.0.1:3000/apiです。

カスタムの/hello Expressルートを表示するには、http://127.0.0.1:3000/helloを開いて’Hello world!’を確認します。

アプリケーションで静的ファイルを提供するには、コンストラクタの最後に次の記述を追加します。

src/server.ts

export class ExpressServer {
  private app: express.Application;
  private lbApp: NoteApplication;

  constructor(options: ApplicationConfig = {}) {
    // earlier code

    // Serve static files in the public folder
    this.app.use(express.static('public'));
  }

  // other functions
}

これで、public/ フォルダーに静的ファイルをロードできます。 一例として、public/notes.htmlのファイルをプロジェクトに追加してnpm startし、http://127.0.0.1:3000/notes.htmlを開いてみてください。メモを表形式で表示する静的ファイルを確認できます。詳細は、Serving static files in Expressをご参照ください。

お疲れ様でした。LoopBack4 REST APIをExpressアプリケーションにマウントできました。