タグ別アーカイブ: Node.js

サーバーレスアーキテクチャを手を動かして理解する

皆さん、こんにちは。
最近、アウトプットすることの大切さを実感している中野です。

さて、今回はサーバーレスアーキテクチャでWebアプリを開発することになったものの、巷のフレームワークに従った開発に慣れてしまい、静的・動的ってなんだっけ?サーバーレスはどう理解すればいいんだっけ?と思っているエンジニアの方向けの内容です。

静的・動的、サーバーレスを理解するために問題を出します。
手を動かしてみて、頭をスッキリ整理させましょう。

問題をシンプルにして原理を理解することに焦点をあてたいため、AWS LamudaやAzure Functions等の技術には一切タッチしませんので、ご了承下さい。

事前準備

まず、Node.js及びExpressをインストールして下さい。
ワークフォルダに以下のソースを配置して下さい。
・server.js

var express = require('express');
var app = express();

app.use(express.static('public'));

app.get('/', function (req, res) {
  res.send('this is root');
})

app.listen(3000);

また、ワークフォルダ配下にフォルダ「public」を作成し以下を配置して下さい。

・input.html

<!DOCTYPE html>
<HTML>
    <head>
        <meta charset="UTF-8">
        <title>入力画面</title>
        <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" rel="stylesheet">
        <script type="text/javascript" src="/input_script.js"></script>
    </head>
    <body>
        
        <div class="container">
            <h1>入力画面</h1>
            <div class="form-group">
                <label class="control-label">苗字</label>
                <input class="form-control" name="first-name" id="first-name-id" type="text">
            </div>
            <div class="form-group">
                <label class="control-label">名前</label>
                <input class="form-control" name="last-name" id="last-name-id" type="text">
            </div>       
            <input type="button" class="btn-lg btn-default" value="確認" onClick="">
        </div>

    </body>
</HTML>

・confirm.html

<!DOCTYPE html>
<HTML>
    <head>
        <meta charset="UTF-8">
        <title>確認・登録画面</title>
        <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" rel="stylesheet">
        <script type="text/javascript" src="/confirm_script.js"></script>
    </head>
    <body>

        <div class="container">
            <h1>確認・登録画面</h1>
            <div class="form-group">
                <label class="control-label">苗字</label>
                <input class="form-control" name="first-name" id="first-name-id" type="text" disabled>
            </div>
            <div class="form-group">
                <label class="control-label">名前</label>
                <input class="form-control" name="last-name" id="last-name-id" type="text" disabled>
            </div>       
            <input type="button" class="btn-lg btn-primary" value="登録" onClick="">
        </div>

    </body>
</HTML>

・input_script.js

window.onload = function () { 
}

・confirm_script.js

window.onload = function () { 
}

以上を用意したところで、サーバーを起動しましょう。

node server.js

ブラウザでlocalhost:3000にアクセスして、this is root と表示されれば成功です。
また、localhost:3000/input.htmlとlocalhost:3000/confirm.htmlも表示されることを確認して下さい。

問題

問題を解く前に、静的・動的の違いを認識しましょう。
サーバーレスの枠組みでは、
静的サイトは、静的ファイル(HTML、JavaScript、CSS)のみで表示されるWebサイトのこと、になります。
動的サイトは、サーバサイドで動的にHTMLを作成して返してくる機能により実現されるWebサイトのこと、になります。
サーバーサイドには、画面に動的な変化をさせるための機能がない状態を、サーバーレスと言っています。

では、この状態で、画面の動きがあるWebアプリを作らなければならないとなると、どうすればいいでしょうか?
この課題に対し、初めの画面で入力を行い、次の画面で入力内容の確認をして登録するという会員登録等でよくあるパターンを題材としました。
ポイントとなるのは、入力画面で入力した値をどうやったら確認画面に引き継げるのか、です。

[問題1]クライアントサイドでデータを保持することで、入力内容の引き継ぎを実現しなさい。
注意点としては、サーバサイドのソース(server.js)の変更は一切行わないで下さい。

