IBM i 上でNode.jsのWebアプリを動かす その3 (ExpressとEJS)

# はじめに

「IBM i 上でNode.jsのWebアプリを動かす」3つ目の記事です。  
- 1つ目の記事はこちら  
  IBM i 上での Node.js の動かし方を簡単に紹介しています。

 https://qiita.com/tom_m_m/items/5cd480eb1aad35a6a6dc

- 2つ目の記事はこちら  
環境情報や作成したWebアプリの概要はこちらをご覧ください。

https://qiita.com/tom_m_m/items/1d0139cc8b507be4b591
 
作成したコードはこちらにおいています。  

https://github.com/tom-m-m/ibmi-nodejs-qr-detection

この記事の中では、こちらのアプリを「QRコードアプリ」と記載しています。  
Node.jsでのWebアプリ制作に関しては手探りで行っていますので、荒いところがあるかもしれません。

# Express について

前回につづいて、アプリ内で使っているパッケージについて書いていきます。  
まずは、`Express` についてです。  
これは、Node.js のWebアプリケーションフレームの一つです。  
Node.js 自体は、Javascriptの実行環境なのですが、Expressを使うことで簡単にWebアプリを作ることができます。  

https://expressjs.com/ja/

こちらのページなど参考にさせていただきました。  

https://qiita.com/ryome/items/16659012ed8aa0aa1fac

それでは、express をインストールして動かしてみます。  
前回の idb-connector と同じように、ディレクトリの作成と初期化を行った上で、インストールを行います。  

```
express-test # npm install express

added 62 packages, and audited 63 packages in 3s

11 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities
```

Webアプリを動かすための Javascript を書いていきます。  
index.js を新しく作成します。  
※ Githubにアップロードしているコードでは、 `app.js` となっています。  

実際のコードは、こちらになります。  
```
const express = require('express');

const app = express();

const hostname = '<サーバーのIPアドレス>';
const port = 9443;

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

app.listen(port, () => console.log(`Listening on port ${port}!`));
```

下記のコマンドで実行できます。  
このサンプルでは、ポートを 9443 に定義しています。  
※ この環境では、よく使われる8080が別で使われていたので、このポートにしています。特に意味はありません。   

実行が完了したら、 `http://<サーバーのIPアドレス>:9443`
```
# node index.js 
Listening on port 9443!
```
アクセスしてみると、無事 Hello World! が表示されています。  

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242652/a0ced5ac-c494-766a-13ff-656df98f92f5.png)


express では、 `res.send` を `res.sendFile` にすることで、HTMLのファイルを表示することも可能です。  
QRコードを読み取るアプリでは、また別の方法 (ejs) を使うので、また違った書き方をしていますが、単純にHTMLを使う場合であれば下記のように記述します。  

```javascript:index.js
const express = require('express');

const app = express();

const hostname = '<サーバーのIPアドレス>';
const port = 9443;

app.get('/', (req, res) => {
    res.sendFile(__dirname + 'index.html');
})

app.listen(port, () => console.log(`Listening on port ${port}!`));
```

HTMLのファイルはこちらのものを、index.js と同じディレクトリに作っています。
```html:index.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  Hello, World!
</body>
</html>
```

## Expressのルーティング

HTTPのリクエストに応じてサーバー側で何かを実行したり、表示するファイルを変更するといったことができます。  
先程の index.js では、`app.get()` の部分で index.html を表示しています。  
GETリクエストがあった場合に、index.html を表示するという記述になっています。  
QRコードアプリでは、QRコードを読み取った時や、ボタンを押したときにPOSTやGETリクエストを送り、Node.js でDBアクセスやベージ遷移を行うようにしています。  

# EJSについて

次に、EJSについて書いていきます。  
EJSは、JavaScriptで使われるテンプレートエンジンです。  

> EJSとは主にJavaScriptで使用されるテンプレートエンジンです。EJSを利用することでHTMLをヘッダーやフッターで分割して管理することやHTML内でループ処理を書いて簡単に記述できるなどを実現できます。

とのこと。
ヘッダーやフッターは、1つのWebアプリの中で共通するので分割して管理したり、HTMLの中でサーバー側から渡したデータをループ処理したりできます。  
今回のQRコードアプリで使っていますが、あまり有効に活用できていません。  

EJSについては、こちらを参考にしています。  

https://zumilog.org/ejs-howto

https://nakanishi-s.jp/node%E3%82%92%E3%81%A1%E3%82%83%E3%82%93%E3%81%A8%E5%AD%A6%E3%81%B6-ejs%E7%B7%A8/


上記の記事ではEJS単体で使用しているため、先に紹介した Express と組み合わせたときの書き方と少し異なる部分があることに注意してください。  

Express との組み合わせは、こちらの記事を参考にしています。  

https://m-kenomemo.com/node-express-ejs/

https://enlyt.co.jp/blog/node-js-2/

ここでは、EJS + Express の場合で書いていきます。  

## インストールから実行

先程、HTMLのファイルを作って表示したのですが、そこにEJSを追加します。  
ここまでやってきたように、EJS をインストールします。  

```
express-test # npm install ejs

added 16 packages, and audited 79 packages in 3s

13 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities
```

テンプレートファイル (ejsファイル) は、`views` ディレクトリに格納する事になっています。  
そのため、views ディレクトリを作成します。  
その中に、index.ejs を作成して、ブラウザからアクセスしてみます。  
ファイルの配置はこのようになっています。  
```
.
|-- index.js
|-- node_modules
|-- package-lock.json
|-- package.json
`-- views
    `-- index.ejs
```

ejsファイルはこのように書いています。  
```ejs:index.ejs
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>トップ</title>
  </head>
  <body>
    <h1>Hello EJS World!</h1>
  </body>
</html>
```
ejsを利用するために、index.js を更新する必要があります。  
express クラスを定義した、app に `app.set("view engine", "ejs");` を記述することで設定できます。  
また、ejsファイルを呼び出すときに、`res.render` を使用します。  

```
const express = require('express');

const app = express();

app.set("view engine", "ejs");

const hostname = 'ibmi75';
const port = 9443;

app.get('/', (req, res) => {
  res.render('index');
});

app.listen(port, () => console.log(`Listening on port ${port}!`));
```
これまでと同じように実行すると、期待どおりの表示になりました。  

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242652/8eaec10e-6ba2-4600-34e7-30cbcb4858d9.png)

## データの渡し方

EJSを使うことで、サーバー側からデータを渡して、動的にページを表示することができます。  
こちらも実際に動かしてみます。  

`res.render()` の部分を以下のように変更します。
`{}`で囲われた2つ目の引数がejs側に渡すデータになります。      
```
app.get('/', (req, res) => {
  res.render('index', {data: 'jsから渡したデータ'});
});
```

index.ejs は下記のように変更します。  
本文のところに、`<%= data %>` という記述があります。  
こちらが、ejsでデータを埋め込む書き方となります。  
index.js 側で渡した変数を、ejs側で使います。  

```
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>トップ</title>
  </head>
  <body>
    <h1><%= data %></h1>
  </body>
</html>
```

実行してみると、以下のように表示されました。  
データが渡されていることが確認できました。  

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242652/5dfaf78b-570e-6373-8acc-fc7832cd5a80.png)

QRコードアプリでは、idb-connector で取得したデータをこのようにejsファイルに渡して表示をしたり、表示する内容を変えたりしています。  

# さいごに

3つ目の記事はここまでとなります。  
今回は、Webアプリの中心となるパッケージの取り扱いについてまとめてみました。  
次回は、QRコードの読み取り部分と実際のアプリの動きについて書いていきます。