PR

【GAS小技】createHtmlOutputFromFile / createTemplateFromFile 徹底活用 ─ CSS/JS分割と共通ヘッダー・フッターで更新爆速化!

こんにちは、イカPOです。
今回は Google Apps Script(GAS)で Web アプリを作るときに、STEP1|ノンプログラマーでもできる!CSSとJSを別ファイルに分ける を紹介します。ソースを分けておくとコードの見通しがグッと良くなり、あとからデザインやロジックを修正するときも超ラクちん。
さらに、この仕組みを応用すれば ヘッダーやフッターなどの共通パーツをコンポーネント化 できるので、複数ページに散らばる同じ要素を一括で更新できて作業効率が爆上がりします。
覚えておいて損はありません! GAS で Web アプリ/Web サイトを作るときは、ぜひ今回のテクニックを活用してみてくださいね 🦑

CSS と JavaScript を“別ファイル化”する方法

ソースを分けて管理してみよう。

① style.html と script.html をちゃちゃっと作成

style.htmlとscript.htmlを作成

CSSとJavaScriptだけを別のファイルに記述します。
今回はCSS用のstyle.htmlとJS用のscript.htmlの2つを作成します。(※ 原文の “funtion.html” という表記は誤植なので修正しています)
cssは タグ、jsは タグでしっかり囲ってください。
特別な記法はありません。最終的に 1 つの HTML ファイルに CSS と JS をインラインで書き込んだのと同じ形でブラウザに渡るイメージで記述すればOKです。

style.html

<style>
  body { padding: 1rem; }
  /* ───────────  テーブル全体  ─────────── */
  #itemTable {
    --bs-table-striped-bg: #f6faff;   /* 奇数行色 */
    --bs-table-hover-bg:   #edf4ff;   /* ホバー色 */
    border-radius: .5rem;
    overflow: hidden;
    box-shadow: 0 .125rem .75rem rgba(0,0,0,.05);
  }
  /* ───────────  ヘッダー  ─────────── */
  #itemTable thead th {
    background: #0d6efd;
    color: #fff;
    font-weight: 600;
    position: sticky; top: 0; z-index: 2;
  }
  /* ───────────  セルの配置調整  ─────────── */
  #itemTable tbody td:nth-child(1){text-align:center;}
  #itemTable tbody td:nth-child(4){text-align:right;}
  /* ───────────  カテゴリーをバッジ風  ─────────── */
  #itemTable tbody td:nth-child(3){
    font-weight: 500; padding:.35rem .75rem; border-radius:9999px;
    background:#e8f1ff; color:#0d6efd;
  }
</style>

script.html

<script>
  // デモ用:ダミーデータで行を追加
  document.getElementById('addRowBtn').addEventListener('click', () => {
    const tbody = document.querySelector('#itemTable tbody');
    const newRow = tbody.insertRow();
    const idCell = newRow.insertCell();
    const nameCell = newRow.insertCell();
    const categoryCell = newRow.insertCell();
    const stockCell = newRow.insertCell();

    const nextId = 1000 + tbody.rows.length;
    idCell.textContent = nextId;
    nameCell.textContent = 'デモ用品';
    categoryCell.textContent = 'テスト';
    stockCell.textContent = Math.floor(Math.random() * 10) + 1;
  });
</script>

コード解説

  • <style> / <script> タグを使う点は通常の HTML と同じ。
  • GAS ではファイル拡張子が .html であればテンプレートとして読み込めるため、CSS も JS も “HTMLラッパー” に包むのがポイントです。

② コピペOK!include(filename) 関数を用意

今度はコード.gsにinclude関数を作成します。includeは関数の名前なので何でもいいです。

function include(filename) {
  return HtmlService.createHtmlOutputFromFile(filename).getContent();
}

この関数の役割は極めてシンプルです。
指定されたファイルの中身を取得し、HTML として返します。これだけです。
ここで返される HTML はエスケープされずにそのままテンプレートへ差し込まれるため、<style><script> に限らず、共通パーツの <header> なども自在に読み込めます。

コード.gs全文

function doGet(e) {
  const template = HtmlService.createTemplateFromFile('table');
  const htmlOutput = template.evaluate();
  htmlOutput.addMetaTag('viewport', 'width=device-width, initial-scale=1');
  htmlOutput.setTitle('WEBページだよ');
  return htmlOutput;
}

function include(filename) {
  return HtmlService.createHtmlOutputFromFile(filename).getContent();
}

コード解説

  • HtmlService.createTemplateFromFile('table')table.html をテンプレートとして読み込みます。
  • include()GAS テンプレートの中からだけ呼び出せるヘルパー。
  • 返り値は文字列なので、<?!= … ?> タグで “エスケープなし” で展開します。(<?= … ?> との違いに注意!)

doget内でtable.htmlを読み込んでます。htmlの表示方法は別の記事を参考にしてください。

③ include() で CSS/JS をページに注入

include関数を呼び出し、ファイル名を指定しましょう。
今回スタイルとJSを適応させたい、ファイルはtable.htmlなので、table.htmlに以下のコードを追加します。

<?!= include('style') ?>
<?!= include('script') ?>

解説

  • <?!= … ?>テンプレート式の“非エスケープ出力”style.html / script.html の中身をそのまま挿入します。
  • ファイル名は拡張子なしで OK。include('style') と書けば style.html が対象になります。

table.html コード全文

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <base target="_top">
  <meta name="viewport" content="width=device-width, initial-scale=1">

  <!-- Bootstrap 5 CDN -->
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">

  <title>WEBアプリだよ</title>

  <?!= include('style') ?> <!-- GASのテンプレートでCSSを読み込み -->
