Corredor

ウェブ、プログラミングの勉強メモ。

Angular アプリを GitHub Pages に公開する際、ルーティングによる 404 を回避する

GitHubツールビルディング ―GitHub APIを活用したワークフローの拡張とカスタマイズ

GitHubツールビルディング ―GitHub APIを活用したワークフローの拡張とカスタマイズ

Angular に限らずだが、最近の SPA ライブラリでルーティングを使用していると、実際には HTML ページが存在しない /hoge/fuga/ といった URL を生成し、画面遷移を実現しているだろう。

こうした SPA アプリを GitHub Pages に公開した場合、最初は必ず /index.html を踏んでもらう必要があるが、ルーティングで生成した URL をブックマークされたりすると、ページが存在しない URL に飛んでしまい、404 エラーになってしまう。

コレを回避するための方法が紹介されていたので、拙作の Angular Utilities に取り入れてみた。

独自の 404 ページを用意する

404 エラーを回避するためには、独自の 404 ページを用意し、ココから index.html に遷移させてやれば良い

GitHub Pages はルートディレクトリに 404.html があるとそれを独自の 404 ページとして自動的に利用してくれるので、コレにリダイレクトの meta 要素を書こう。

<meta http-equiv="refresh" content="0;URL=./">

後はこの 404.html を GitHub Pages にアップしてやれば良いだけ。簡単だ。

ただ、IE は独自に用意した 404 ページの容量が 512 バイトを超えると上手く動かないようなので、404 ページは最低限の実装にしておこう。

拙作の 404 ページの実装は以下のとおり。

踏まれた URL に遷移させ直すには

このリダイレクトだけだと、踏まれた URL に戻ってくれず、必ずアプリのトップページが開くような作りになってしまう。

そこで、404.html で踏まれた URL を SessionStorage に記録しておき、アプリの初期処理でその SessionStorage に記録されている URL を基に初期表示するページを選定してやる。

<script>
  // location.href を SessionStorage に記録しておく
  sessionStorage.redirect = location.href;
</script>
<meta http-equiv="refresh" content="0;URL=./">

アプリの初期処理の中で、sessionStorage.redirect の値を基に、表示したいページを選んでやれば良い、という寸法。

Angular の Guard によるページ遷移制限をかけていたり、ログインページを用意していたりする場合は、踏まれた URL ごとに適切にハンドリングしてやろう。


単純な発想だが、404 ページを利用する方法が思い付かず、目から鱗だった。

参考

insertAdjacentHTML を今更知った

インクルーシブHTML+CSS & JavaScript 多様なユーザーニーズに応えるフロントエンドデザインパターン

インクルーシブHTML+CSS & JavaScript 多様なユーザーニーズに応えるフロントエンドデザインパターン

  • 作者: Heydon Pickering,太田良典,伊原力也,株式会社Bスプラウト
  • 出版社/メーカー: ボーンデジタル
  • 発売日: 2017/11/04
  • メディア: 単行本(ソフトカバー)
  • この商品を含むブログを見る

innerHTML += とか jQuery.append() とかやらなくていいのか…。

insertAdjacentHTML は、指定した要素の innerHTML を壊すことなく、要素の前後に別の要素を挿入できるネイティブの API。恥ずかしながら最近まで知らなかったが、「Can I Use」を見るとだいぶ前から使えたみたい。

サンプルコード

まずは以下のような div#target がある前提。

<div id="target">
  <p>Text</p>
</div>

次に、以下のように JavaScript コードを書く。

document.querySelector('#target').insertAdjacentHTML('afterbegin', '<p>Child text</p>');

すると、結果は以下のような HTML になる。

<div id="target">
  <p>Child text</p>
  <p>Text</p>
</div>

この時、元からあった <p>Text</p> にイベントを定義していたりした時に、そのイベント定義が消えたりしないところがミソ。

挿入場所の指定

要素を挿入できる場所は4ヶ所ある。第1引数に文字列で指定する。

<!-- 'beforebegin' -->
<element>
  <!-- 'afterbegin' -->
  <child>Text</child>
  <!-- 'beforeend' -->
</element>
<!-- 'afterend' -->

ウ~ンコレはベンリ!!

参考

はてなブログに「目次記法」があることにいまさら気付いた

はてなブログカスタマイズガイド―HTML & CSSで「はてなブログ」を次のステッ

はてなブログカスタマイズガイド―HTML & CSSで「はてなブログ」を次のステッ

WordPress で作られたブログには、よく「目次」のリンクがあり、コレが便利だなーと思っていたのだけど、はてなブログにも「目次記法」というモノがあり、コレで目次を自動生成してくれることを最近知った。

よく見たら記事編集画面のツールバーに生成ボタンあるじゃん…。

↑コレが目次記法で作った目次。

公式の解説記事

「はてなブログ開発ブログ」に、この目次記法の紹介記事があった。

目次のインデントも可能

目次は見出しのレベルに応じて自動的にインデントされる。

自分のブログだと Markdown 記法を使っていて、トップレベルの見出しは「#」、つまり h1 要素で作成している。そして先程の「目次のインデントも可能」という見出しは「## = h2 要素」で作成した。コレも目次記法の中では正しくインデントされているであろう。

目次記法の配置方法

目次方法を配置するには、以下のように書くだけ。

[:contents]

これで、ul.table-of-contents が生成され、見出しに応じたリストが生成される。

目次記法のデザイン

通常だと、単なる ul 要素でレイアウトされ、「目次」みたいな見出しも付かない。逆に「目次」という文字を見出しレベルで書いてしまうと、コレも目次記法のリストの中に書かれてしまう。

そこで、CSS でデザインを整えつつ、「目次」という小見出しを入れてみようと思う。

/* 目次記法 */
.table-of-contents {
  display: inline-block;
  margin: 1em 0 !important;
  padding: 1em 1.5em 1em 2em !important;
  border: 1px solid #ccc;
  background: #f3f3f3;
}

/* 目次記法の小見出しを作る */
.table-of-contents:before {
  display: block;
  content: "目次";
  margin-bottom: 1em;
  font-weight: bold;
  text-align: center;
}

このサイトで付けている CSS はこんな感じ。ul.table-of-contentsdisplay: inline-block を付けて、border が幅いっぱいに付かないようにしてやると、WordPress でもよく見る目次記法っぽくなる。

あとは :before 疑似要素で「目次」というテキストを入れてやれば OK。

以上

JavaScript を組み合わせれば目次リストの開閉もできそうだが、とりあえず今はいいかな。