つぶやき Web拍手を送る

とりあえず触ってみよう

前のページで11tyをインストールできたので、ここからは実際に11tyを動かしてwebページを作ってみましょう。

最初の1ページ

何はともあれ、まずはページを1つ作ってみましょう。
サイトのトップページと想定して、作業用フォルダの直下にindex.htmlというファイルを新規作成します。

vscodeでindex.htmlを作成したところ

次に、今作成したindex.htmlの中に下記のコードを入力して保存しましょう。
といっても、見ての通り何の変哲もないhtmlです。

index.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>Sample Page</title>
</head>
<body>
    <h1>Sample Page</h1>
    <p>11tyでサイトを作るぞ~</p>
</body>
</html>

ここまで出来たら、ターミナルでコマンドnpx @11ty/eleventy を実行します。するとターミナルに何やら表示されて……

コマンドを実行すると白い行と緑の行が表示される

作業フォルダの中に_siteというフォルダが新しく作成されました!

サイト制作フォルダの直下に「_site」フォルダが作られた(vscodeでの表示)
vscodeでの表示
サイト制作フォルダの直下に「_site」フォルダが作られた(エクスプローラーでの表示)
エクスプローラーでの表示

_siteフォルダの中を見てみると、index.htmlというファイルがあるのが分かります。これをブラウザで開いて見てみましょう。

新しくできた「_site」フォルダの中身

最初に作成したindex.htmlに記述したhtmlの内容が表示されました!

_site/index.htmlをブラウザで表示させた!

やた!

今何が起きていたかというと、コマンドnpx @11ty/eleventy を実行することで

  1. 作業用フォルダ内にあるhtmlファイルを「ページを生成する素材」として読み取り
  2. その内容から公開用のhtmlファイルを_siteフォルダの中に生成する

