フレームワークを使わない静的サイトの作り方

こんにちは。今回は静的サイトの作り方について書いてみます。

フリー張り紙素材 はりがみやも静的サイトで、基本的にはこの記事と同じようなやり方で作られています。

 

【注意】

これを書いている人は趣味レベルな上、「なんだかわからんが動いたからヨシ!」という人間です。ベストプラクティスとは程遠い内容かもしれません。

とはいえ「ちゃんとやる」「完璧にやる」といろいろとハードルが高いですし。

とりあえず動かしてみたい、作ってみたいという方に読んでいただければ。

 

 

想定している読者

  • 職業プログラマーではない
  • WEBデザイナーでもない
  • 自分で作った渾身のWEBサイトを公開したい
  • ブログサービスでは満足できない
  • サーバーの運用はしたくない。コンテンツに集中したい。
  • HTMLチョットワカル
  • PHPチョットワカル or コレカラベンキョウスル

このような方向けの記事となります。

上記条件だと、

  • 静的なWEBサイトを
  • サーバーレスアーキテクチャで公開する

これが、ゴールのひとつになるはず。

 

前書き

静的サイトとは?

簡単に言うと

  • htmlファイル
  • CSSファイル
  • 画像ファイル

これだけで構成されたWEBサイトですね。JavaScriptも含まれますが、基本としては上記3つ。

そして、このファイル達をWEBサーバーにアップロードすれば無事完成・・・なのですが、Apacheやnginx等のWEBサーバーを使う = 運用が発生してしまいます。

そこでクラウドサービス各社が提供しているストレージサービスを利用します。

  • Amazon AWS S3
  • Microsoft Azure Blob Storage
  • Google GCP Cloud Storage

などが有名です。Netlifyなどの静的サイトのホスティングに特化したサービスを使用してもよさそうです。

静的サイトにはこのようなメリットがあります。

  • ページの表示が早い
  • ストレージサービスに置くことでセキュリティリスクがほぼゼロ
  • アクセス急増やサーバー負荷に悩むことがない 

しかし、ユーザーの操作、属性によって画面内容が動的に変わるものには向いていません。ECサイトとか。

素材配布サイトには超向いてます。

 

 

動的サイトとは?

PHPなどのプログラミング言語を使い、データベースにあるデータを呼び出したりして、アクセスされたときに都度、ページを生成して表示するサイトのことです。

事前に全てのHTMLファイルを作る必要がない分、便利なのは間違いなくコッチなのですが、

  • サーバーの運用(セキュリティ対策、アップデート)
  • ソフトウェアの運用(Wordpressなど)
  • 規模に応じたスケールアップ、スケールアウト

などなど面倒が多いです。この辺も苦にならないならよいのですが、たいていの人は「コンテンツを生み出す」ことに注力したいですよね。

動的なサイトもサーバーレスで作れなくもないですが、それはそれで各種サービスへの理解が必要で、大変です。

 

静的サイト作成の流れ

1ページずつHTMLファイルを作ってアップロードする・・・のは現実的ではありません。各ページのヘッダやフッタなど共通部分を変更する時に死にます

なので動的サイトの仕組みを活かします。

  • プログラミング言語を使って、WEBサイトの全ページを生成して
  • 全ファイルをストレージサービスへアップロードする

という流れになります。 

「結局プログラミング言語を使うのならサーバー必要なのでは?」と聞こえてきそうですが、今使っている自分のパソコンで動かせばOKです。

この記事ではPHPを使いますが、Macならもともと入っていますし、Windowsでも簡単にインストールできます。

 

静的サイトジェネレーター

SSG(Static Site Generator 静的サイトジェネレーター)と呼ばれる、静的サイトを作るための仕組み(フレームワーク)が多数公開されています。

ですが、私は使っていません。

  • フレームワークの学習コストがかかる
  • メンテが打ち切られたら乗り換えがめんどい

仕事としてやるなら導入したほうがよいのでしょうけども、趣味のサイトなので。
気になる方はぜひ検討してみてください。ここから先を読む理由も無くなりますが・・・。

本も色々出ているみたいです。 

 

本記事のゴール

「PHPを使ってオレオレ静的サイトジェネレーターを作る」

それでは作っていきましょう。

 

完成イメージ

このようなデザインのサイトを作ってみます。

f:id:trial-and-error:20210508211742j:plain

  • ヘッダー
  • サイドバー
  • フッター
  • メインコンテンツ

よくある構成ですね。

この中で

  • ヘッダー
  • サイドバー
  • フッター