</head>
<body>
  <h1 class="h4 mb-3">WEBアプリだよ</h1>
  <p class="mb-4">以下のように &lt;table&gt; タグで作成できます。</p>

  <div class="table-responsive">
    <table id="itemTable" class="table table-striped table-hover align-middle">
      <thead class="table-primary">
        <tr><th>商品ID</th><th>商品名</th><th>カテゴリー</th><th>在庫数</th></tr>
      </thead>
      <tbody>
        <tr>
          <td>1001</td>
          <td>シャンプー</td>
          <td>風呂</td>
          <td>1</td>
        </tr>
        <tr>
          <td>1002</td>
          <td>リンス</td>
          <td>風呂</td>
          <td>1</td>
        </tr>
      </tbody>
    </table>
  </div>
  <div class="d-flex gap-2 mt-4">
    <button id="addRowBtn" class="btn btn-primary btn-sm">行を追加</button>
  </div>

  <?!= include('script') ?> <!-- GASのテンプレートでJSを読み込み -->
</body>
</html>

ポイント

  • テーブルに Bootstrap 5 のクラスを当てつつ、細かいデザインを style.html で上書きしています。
  • 行追加ボタンは script.html のハンドラで動的に行を増やします。
完成イメージ図
完成した画面です。CSSでリッチな見た目を作りつつ、JSで簡単なアクションを追加しています。

STEP2|共通ヘッダー&フッターを部品化して更新ラクラク

複数のページで使いまわす、ヘッダーとフッター要素をコンポーネント化することで、編集が楽になります。

① header.html と footer.html を作成

header.html

<!-- header.html  -->
<header class="mb-4">
  <nav class="navbar navbar-expand-lg navbar-dark bg-primary">
    <div class="container-fluid">
      <!-- サイトタイトル/ロゴ -->
      <a class="navbar-brand fw-bold" href="<?= deployURL ?>">イカPOアプリ</a>

      <!-- スマホ用ハンバーガーボタン -->
      <button
        class="navbar-toggler"
        type="button"
        data-bs-toggle="collapse"
        data-bs-target="#navbarNav"
        aria-controls="navbarNav"
        aria-expanded="false"
        aria-label="Toggle navigation">
        <span class="navbar-toggler-icon"></span>
      </button>

      <!-- メニュー -->
      <div class="collapse navbar-collapse" id="navbarNav">
        <ul class="navbar-nav ms-auto gap-lg-2">
          <li class="nav-item">
            <a class="nav-link" href="<?= deployURL ?>">ホーム</a>
          </li>
          <li class="nav-item">
            <a class="nav-link" href="<?= deployURL ?>?page=list">一覧</a>
          </li>
          <li class="nav-item">
            <a class="nav-link" href="<?= deployURL ?>?page=about">このアプリについて</a>
          </li>
        </ul>
      </div>
    </div>
  </nav>
</header>

footer.html

<!-- footer.html -->
<footer class="bg-light text-center py-4 mt-auto shadow-sm">
  <div class="container small text-muted">
    <div class="mb-2">
      <a href="<?= deployURL ?>?page=privacy" class="link-secondary me-3">プライバシーポリシー</a>
      <a href="<?= deployURL ?>?page=contact"  class="link-secondary">お問い合わせ</a>
    </div>
    <div>
      &copy; <script>document.write(new Date().getFullYear())</script> イカPO All&nbsp;Rights&nbsp;Reserved.
    </div>
  </div>
</footer>

header.htmlとfooter.htmlを用意します。

② include() でヘッダー/フッターを読み込み

あとはCSSとjsと同じく

<?!= include('header') ?>
<?!= include('footer') ?>

追加したいところにこのコードを書きましょう。

table.html コード全文 ヘッダーとフッター追加版

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <base target="_top">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <!-- Bootstrap 5 -->
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
  <title>WEBアプリだよ</title>
  <?!= include('style') ?>
</head>
<body>
  <?!= include('header') ?>

  <h1 class="h4 mb-3">WEBアプリだよ</h1>
  <p class="mb-4">以下のように &lt;table&gt; タグで作成できます。</p>

  <div class="table-responsive">
    <table id="itemTable" class="table table-striped table-hover align-middle">
      <thead class="table-primary">
        <tr><th>商品ID</th><th>商品名</th><th>カテゴリー</th><th>在庫数</th></tr>
      </thead>
      <tbody>
        <tr>
          <td>1001</td>
          <td>シャンプー</td>
          <td>風呂</td>
          <td>1</td>
        </tr>
        <tr>
          <td>1002</td>
          <td>リンス</td>
          <td>風呂</td>
          <td>1</td>
        </tr>
      </tbody>
    </table>
  </div>
  <div class="d-flex gap-2 mt-4">
    <button id="addRowBtn" class="btn btn-primary btn-sm">行を追加</button>
  </div>
  <?!= include('footer') ?>
  <?!= include('script') ?>
</body>
</html>

まとめ|これでメンテナンスが爆速に!

ヘルパー関数を作成することで、別ファイルのCSSとJSを呼び出すことができます。
同じ関数を使ってヘッダーやフッターをコンポーネント化して別のページでも使いまわすこともできます。
return HtmlService.createHtmlOutputFromFile(filename).getContent(); の仕組みを使うだけ。便利なテクなので、開発のお供に是非。

それでは、また

タイトルとURLをコピーしました