Webアプリケーションを開発する際の肝になるのがサーバーサイドとの通信でしょう。クライアントサイドにはないデータを扱ったり、セキュリティ上データベースにあるデータにアクセスする際には、クライアント/サーバー間の通信が欠かせません。

しかし、その実装としてAjaxやfetch APIを使うのは面倒です。特に、HTMLテンプレートを使っている場合、サーバーサイドと通信するためにJavaScriptでDOMを操作する必要があります。

そこで紹介したいのがHMPL.jsです。簡易的なサーバーとの通信であれば、JavaScript不要で実装できるライブラリです。

HMPL.jsとは

HMPL.jsはサーバーとの通信を隠蔽してくれる、クライアントサイドで使えるテンプレート言語です。サーバーからはHTMLを返却し、受け取った結果をDOMの中に描画します。

HMPL.js

HMPL.jsの基本

HMPL.jsでは、テンプレートとして .hmpl という拡張子のファイルを利用します。たとえば、以下のような内容です。以下の場合、 GET /api/test というリクエストを投げ、結果を <div /> タグの中に描画します。

<div>
  <div
  >
    {{#request
      src="/api/test"
      method="get"
      interval=1000
      indicators=[
        {
          trigger: "pending",
          content: "<p>Loading...</p>"
        },
        {
          trigger: "rejected",
          content: "<p>Error</p><button>reload</button>"
        }
      ]
      allowedContentTypes=["text/html"]
      disallowedTags=["script", "style", "iframe"]
      sanitize=false
    }}{{/request}}
  </div>
</div>

HMPL.jsの始め方

HMPL.jsは npm ではじめられます。現状(2025年5月現在)だと、テンプレートに少し不具合があるようなので注意してください。

npx degit hmpl-language/hello-hmpl-starter hello-hmpl
cd hello-hmpl
npm install
npm run dev

これで、viteの開発環境が整います。ブラウザからは http://localhost:5173/ にアクセスすれば、HTMLが表示されます。

内容について

最初に表示されるのは src/HelloWorld.hmpl の内容です。内容は上記のテンプレートの通りです。このファイルを main.js で読み込んで表示しています。

import helloWorldTemplate from "./hmpl/HelloWorld.hmpl";

const { response: helloWorld } = helloWorldTemplate();

document.body.appendChild(helloWorld);

viteを使わない場合は、以下のようになります。この場合は、 GET /api/test の結果を、 #wrapper というIDの要素に描画します。

<div id="wrapper"></div>
<script src="https://unpkg.com/json5/dist/index.min.js"></script>
<script src="https://unpkg.com/dompurify/dist/purify.min.js"></script>
<script src="https://unpkg.com/hmpl-js/dist/hmpl.min.js"></script>
<script>
  const templateFn = hmpl.compile(
    `<div>
      {{#request src="http://localhost:5173/api/test"}}{{/request}}
    </div>`
  );

  const wrapper = document.getElementById("wrapper");

  const obj = templateFn();
  wrapper.appendChild(obj.response);
</script>

入力を受け付ける

HTMLフォームから入力を受け付ける例です。 src/Form.hmpl というファイルを作成します。ファイル名は任意です。これは #formsubmit イベントをトリガーにして、 POST /api/hello というAPIを叩きます。 autoBody=true にすることで、フォームの内容を自動的にリクエストボディに追加します。

<div>
  <form id="form" method="post" onsubmit="event.preventDefault()">
    <input type="text" name="name" placeholder="Enter your name" />
    <input type="submit" value="Submit" />
  </form>

  <div>
    {{#request
      src="/api/hello"
      after="submit:#form"
      method="post"
      autoBody=true
      repeat=false
      indicators=[
        {
          trigger: "pending",
          content: "<p>Loading...</p>"
        },
        {
          trigger: "rejected",
          content: "<p>Error!</p>;"
        }
      ]
    }}
    {{/request}}
  </div>
</div>

このファイルを main.js で読み込みます。

import helloWorldTemplate from "./hmpl/HelloWorld.hmpl";
import formTemplate from "./hmpl/Form.hmpl";

const { response: helloWorld } = helloWorldTemplate();
const { response: formEl } = formTemplate();

document.body.appendChild(helloWorld);
document.body.appendChild(formEl);

そして、 mock/api.js を修正します。このファイルは、セットアップ時に生成されるファイルです。 export default でエクスポートされている配列に、APIの情報を追加します。以下のように修正してください。これは POST /api/hello というAPIで、受け取った name を表示したHTMLを返却します。

export default [
  // 以下を追加
    {
        url: "/api/hello",
        method: "post",
        rawResponse: async (req, res) => {
            upload.any()(req, res, () => {
                res.setHeader('Content-Type', 'text/html');
                res.statusCode = 200;
                res.end(<h2>Hello, ${req.body.name}</h2>);
            });
        },
    },
];

繰り返しアクセスする

以下のように interval=1000 を指定してテンプレートを作成すると、1000ミリ秒毎にサーバーへ定期的にアクセスします。

<div>
  <div
  >
    {{#request
      src="/api/test"
      method="get"
      interval=1000
      indicators=[
        {
          trigger: "pending",
          content: "<p>Loading...</p>"
        },
        {
          trigger: "rejected",
          content: "<p>Error</p><button>reload</button>"
        }
      ]
      allowedContentTypes=["text/html"]
      disallowedTags=["script", "style", "iframe"]
      sanitize=false
    }}{{/request}}
  </div>
</div>

以下は1秒毎に、現在時刻を返却するAPIにアクセスしている例です。

Tips

HMPL.jsには専用のVS Code機能拡張があります。これをインストールすると、HMPLのハイライトが有効になります。開発する際にはインストールすると便利です。

HMPL.jsでは、サーバー側はHTMLを返却する必要があります。JSONや、文字列ではうまく動かないので注意してください。たとえば Hello, Monaca! ではなく、 <div>Hello, Monaca!</div> のようにHTMLを返却する必要があります。

まとめ

HMPL.jsは、クライアントとサーバーサイドの連携を手軽に実装できるライブラリです。複雑なWebアプリケーションには向かないかも知れませんが、ちょっとしたデータ取得であれば十分使えそうです。特に、プログラミング初学者であれば便利に使えるでしょう。

HTMLでレスポンスを返さないといけないなど、癖もありますが、便利に使える場面もありそうなので覚えておくと良いでしょう。

HMPL.js