この3つは全ページで共通する部分となります。

 

環境の準備

Macでの解説となってしまいますが、基本的にWindowsでも同じはずです。

PHPが動作するか

$ php -v

WARNING: PHP is not recommended

PHP is included in macOS for compatibility with legacy software.

Future versions of macOS will not include PHP.

PHP 7.3.24-(to be removed in future macOS) (cli) (built: Feb 28 2021 09:53:14) ( NTS )

Copyright (c) 1997-2018 The PHP Group

Zend Engine v3.3.24, Copyright (c) 1998-2018 Zend Technologies

ターミナル(Terminal.app)で、php -v と打って上記のようにでればOKです。
将来的にPHPはデフォルトで入らなくなっちゃうんですね・・・

 

作業フォルダの作成

  • ~/Documents/myssg/source
  • ~/Documents/myssg/public

この2つを作りましょう。
場所はどこでもよいのですが、日本語が含まれたり階層が深いと移動が面倒です。

  • myssgは今回のプロジェクトを保存するため
  • sourceはテンプレートとなるphpファイルを置く場所
  • publicは公開用に生成したHTMLファイルが格納される場所

 

事前の動作確認

publicに下記内容のファイルを置いて、開けるかどうか、想定通りのデザインで表示されるのか確認します。

ファイル名は index.html としてください。

なお、CSSフレームワークとしてBootstrapを使っています。
個人的に気に入っているからですが、別のフレームワークを使っても、使わなくても大丈夫です。

CDN(コンテンツ配信ネットワーク)から読み込んでいるので、ダウンロードして配置することなく使えます。

使い方はこちらのサイトを参考にしています。

v4.bootstrap-guide.com

index.html

<!doctype html>

<html lang="ja">

  <head>

    <title>オレオレ静的サイトジェネレーター</title>

    <!-- 必要なメタタグ -->

    <meta charset="utf-8">

    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- Bootstrap CSS -->

    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css" integrity="sha384-B0vP5xmATw1+K9KRQjQERJvTumQW0nPEzvF6L/Z6nronJ3oUOFUFpCjEUQouq2+l" crossorigin="anonymous">

  </head>

  <body>

  

    <div class="container-fluid">

      <div class="row">

        <div class="col-12 text-center bg-primary border">

          <h1>ヘッダー</h1>

        </div>

      </div>

 

      <div class="row" style="height:400px;">

        <div class="col-3 bg-warning border d-flex align-items-center">

          <h1>サイドバー</h1>

        </div>

        <div class="col-9 bg-success border d-flex align-items-center">

          <h1>メインコンテンツ</h1>

        </div>

      </div>

 

      <div class="row">

        <div class="col-12 text-center bg-info border">

          <h1>フッター</h1>

        </div>

      </div>

 

    </div>

  

    <!-- オプション1:jQueryとBootstrapバンドル版(Popperを含む) -->

    <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>

    <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-Piv4xVNRyMGpqkS2by6br4gNJ7DXjqk09RmUpJ8jgGtD7zP9yug3goQfGII0yAns" crossorigin="anonymous"></script>

 

  </body>

</html>

ファイルを保存して、ダブルクリックして・・・

 

f:id:trial-and-error:20210508215110p:plain

Safariなどのブラウザで、こんな画面が出れば成功です。

 

ファイルの分割 

ヘッダー、サイドバー、フッターは共通部分なのでここを切り出してみます。

  • ヘッダーファイル : template_header.php
  • サイドバーファイル : template_sidebar.php
  • フッターファイル : template_footer.php

コンテンツファイルはこんな名前にしてみました。

  • contents_index.php

「index」の部分が最終的に出力されるhtmlファイル名になります。

この例だと「index.html」が出力されます。

 

ヘッダーファイル : template_header.php

<!doctype html>

<html lang="ja">

  <head>

    <title>オレオレ静的サイトジェネレーター</title>

    <!-- 必要なメタタグ -->

    <meta charset="utf-8">

    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- Bootstrap CSS -->

    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css" integrity="sha384-B0vP5xmATw1+K9KRQjQERJvTumQW0nPEzvF6L/Z6nronJ3oUOFUFpCjEUQouq2+l" crossorigin="anonymous">

  </head>

  <body>

  

    <div class="container-fluid">

      <div class="row">

        <div class="col-12 text-center bg-primary border">

          <h1>ヘッダー</h1>

        </div>

      </div>

 

サイドバーファイル : template_sidebar.php

      <div class="row" style="height:400px;">

        <div class="col-3 bg-warning border d-flex align-items-center">

          <h1>サイドバー</h1>

        </div>

 