という動作をしていました。この流れは、今後作業用フォルダ内にページの素材となるファイルが増えていっても同様です。
つまり、最終的にwebサイトを構成するために必要なファイル一式が_siteフォルダ内に生成されるということです。そのため、サイトをインターネット上に公開する時は、この_siteフォルダの中身を丸ごとサーバーのルートにあたる場所(一番上の階層、https://xxxx.xx/に相当するところ)にアップロードすればOKということになります。
今回はいたって普通のhtmlファイルだったため、そのまま_siteフォルダにコピーされただけですが、ここから少しずつ複雑なことをやっていきましょう。

サイトのチェックに便利な機能~ローカルサーバー~

さて、ページの素材となるファイルを編集するたびにコマンドを実行してファイルを生成、ブラウザで生成されたファイルを開いてどうなったか確認……とやるのは面倒ですよね。そんなことをしなくても作成したサイトの動作を簡単に確認できる機能が11tyには備わっています。ここではその機能を試してみましょう。

先ほどはページを生成するためのコマンドとしてnpx @11ty/eleventy を実行しましたが、今度はその末尾に--serveを付けた、以下のコマンドを実行してみてください。

npx @11ty/eleventy --serve

すると、今度は以下のようにhttp://localhost:XXXX/(Xは数字、ほとんどの場合8080)のような表示が出てきたと思います。 --serve無しのコマンドを実行した時と比べて、アドレスの書いてある青い行が増えた

それでは、この状態でここに表示されているアドレスhttp://localhost:XXXX/にブラウザでアクセスしてみましょう。(vscodeであればターミナルに表示されたアドレスをAlt+クリックで開くことができます。)
すると……

ブラウザでhttp://localhost:XXXX/にアクセス、index.htmlと同じ内容が表示された!

最初にindex.htmlをブラウザで開いて確認した時と同じ内容が表示されました。

さて、すごいのはここからです。最初に作った作業フォルダ直下のindex.html(ページの素材となる方)の中身を適当に書き換えて上書き保存してみましょう。今ブラウザで表示させたhttp://localhost:XXXX/はそのまま置いておいて大丈夫です。

index.html
 <!DOCTYPE html>
 <html lang="ja">
 <head>
     <meta charset="UTF-8" />
     <title>Sample Page</title>
 </head>
 <body>
     <h1>Sample Page</h1>
-     <p>11tyでサイトを作るぞ~</p>
+     <p>11tyでサイトを作ったぞ~い</p>
 </body>
 </html>

するとファイルを保存した直後にターミナルにまた何やら表示されて…… ターミナルの青い行の下に行が増えた

ブラウザで表示させていたhttp://localhost:XXXX/の中身が変更内容に合わせて書き換わりました! http://localhost:XXXX/が勝手に書き換わった!

ここで、コマンドnpx @11ty/eleventy --serveを実行することで何が起きていたかを簡単に説明すると……

……と、このような動作をしていました。つまり、最初にコマンドnpx @11ty/eleventy --serveを実行してブラウザでhttp://localhost:XXXX/を表示させておけば、そのあとはファイルを書き換えて保存するたびに勝手に変更内容が反映され、そのページをブラウザ上でチェックできる……という訳です。ファイルを保存するたびに更新ボタンを押さなくてもいいんだって!こりゃいいや!

ところで、このコマンドは一度実行するとこちらが停止させるまでずっとファイルの更新を監視し続けます。停止させたいときはターミナルにカーソルがある状態で 「Ctrl+C」→「y」→「エンターキー」 です。サイト制作の作業を終わるときはこのコマンドで動作を停止させておきましょう。

「Ctrl+C」を押すとターミナルに質問が表示される
「Ctrl+C」を押すとこんな表示が出るので……
質問の後に「y」キーを押してエンター
「y」を入力してエンターを押すと停止します

今後はこのnpx @11ty/eleventy --serve コマンドで変更内容がすぐ確認できる状態にして、いろいろ触っていきましょう。

いちいちコマンド打つの面倒だよ~~~

ところで上記のnpx @11ty/eleventy --serve というコマンド、ちょっと長いですよね?また、コピペで済むといっても毎回毎回コピペ元から貼り付けてくるのも面倒臭くないですか?
……ということで、コマンド入力を楽にする方法をここで紹介します。

使用するのは、サイト制作用フォルダの直下にあるpackage.jsonというファイルです。11tyをインストールしようでコマンドnpm init -yを実行したときに、なんか勝手に生成された奴です。とりあえず中身を見てみましょう。おおむね以下の画像のような感じになっていると思います。

package.jsonの中身

このファイルはサイト制作フォルダ内の設定のようなものです。ここで、画像でいう5行目の"scripts":の後にあるかっこ{}の中に設定を書くと、コマンドに名前を付け、その名前でコマンドを実行できるようになります。
今回は、コマンドnpx @11ty/eleventy --servewatchという名前でまとめてしまおうと思います。そのためには、"scripts":の後にあるかっこ{}に以下のように記述します。
("test"で始まる行は消してしまってもよいですし残しておいてもよいです)

package.json
 // 前略
   "scripts": {
-     "test": "echo \"Error: no test specified\" && exit 1"
+     "test": "echo \"Error: no test specified\" && exit 1",
+    "watch": "npx @11ty/eleventy --serve"
   },
 // 後略

このように書き換えたらpackage.jsonを上書き保存します。 そのうえでターミナルに以下のコマンドを入力して実行すると……

npm run watch

コマンドnpx @11ty/eleventy --serveを実行した時と同じ結果になったと思います。 これなら元のコマンドより短くて覚えやすいし、だいぶ楽になりました。

実は、vscodeならもっと楽にコマンド実行ができるようになっています。上記の通りpackage.jsonを書き換えた後で、今度は左のサイドバーの下の方の 「NPMスクリプト」 という部分をクリックして展開してみましょう。

vscodeの左サイドバーの下の方に「NPMスクリプト」がある

もしも「NPMスクリプト」が表示されていない場合は、左サイドバー上の何か展開できそうな場所(上の画像の「アウトライン」「タイムライン」のような場所)を右クリックすると下の画像のようなメニューが出てくるので、 「Npm スクリプト」 をクリックしてチェックを入れると表示されます。 左サイドバーの「アウトライン」上を右クリックしたところ

「NPMスクリプト」を展開すると、以下のようにpackage.jsonに追記したコマンドが表示されます。ここにマウスカーソルを載せると右側に再生ボタンのようなマークが表示されるので、これをクリックすると登録したコマンドを実行することができます。マウス操作だけでコマンドが実行できてしまいました! package.jsonに登録したコマンドが「NPMスクリプト」の下に表示される!

変数を使ってみよう

普通のhtmlではできないけれどSSGならできることの一つとして、ページ内で変数(のようなもの)を使用することが挙げられます。早速やってみましょう。

まずはindex.htmlの先頭、<!DOCTYPE html>よりも前に次のように追記します。

---
title: Sample Page
---

そして、html内の「Sample Page」の文字列を{{ title }}に置き換えます。今、index.html全体は以下のようになっているはずです。

index.html
 ---
 title: Sample Page
 ---
 
 <!DOCTYPE html>
 <html lang="ja">
 <head>
     <meta charset="UTF-8">
+    <title>{{ title }}</title>
 </head>
 <body>
+    <h1>{{ title }}</h1>
     <p>11tyでサイトを作ったぞ~い</p>
 </body>
 </html>

この状態で生成されたindex.htmlはどのようになるのでしょうか。見てみましょう。

コードを書き換える前と全く同じ表示のindex.html

先ほどまでと同じ状態になりました。

ここで、今書き換えた内容について解説します。
まず、ファイルの先頭に追記した------ で挟まれた塊はフロントマター(Front Matter) と言います。このフロントマター------ の中に様々な記述をすることで、ファイルに対して各種設定を行うことができます。

次に、今フロントマター内に記述したtitle: Sample Pageですが、これは ファイルの持っている 「title」という属性(キー)に「Sample Page」という値を設定する 、という意味です。少し分かりにくいのでもう少し身近な表現に置き換えてみます……
例えば人間が一人いたとして、この人は色々な情報を持っています。名前、誕生日、血液型、好きな食べ物などなど……筆者の場合は「名前:よしむら」「誕生日:2/22」「血液型:新潟」「好きな食べ物:おにぎりと唐揚げ」といった感じです。
この「名前」「誕生日」「血液型」「好きな食べ物」が 属性(キー) に当たり、それに対応する が「よしむら」「2/22」「新潟」「おにぎりと唐揚げ」となります。
ここで人間を先ほどのファイルに置き換えてみると、「名前」「誕生日」などに当たるのが「title」で、「Sample Page」がその属性に対応する値となります。
ということで、title: Sample Pageは「このファイルの『タイトル(title)』は『Sample Page』です」と宣言していると考えればよいでしょう。筆者が「私の『名前』は『よしむら』です」と言っているようなものです。

このフロントマター内の設定は 「YAML」 という文法で記述し、属性(キー)の名前: 値という書き方をすることで左側に記述した属性に対してに右側の値を設定する、という意味になります。このとき、コロン(:)の右側に半角スペースを入れるのを忘れないようにしてください。正しく認識してくれなくなります(n敗)。

最後にhtml内に書いた{{ title }} ですが、このように{{属性名}}と記述することで、その属性に設定されている値を呼び出すことができ、html生成時にその値と置き換えてくれます。
そのため、生成結果は今回{{ title }} と記述した部分に属性titleの値であるSample Pageという文字列を当てはめた状態……つまり書き換える前と同じ状態になったという訳です。

ではここで、フロントマター内title: Sample Page の値の部分……:の右側を適当に書き換えてみましょう。例えば下のように書き換えて……

---
title: サンプルページ
---

この状態で上書き保存して、生成されたページを見てみると……

とりあえず触ってみようと書いたところが全て「サンプルページ」に書き換わったindex.html

{{ title }} と記述した部分が書き換わりました!今回は<title></title><h1></h1>の中身を置き換えたので、本文内のh1タグだけでなくタブに表示されるタイトルもちゃんと書き換わっていることを確認してください。

このように、ファイル内の1カ所を書き換えるだけで複数個所の内容を変更することができるようになります。

ちなみに

今の属性を{{属性名}} と書いて呼び出す書き方は、 「Liquid」 と言われるテンプレート言語……htmlに変数や条件分岐、繰り返し処理などのプログラミング的な機能を組み込める言語……の書き方です。実は、11tyは初期設定ではhtmlファイルはLiquidで書かれたものとして処理を行うようになっています(この設定は変更することも可能です)。なので上記のようなことができたんですね~。
フロントマターの書き方やプログラミング的なことを実現するための書き方については、この後の解説内でも必要に応じて説明していく予定ですが、もっと詳しく知りたい!と思ったら 「YAML」 「Liquid」 などのワードで調べてみてください。

画像を使おう~11tyの設定ファイルとpassthroughCopy~

さて、文字だけのページだとちょっと寂しいので、ここらで画像でも貼り付けてみましょう。
いい感じの軍艦島の写真(撮影:筆者)があったのでこれをindex.html<h1><p>の間の部分に貼ることにします。お手元にいい感じの画像があればそちらを使ってもいいですよ。

いい感じの軍艦島の写真
いい感じの軍艦島の写真

作業用フォルダの中に画像を置いておくためのフォルダsrcを作成し、その中に使用する画像をheader.jpgという名前で配置します。

「src」フォルダを作って画像を置いたところ
現在の作業用フォルダ内の構成。画像の拡張子はwebサイトで使えればなんでもおk

今配置した画像ファイルを普通にimgタグで貼り付けてみましょう。

index.html
 <!-- 前略 -->
 <body>
     <h1>{{ title }}</h1>
+    <img src="src/header.jpg">
     <p>11tyでサイトを作ったぞ~い</p>
 </body>
 <!-- 後略 -->

この状態で保存して、生成されたページを確認してみると…… いい感じの軍艦島の写真が表示されていないindex.html あ、あれ???

画像が表示されません。困ったね。
どうしてこうなるのか、一つずつ見ていきましょう。まずは生成されたページのソースを確認してみると

ブラウザのデベロッパーツールでソースを確認
ブラウザのデベロッパーツールでソースを確認

ここは最初の記述通りです。特に変わったことはなさそうです。
ただ、このページは_site フォルダ内に生成されるのでしたよね。ということは、_site フォルダの中の、さらにsrcというフォルダの中に画像がなければ表示されないわけです。今_site フォルダの中はどうなっているのでしょうか?

_siteフォルダ内に画像ファイルがない
ない

……index.htmlしかありませんね。これでは画像が表示されないわけです。
実は11tyの初期設定ではhtmlを生成する素材となるファイルについては処理を行ってくれるのですが、画像や動画、あるいはcssなどのhtml生成に直接関与しない、参照しているだけのファイルについては特に何もしない……という挙動になっています。

とはいえ、このままでは画像が使えなくて困ります……今回はsrcフォルダ内の画像ファイルがそのまま階層構造を保って_siteフォルダ内にコピーされてくれれば問題は解決しそうです。という訳で、そのような動作をしてくれるように11tyの設定を変更しましょう。

このような階層構造になってほしい
こういう構成になってほしい

11tyの設定の変更には、作業用フォルダの直下に.eleventy.jsという名前のファイルを作成し、その中に決まった書き方で設定を書いていく、という方法を取ります。という訳で、まずは.eleventy.jsを作りましょう。

空の.eleventy.jsを作成した画面 .eleventy.js を作りました。まだ中身は空で大丈夫です。

それでは、この中に以下のように記述して保存しましょう。

.eleventy.js
module.exports = function (eleventyConfig) {
    eleventyConfig.addPassthroughCopy("src");
};

基本的に.eleventy.js の中身は、上記のfunction (eleventyConfig)の後の波括弧{} 内に設定する内容を記述していく形式となっています。今回のeleventyConfig.addPassthroughCopy("src");という記述は、括弧()の中のダブルクォーテーションで囲まれた名前のフォルダ(今回はsrc)の中身を、構成はそのまま_siteフォルダの中にまるっとコピーする、という設定です。

それでは、この設定でちゃんと動くのか確かめてみましょう。.eleventy.js を保存したら、npx @11ty/eleventy --serveでローカルサーバーを起動している場合はCtrl+Cで一度終了させて、もう一度npx @11ty/eleventy --serve を実行します。すると…… いい感じの軍艦島の写真が表示されたindex.html

今度はちゃんと画像が表示されました!_site フォルダの中身も期待した通りの構成になっています。

現在の_siteフォルダ内の階層構造

これで画像などの素材も問題なく使えるようになりました!先ほど少し言及しましたが、同じ方法でcssファイルも扱うことができます。ちょっとやってみましょう。 srcフォルダの中にstyle.cssというcssファイルを作って……

srcフォルダ内にstyle.cssを追加したところ

適当に何か書いて……

src/style.css
h1 {
    color: orange;
}

index.html内で今作ったstyle.css を読み込む記述をして保存すると……

 <!-- 前略 -->
 <head>
     <meta charset="UTF-8">
     <title>{{ title }}</title>
+    <link rel="stylesheet" href="src/style.css">
 </head>
 <!-- 後略 -->

スタイルシートが反映されてh1タグの色が変わりました!

スタイルシートが反映されたindex.html

また、この状態でstyle.css の中身を書き換えて上書き保存すると……

src/style.css
 h1 {
+    color: blue;
 }

自動的に変更が反映されました!スタイルシートを編集する時も保存→ブラウザ再読み込みを繰り返さなくていいのは良いですね。 自動で再読み込み・スタイルシートが反映されたところ 自動で再読み込み、反映してくれました

ちなみに

新規でサイトを作っていく際は、今回のように1つのフォルダに対してeleventyConfig.addPassthroughCopy の設定を行い、そのフォルダの中に画像などの素材を全部突っ込んでいくのが一番楽だと思います。この時、設定したフォルダの中にさらにフォルダを作成しても、その構成を保ったままコピーしてくれるので適宜整理しておくとよいでしょう。
また、元々別の方法で構成していたサイトを11tyに移植したいとなった場合は、コピーして欲しいファイルの入ったフォルダが複数あったり、あるいは様々な場所に散らばっていたりするかもしれません。その時は以下のコードを参考にしてください。
さらに詳しく知りたい場合は、公式の解説ページも参照してみてください(全部英語ですが……)。

module.exports = function (eleventyConfig) {
	// 以下のように複数書けば、書いた分のフォルダ全てコピーしてくれます。
	eleventyConfig.addPassthroughCopy("img");
	eleventyConfig.addPassthroughCopy("material");
 // 下記のように書けば作業フォルダ直下にないフォルダも指定可能です。
	eleventyConfig.addPassthroughCopy("css/main");

	//下記のようにワイルドカードを使用すれば、特定の拡張子のファイルすべてをコピーする、ということもできます。(この設定方法ももちろん複数記述できます)
	eleventyConfig.addPassthroughCopy("**/*.jpg");
};

ここまでで、手打ちでできることは11tyでも普通にできるということ、そして11tyだからできることの例として、ローカルサーバーを起動しての生成物の確認やフロントマターによる設定の使用などを見てきました。 そろそろサイトにページが1つだけというのも寂しくなってきたので、次の項目ではページを増やしていろいろやってみましょう。