簡素なHTML/Javascriptの検証環境をNode.jsで構築してみた

### 検証環境を用意しようとした経緯
iOSエンジニアですが、アーキテクチャーやライブラリなど、フロント(Javascript)経由の技術が多いので簡単にデバックできるサーバーを作成してみようと思いました。ご自由にお使いください。

### 実行環境(MacとNode.js)
Mac環境であればNode.jsをインストールすれば実行可能です。

### 構築ステップ
1. Node.jsをインストール
node-v14.xx.x.pkgをダブルクリックしてインストールします。
(node-v14.17.4.pkgを使用しました)
https://nodejs.dev/download/

2. Githubよりnode-jsをチェックアウトする。
リポジトリ: https://github.com/rwakizaka7/node-js

3. Node.jsでexpressなど使用するライブラリをインストールする。package.jsonにライブラリの設定があります。

```コマンド:チェックアウト方法
$ cd [チェックアウト先フォルダ]
$ git clone https://github.com/rwakizaka7/node-js
```

```コマンド:Node.jsでライブラリインストール
$ cd node-js
$ npm install package.json
```

### 実行方法

1. node-js/htmlにブラウザからアクセスするHTMLを入れます。
2. HTTPサーバーを起動します。
3. http://localhost:3000 にアクセスし、ブラウザの内容を表示します。

```コマンド:HTTPサーバーの起動
$ node html-loader.js
```

### 使い方

1. Javascriptでゲームを作成するphaser3のチュートリアルを入れてみました。
![スクリーンショット 2021-12-08 13.23.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1545849/fdc224f3-7c7d-af82-ec23-84c7bb1e0ad3.png)

2. ブラウザからファイルをたどれます。
3. Javascriptゲームの実行
![スクリーンショット 2021-12-08 13.23.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1545849/21bd964f-fbd6-e081-44f1-7a21ed27d0d0.png)

![スクリーンショット 2021-12-08 13.23.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1545849/ccb97744-2f80-1865-5008-7ed304e681ea.png)

![スクリーンショット 2021-12-08 13.23.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1545849/e440aa95-5bdc-7d0a-f632-69e1b333d3af.png)

### ソースコード

```javascript:node-js/html-loader.js
const express = require('express')
const os = require('os')
const fs = require('fs')
const ejs = require('ejs')
const app = express()
const scheme = 'http://'
const domain = getLocalIpAddress()
const port = 3000
const baseUrl = scheme + domain + ':' + port

const htmlFolderPath = '/html'
const indexTemplatePath = '.' + htmlFolderPath + '/index.html'

app.all(/^\/.+$/, express.static(__dirname + htmlFolderPath))

app.all(/\/$/, (req, res) => {
    const path = req.url.slice(0, -1)
    const top = path == ''
    const accessUrl = baseUrl + path
    const readingPath = '.' + htmlFolderPath + path
    getUrlAndTitleList(top, accessUrl, readingPath, (urlAndTitleList) => {
        const html = ejs.render(fs.readFileSync(indexTemplatePath, 'utf8'), {
            accessUrl: accessUrl,
            readingPath: readingPath,
            urlAndTitleList: urlAndTitleList
        })
        res.send(html)
    })
})

app.listen(port, () => {
    console.log('html-loader')
    console.log('Refer to ' + baseUrl)
    console.log('Ends in [control + C]')
})

function getLocalIpAddress() {
    var nis = os.networkInterfaces()
    nis = Object.keys(nis)
    .flatMap((key) => nis[key])
    .filter((ni) => ni.family == 'IPv4' && !ni.internal)
    
    var address
    if (nis.length > 0) {
        address = nis[0].address
    }
    
    return address
}

function getUrlAndTitleList(top, accessUrl, readingPath, complete) {
    fs.readdir(readingPath, (err, fileList) => {
        function createUrlAndTitleList(file) {
            return {href: accessUrl + '/' + file, title: file}
        }
        
        var _fileList = []
        
        if (!top) {
            _fileList.push('..')
        }
        
        if (fileList) {
            _fileList = _fileList.concat(fileList)
            _fileList = _fileList
            .filter((file) =>
                    indexTemplatePath != readingPath + "/" + file
                    && (file == '..'
                    || file.match(/^(?!\.).*$/)))
        }
        
        let urlAndTitleList = _fileList
        .map((file) => createUrlAndTitleList(file))
        
        complete(urlAndTitleList)
    })
}
```

```html:node-js/html/index.html
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <title>html-loader</title>
    <style type="text/css">
        body {
            font-family: 'Alegreya Sans SC', sans-serif;
            font-size: 13px;
        }
        hr.style1 {
            border-top: 2px dashed blue;
        }
    </style>
</head>
<body>
URLアクセス = <%=accessUrl%><br/>
アクセスフォルダ = <%=readingPath%><br/>
<hr class="style1"/>
<%
    const list = urlAndTitleList
    for(var i in list) {
%>
<a href="<%=list[i].href%>"><%=list[i].title%></a><br/>
<% } %>
</body>
</html>
```