[問題2]サーバサイドでデータを保持することで、入力内容の引き継ぎを実現しなさい。
注意点としては、HTMLファイルを別の拡張子に変更してはいけません。また、本来、HTMLを公開するためのWebサーバと、クライアント側に動的な情報を提供するWebAPIは異なる仕組みのものですが、問題を解く上では、同じWebサーバに存在する状態とする(server.jsに追加する)とご理解ください。

解答

[問題1]
どうでしょう?できましたか?
手段は様々考えられますが、やるべきことはブラウザの機能を使って入力内容を保存、読み出しすることです。
私は、localStorageを使って実現しました。Cookie等を使ってもいいと思います。

・input.html

…
<input type="button" class="btn-lg btn-default" value="確認" onClick="link_confirm()">
…

・input_script.js

window.onload = function () { 
    localStorage.clear();
}

function link_confirm() {
    save_input();
    location.href='/confirm.html';
}

function save_input() {
    localStorage.clear();
    var first_name = document.getElementById("first-name-id").value;
    localStorage.setItem("first-name",first_name);
    var last_name = document.getElementById("last-name-id").value;
    localStorage.setItem("last-name",last_name);
}

・confirm_script.js

window.onload = function () { 
    load_input();
}

function load_input() {
    var first_name = localStorage.getItem("first-name");
    if(first_name){
        document.getElementById("first-name-id").value = first_name;
    }
    var last_name = localStorage.getItem("last-name");
    if(last_name){
        document.getElementById("last-name-id").value = last_name;
    }
}

[問題2]
こちらもかなり自由度が高いので、解は様々になったと思います。
ですが、やるべきことはサーバサイドに入力内容を保存・読み出しできるWebAPIを用意してあげること、クライアント側からそれらを適切なタイミングで呼び出すことです。
私は、サーバサイドにはmemory-cacheというライブラリを追加して、キャッシュするようにしました。Session機能等を使ってもいいと思います。

・server.js

var express = require('express');
var cache = require('memory-cache');
var app = express();

app.use(express.static('public'));

app.get('/', function (req, res) {
  res.send('this is root');
})

app.get('/confirm', function (req, res) {
  cache.put('first-name', req.query['first-name']);
  cache.put('last-name', req.query['last-name']);
  res.send();
})

app.get('/input', function (req, res) {
  var first_name = cache.get('first-name');
  var last_name = cache.get('last-name');
  var param = {
    "first-name":first_name ,
    "last-name":last_name
  };
  res.header('Content-Type', 'application/json; charset=utf-8');
  res.send(param);
})

app.listen(3000);

・input.html

…
<input type="button" class="btn-lg btn-default" value="確認" onClick="fetch_input()">
…

・input_script.js

function fetch_input() {
    var first_name = document.getElementById("first-name-id").value;
    var last_name = document.getElementById("last-name-id").value;
    fetch('/confirm?first-name='+first_name+'&'+'last-name='+last_name)
    .then(function(response) {
        location.href='/confirm.html';
    })
}

・confirm_script.js

window.onload = function () { 
    fetch_input();
}
function fetch_input() {
    fetch('/input')
    .then(function(response) {
        response.json().then(function(json) {
            var first_name = json['first-name'];
            if(first_name){
                document.getElementById("first-name-id").value = first_name;
            }
            var last_name = json['last-name'];
            if(last_name){
                document.getElementById("last-name-id").value = last_name;
            }
        });
    })
}

さて、理解は進みましたでしょうか?実際にPGMを書いてみて、こっちの方がいいよ!という方がいらっしゃいましたらご連絡ください。掲載させて頂きたく思います。

サーバーレス自体の概念は、それぞれの機能の最適化を図っていった結果だとみていますが、システムの規模や実現したいことによっても、動的・静的のいずれを採用すべきかが変わってくると思います。それでは今回はこの辺で!