Tech Blog

Vite で Handlebars を 使用してHTMLファイルにデータを流し込む

Vite で Handlebars を 使用してHTMLファイルにデータを渡す方法を説明しています。

任意のディレクトリでViteのインストールとViteのプラグインとして提供されているhandlebarsをインストールします。


$ npm init
$ npm install vite --save-dev
$ npm install vite-plugin-handlebars --save-dev

最終的なディレクトリ構成は以下になります。
.
├──index.html
├──src/data/pages/index.js
├──main.js
├──package-lock.json
├──package.json
├──vite.config.js
├──node_modules

package.jsonのscriptsプロパティにvite コマンドを設定しておきます。
またあとで、ダイナミックインポートを使用するため "type": "module" を追記します。


{
  "name": "project",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "type": "module",
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "vite": "^4.5.0",
    "vite-plugin-handlebars": "^1.6.0"
  }
}

vite.config.jsに直接データを記述する方法で出力してみます

htmlでは渡ってきた変数を出力する箇所に{{変数名}}で展開します。


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{{title}}</title>
</head>
<body>
  {{body}}
  <script type="module" src="/main.js"></script>
</body>
</html>

vite.config.jsにhtmlに渡すデータを直接記述してみます。


import { defineConfig  } from "vite";
import handlebars from "vite-plugin-handlebars";

export default defineConfig({
    plugins: [
        handlebars({
            context: {
                title: "Vite + Handlebars",
                body: "This is the body"
        }),
    ]
})

ここまででhtmlファイルに変数が展開されて表示されます。
npm run dev もしくは npm run build で確認することができます。

データをvite.config.jsに直接書くのではなく別ファイルにする

現状だとトップページにあたるindex.htmlファイルのみなので恩恵がありませんが、データファイルを置いてある構造とhtmlの構造を同じにすることでそれぞれのhtmlファイルに対応したデータファイルを自動で読み込むようにします。ダイナミックインポートで読み込むため、package.jsonに"type": "module"が必要になります。分割代入を使用してdefaultの値をdataに入れて渡すようにします。

vite.config.jsに記述していた内容をindex.jsに外部化して別ディレクトリ(/src/data/pages/index.js)に配置します。


export default {
    title: "Vite + Handlebars",
    body: "This is the body",
}


export default defineConfig({
    plugins: [
        handlebars({
            context: async (pagePath) => {
                const dataPagePath = `./src/data/pages${pagePath.replace('.html', '')}.js`;
                try{
                    const  { default: data } = await import(dataPagePath);
                    return data;
                }catch(err){
                    console.log(err);
                }
            }
        }),
    ]
})

参考)ダイナミックインポートについて
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/import