フッターファイル : template_footer.php 

      </div>

 

      <div class="row">

        <div class="col-12 text-center bg-info border">

          <h1>フッター</h1>

        </div>

      </div>

 

    </div>

  

    <!-- オプション1:jQueryとBootstrapバンドル版(Popperを含む) -->

    <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>

    <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-Piv4xVNRyMGpqkS2by6br4gNJ7DXjqk09RmUpJ8jgGtD7zP9yug3goQfGII0yAns" crossorigin="anonymous"></script>

 

  </body>

</html>

 

コンテンツファイル : contents_index.php

        <div class="col-9 bg-success border d-flex align-items-center">

          <h1>メインコンテンツ</h1>

        </div>

 

分割の仕方に賛否があるかもしれません。
ここまで終わると以下のようなファイル構成になっているはずです。

$ ls -1 source/

contents_index.php

template_footer.php

template_header.php

template_sidebar.php 

 

生成プログラムの作成

テンプレートとコンテンツが1個出来ましたので、これらを元にhtmlファイルを生成するプログラムを作ります。

ファイル名はbuild.phpにしましょう。sourceフォルダに保存してください。

 

build.php

<?php

 

// contents で始まるファイルを取得する

$filelist = glob('./contents*');

 

// 取得したファイルでループ

foreach($filelist as $filename){

 

  // 中間ファイルとして全ての要素が入ったPHPファイルを生成する

  $contents = <<<EOF

 

    <?php 

    include('./template_header.php');

    include('./template_sidebar.php');

 

    include('./$filename');

 

    include('./template_footer.php');

 

EOF;

 

  // 出力するHTMLファイルの名前に使う部分を抜き出す

  $html_filename = preg_replace('/^.*contents_(.*)\.php/','$1',$filename);

 

  // 一時ファイルの名前を決める

  $temp_file = './_temporary_' . $html_filename . '.php';

 

  // 一時ファイルを書き込む

  file_put_contents($temp_file, $contents);

 

  // 一時ファイルを実行し、標準出力をpublicフォルダに書き込む

  exec('/usr/bin/php ./' . $temp_file . ' > ../public/' . $html_filename . '.html');

 

}

こんな感じでしょうか。適当ですけども。

  1. contents_で始まるファイル一覧を取得
  2. 取得したファイルに対して中間ファイル(テンプレートとコンテンツをincludeしたもの)を生成
  3. 中間ファイルを実行、ファイル出力

このような流れになっています。

 

sourceフォルダに移動した上で、

php build.php

を実行すると、publicフォルダにhtmlファイルが書き出されるはずです。
ブラウザで開いてみてください。事前に確認したのと同じ画面になっていますでしょうか?

 

サンプルなので中間ファイルも同じsourceフォルダに吐き出していますが、別のフォルダにしても良いと思います。

PCで動作確認が出来たらお好きなストレージサービスにアップロードなり、同期なりして公開して完了です。

ストレージサービスへのアップロード方法は色々なサイトで解説されつくしていますので割愛します。

 

コンテンツ(ページ)を増やしたい場合

contents_ファイル名.php

このようなファイル名で増やしていけば、自動的に「ファイル名.html」が出力されます。

コンテンツが増えるとサイドバーのメニューを増やす必要もあるかもしれません。template_sidebar.php内でbuild.phpと似たようなループ処理を追加することで、メニューの増減も自動化出来るかと思います。

 

想定される疑問・質問

テンプレートの中身がHTMLしか無いのに.phpである必要があるの?

今回の作り方では最後までその必要はないです・・・
でも、いずれ各ファイル内でプログラムを書くことになるはずなのでphpとしています。

exec() 使っちゃダメってどっかで聞いた!

公開サーバーで動くPHPプログラムではなく、自分のパソコンで実行するだけなので別にいいかなって。

コンテンツを1ページずつ作るのが面倒

素材配布サイトのように、ページのごく一部しか変わらないページが大量にある場合は

  • 素材リスト(ファイル名や説明)をcsvなどで用意する
  • csvを読み込んでhtmlファイルを生成しまくる

などで対応出来ます。「はりがみや」はこのようにしています。

もちろんデータベースを立ててSQLで取ってきてもよいのですが、個人サイトレベルではExcelやGoogleスプレッドシートが十分にデータベース代わりになるはずです。

 

まとめ

初心者でもできる(かもしれない)、静的サイトの作り方でした。
お役に立てば幸いです。