もはや我々WEBコーダーにとって必需品と言える静的サイトジェネレーター。Dreamweaverから始まったその系譜は静的サイトジェネレーターへと受け継がれた。そのメリットは一部のサーバーサイドCMSすらも駆逐し、すでにデファクトスタンダードとなりつつある。
使っていますか?静的サイトジェネレーター。
私は常に「HUGO」を立ち上げていて、仕事のコーディング、Markdownドキュメントの整理、ブログ等、HTMLが関わる作業は全て静的サイトジェネレーターでこなしています。
静的サイトジェネレーターを使っていなかった時代のことも振り返りながら、個人的に思うメリットを書いていきます。
なぜ静的サイトジェネレーターが必要なのか
HTMLコーディングには2つの壁があります。
- 共通パーツの分割
ヘッダーやフッターなど、全ページにまたがる共通の記述は別ファイルに分割して管理したいですよね。しかしHTMLだけだとそれが実現できないため工夫が必要になります。
- 動的要素の表現
動的要素とは、主にサーバーサイドの処理を指します。HTMLはブラウザで動作するクライアントサイドの言語です。リクエストに対して完全に固定されたレスポンスしか返しません。Wordpressのようにページごとにbody.classを割り当てたり、記事のリンクを作成したり、ページングを行ったりすることはできません。
しかし、静的サイトジェネレーターを使うとHTMLだけで上記の課題を解決することが出来ます。後述しますが、ページングすらもです!
昔は共通パーツのインクルードとかどうしてたんですか?
HTMLコーディングで最初に困るのが、ヘッダーやフッターなどの共通パーツのインクルード。
静的サイトジェネレータでは別パーツに分けながらプレビューしたりデプロイしたりできるのですが、そうじゃなければどの様なアプローチがあるのでしょうか。
iframeを使う
なるほど。却下。
SSIを使う
Server Side Include。
そんなのありましたね。
Options +Includes
こんな風に設定して、
<!--#include virtual="/include/header.html" -->
<div id="content"></div>
<!--#include virtual="/include/footer.html" -->
こんな感じで使うやつですね。
レスポンスはphpのようにインクルードされて返ってきます。
さらにこんな事までできるようです。
<pre>
<!--#exec cmd="ls" -->
</pre>
あ、危なすぎる・・・。
使うのはやめましょう・・・。
javascriptを使う
なるほど。例えばこんな感じでしょうか。
<body>
<div id="head"></div>
<div id="content"></div>
<div id="foot"></div>
<script>
const head = `
<ul>
<li><a href="">メニュー1</a></li>
<li><a href="">メニュー2</a></li>
<li><a href="">メニュー3</a></li>
</ul>`;
document.getElementById("head").innerHTML = head;
</script>
</body>
もっと抽象的に、
<body>
<div id="content"></div>
<script>
// ヘッダー
const head = document.createElement('div');
head.id = 'head';
head.innerHTML = `
<ul>
<li><a href="">メニュー1</a></li>
<li><a href="">メニュー2</a></li>
<li><a href="">メニュー3</a></li>
</ul>`;
// フッター
const foot = document.createElement('div');
foot.id = 'foot';
// ビュー
document.body.insertBefore(head, document.body.firstChild);
document.body.appendChild(foot);
</script>
</body>
なんとか運用できそうですが、前者は結局DOM置いてたり、後者はインクルード位置がDOM相対だったり、HTMLの悪いところが出ていますね。
ファイルとロジックの分割はできそうですが、さらに細かいパーツに分割していくと人間の脳では管理しきれなそうです。(そのために現代ではjsテンプレートエンジンがありますよね)
運用するとしてもこのままではクライアント側の負担が大きいです。非同期でインクルードするとしてもDOMContentLoadedの後にヘッダー・フッターがインクルードされてもねぇ。SEO的にもメリットがないですよね。
jsでのインクルードはサーバサイドで分割する前提でしか使えませんね。
サーバサイド言語を使う
本末転倒です。
Dreamweaverを使う
そ の 手 が あ っ た か !
DreamweaverのTemplate機能って、ほとんど静的サイトジェネレーターですよね。灯台下暗しでした。
というかむしろ、なぜインクルード手段を模索しなくてはならないかと言うと、その動機ってDreamweaverを卒業したいからだったのかもしれません。Sublimeとかでコーディングしたいですもん。
ただやっぱりDreamweaverのテンプレート機能ってレガシーで、更新するたびに数百のファイルに置換が走りますからね、できれば使いたくありませんね。
静的サイトジェネレーターならインクルードは分割管理できますし、プレビューも出来ます。デプロイ時にはインクルードされた状態のHTMLを吐き出すことも出来ます。
ニュースの更新とかどうするんですか?
静的サイトジェネレーターは、時系列で増える連載など動的なコンテンツのナビゲーションも自動で生成します。記事のカテゴリー別・年月別アーカイブや、ページング処理もです!
ですので、Wordpress等のCMSの動作をローカルだけで、静的なHTMLだけでシュミレートできます。サーバも使いません。ファイルの分割単位やアーキテクチャがCMSと同等になりますので、載せ替えや移行が実に楽です!
Javascriptテンプレートエンジンではダメなんですか?
確かにHandlebarsやNunjucksなどで簡単にインクルードが行えます。が、どちらかというと「ショートコード」とか「テンプレート」の類のものです。上記で挙げたようなページングなどは不可能です。HTMLサイトを構築する用途では静的サイトジェネレータに軍配が上がります。
静的サイトジェネレーターで出来ないこと
お問い合わせフォームとかのGET/POSTが絡むページはエミュレートできません。そこはダミーでしのぎます。
また、ブログ用途の場合は複数人での更新には向いていません。素直にログイン型のブログCMSを使いましょう。
静的サイトジェネレータの種類
以下の3つが突出して有名なようです。
(StaticGen調べ)
これに加えてGulpで完結するMetalsmithもオススメです。
個人的にはテンプレートがReactになっているGatsbyも気になっています。
私がオススメする「HUGO」の良いところ
HUGOを使用して半年ほどが経ちました。
今や無くてはならないツールとなっています。
インストールが簡単
MacならHomebrewで一発です。
brew install hugo
WindowsだとChocolateyとかいうCUIアプリでインストールできるみたいです。
choco install hugo -confirm
アナログな僕は、.exeバイナリーを直接配置して、環境変数にpathを通してインストールしています。
バイナリーはこちらでダウンロードできます。
使い方が簡単
新規サイトを作る際は以下を打ち込むだけです。
hugo new site sample-site
新しい記事の作成は以下です。
hugo new post/sample-post.md
こうすると、すぐにエディタが立ち上がり記事を書き始められます。
hugo new post/sample-post.md --editor=code
VScodeが立ち上がり、すぐにMarkdownで記事が書けます。
サイトのビルドは、
hugo
これだけです。
publicフォルダにHTMLサイトが生成されるので、あとは好きにデプロイして下さい。
詳しい使い方は公式サイトを見ていただくか、時間があれば使い方の記事を書くかもしれません。
ライブリロードが爆速
なんとライブリロードしながらプレビューが出来ます。
hugo server -w
http://localhost:1313 でサイトのプレビュー!
爆速ライブリロードで快適コーディング!
HUGOの嫌なところ
シンプルとかいう宣伝文句を目にするのですが、十分に独自過ぎるエコシステムを持っていると思います。「Wordpressで実現しているこの機能はHUGOだとどうやるんだろう?」とググる場面は多いです。
テンプレートの言語がGo言語なのも向かい風です。マジで全然分かりません。ほとんどコピペでしかカスタマイズできていません。Goを勉強するつもりもありません。
私の快適なコーディング環境
- VScode
- HUGO
- gulp-sass
- (場合によってはgulp-babel)
VScodeはなんと言っても、ターミナルウィンドウが便利です。しかも複数のターミナルを起動できます。さらに起動するターミナルもcmd.exeやpowershellやGitBashなど選択できます。
HUGOを起動しながらGulpも起動、時にはWebpackなんかも同時に起動、それでもVScodeだけで完結します。スッキリ!
.scssを.cssにトランスパイルした時だけライブリロードが走るようにできます。gulp-sassのsrcフォルダをHUGOのビルド管理外のフォルダに指定し、エクスポート先をHUGOのstaticフォルダ内にするだけです。これをしないと.scssを保存した時、.cssに変換された時の2回リロードが走ることになります。
一応このサイトのgulpfile.jsを置いておきます。(2017/09/01時点)
'use strict';
var gulp = require('gulp');
var sass = require('gulp-sass');
var autoprefixer = require('gulp-autoprefixer');
var sourcemaps = require('gulp-sourcemaps');
var minifyCss = require('gulp-minify-css');
gulp.task('scss-compile', function() {
return gulp.src('./gulp_src/scss/**/*.scss')
.pipe(sourcemaps.init())
.pipe(sass({
// outputStyle: 'compressed'
}).on('error', sass.logError))
.pipe(autoprefixer({
browsers: ['last 2 version', 'iOS >= 8.1', 'Android >= 4.4'],
cascade: false
}))
.pipe(minifyCss({advanced:false})) // minify
.pipe(sourcemaps.write('../maps'))
.pipe(gulp.dest('./themes/hugo-geo/exampleSite/static/css'));
});
gulp.task('default', function() {
gulp.watch('gulp_src/scss/**/*.scss', {cwd: './'}, ['scss-compile']);
});
最後に
少し前までタスクランナーすら使っていなかった私ですが、
- HTMLはHUGO
- .scssはgulp-sass
- jsビルドはwebpack
これらをVScodeで、という開発環境が肌に馴染んでしまいました。
(PHPとかJAVAはまた別の機会に)
快適な開発環境はストレスフリーな生活への第一歩です。
静的サイトジェネレーターという選択肢を検討してみてはいかがでしょうか。