一覧CL-15-1 · Cloudflareでの静的教材配信

静的サイトのURLとファイル配信

各教材の直接URL、共有アセット、404、配信設定をファイルに対応付け、前の教材を開かなくても開始できる構成を確認します。

説明

静的サイトでは、あらかじめ作ったHTML・JavaScript・データファイルを配信します。利用者ごとにHTMLを生成するサーバー処理がなくても、ブラウザ内のJavaScriptで操作できます。URLからどのファイルへ届くかを確認することが、独立した教材の入口を作る基本になります。

教材aとb、一覧、共有JavaScript、404ページを持つ小さな成果物を調べます。ローカルHTTPで各URLを直接取得し、Cloudflare Pages向けのヘッダー設定ファイルも読みます。ここで確認するHTTP応答はPythonの静的サーバーによるものです。

各教材の直接URL、共有アセット、404、配信設定をファイルに対応付け、前の教材を開かなくても開始できる構成を確認します。

1成果物を一覧にする

siteが配信するディレクトリです。ソースコードの置場と、ブラウザへ渡す成果物の範囲を分けて確認します。

python3 -c配信ディレクトリ内のファイルを列挙する 'from pathlib import Path; print("\n".join(str(p.relative_to("site")) for p in sorted(Path("site").rglob("*")) if p.is_file()))'

教材ごとのindex.html、共有assets、404.html、データ、_headersがあります。これらはファイルとして保存されています。

2一覧のリンクを読む

一覧は教材への入口です。target=_blankで各教材を新しいタブに開きます。

cat site/index.htmlホームの教材リンクを読む

aとbのURLへ直接リンクしています。教材内部の進捗を使ってリンク先を決める構成ではありません。

3aのURLへ直接アクセスする

static.pyは一時的なloopbackサーバーを起動してURLを取得し、statusと本文を表示します。

python3 static.py /learn/a/aの直接URLをHTTPで取得する

200とaのHTMLが返ります。HTML自身に学ぶ内容の説明と共有JavaScriptの参照があるため、ホームを経由しなくても入口になります。

4bも別の入口から開始する

同じ方法でbを取得します。aの状態や履歴は渡しません。

python3 static.py /learn/b/bの直接URLをHTTPで取得する

bの説明と同じ共有アセット参照が返ります。画面の共通処理は共有しても、教材の内容と開始状態は独立させられます。

5参照されたJavaScriptを取得する

HTMLが参照する絶対パス/assets/lab.v1.jsを取得します。入れ子のURLでも同じ場所を指します。

python3 static.py /assets/lab.v1.jsHTML内の参照先をHTTPで取得する

応答の本文は#stateをreadyへ変えるJavaScriptです。HTML取得と、HTMLが参照するアセットの取得は別の要求です。

6存在しない教材の応答

存在しないパスでは404のstatusと案内用HTMLを返します。

python3 static.py /learn/missing/存在しないURLのstatusと本文を読む

404と「指定した教材は見つかりません」が返ります。案内文だけでなくstatusも確認します。Cloudflare Pagesでは404.htmlの有無がフォールバックの挙動にも関係します。

7配信設定を読む

_headersはCloudflare Pages向けの設定ファイルです。教材HTMLは再検証し、版を名前に含めたassetsは長く保存する設定例です。

cat site/_headersパスごとのCache-Control設定を読む cat site/data.json教材を識別する静的データを読む

/learn/*と/assets/*で指定が異なります。設定ファイルを読んだことと、配置先がその設定を反映したことは別なので、配置時にはHTTPヘッダーを確認します。

まとめ

HTMLと参照アセットは別々のHTTP要求で取得されます。

直接URLに必要な説明と初期状態を含めると、教材を独立して開始できます。

404の本文とstatus、配信設定と実際の応答をそれぞれ確認します。

操作履歴と解説を振り返れます。

Python HTTP server / 静的ファイル

1
python3 -c 'from pathlib import Path; print("\n".join(str(p.relative_to("site")) for p in sorted(Path("site").rglob("*")) if p.is_file()))'
404.html
_headers
assets/lab.v1.js
assets/lab.v2.js
data.json
index.html
learn/a/index.html
learn/b/index.html
2
cat site/index.html
<!doctype html><html lang="ja"><meta charset="utf-8"><title>教材一覧</title><details open><summary>数の表現</summary><a href="/learn/a/" target="_blank" rel="noopener">整数の範囲</a><br><a href="/learn/b/" target="_blank" rel="noopener">文字のバイト数</a></details></html>
3
python3 static.py /learn/a/
status=200 content_type=text/html
<!doctype html><html lang="ja"><meta charset="utf-8"><title>整数の範囲</title><h1>整数の範囲</h1><p>8ビットで表せる符号なし整数の範囲を確認します。</p><pre id="state"></pre><script src="/assets/lab.v1.js" defer></script></html>
4
python3 static.py /learn/b/
status=200 content_type=text/html
<!doctype html><html lang="ja"><meta charset="utf-8"><title>文字のバイト数</title><h1>文字のバイト数</h1><p>UTF-8で文字を保存するときのバイト数を確認します。</p><pre id="state"></pre><script src="/assets/lab.v1.js" defer></script></html>
5
python3 static.py /assets/lab.v1.js
status=200 content_type=text/javascript
document.querySelector('#state').textContent = 'ready';
6
python3 static.py /learn/missing/
status=404 content_type=text/html; charset=utf-8
<!doctype html><html lang="ja"><meta charset="utf-8"><title>見つかりません</title><h1>指定した教材は見つかりません</h1></html>
7
cat site/_headers cat site/data.json
/learn/*
  Cache-Control: no-cache
/assets/*
  Cache-Control: public, max-age=31536000, immutable
{"modules":[{"id":"a","title":"整数の範囲"},{"id":"b","title":"文字のバイト数"}]}

演習完了