SlideShare a Scribd company logo
1 of 35
SPA のルーティングの話
NDS Meetup #12
ushiboy
SPA とは
SPA ( Single Page Application )とは
単一の Web ページで構成される Web アプリケーションや Web サイト
デスクトップアプリケーションのような UX を実現する
画面の切り替えは JavaScript による DOM 操作で行う
クライアントサイドで URL に応じた画面を表示(ルーティング)する
SPA ルーティングの方法
2通りの方法がある
Hash
History API
Hash
Hash によるルーティング
URL の Hash (フラグメント識別子)を利用した方法
location.hash
hashchange イベント
http://localhost:8080/path/to#hoge
Hash ( JavaScript でのルートの扱い)
location.hash を使う
遷移先ルートの設定
location.hash = 'hoge';
現在のルートの取得
console.log(location.hash); // -> '#hoge'
(補足) location
http://localhost:8080/path/to?a=1&b=2#hoge
protocol http:
host localhost:8080
hostname localhost
port 8080
origin http://localhost:8080
pathname /path/to
search ?a=1&b=2
hash #hoge
href http://localhost:8080/path/to?a=1&b=2#hoge
Hash ( a タグでの扱い)
a タグでは通常通りに href 属性で定義する
<a href="#hoge">Hoge</a>
<a href="#fuga">Fuga</a>
<a href="#piyo">Piyo</a>
hashchange イベント
Hash が変わった時に発生する
location.hash === '#aaa' の時に location.hash = 'aaa' しても発生しない
イベントリスナーで変更前と変更後の URL が取得できる
window.addEventListener('hashchange', e => {
const { newURL, oldURL } = e;
console.log(newURL); // http://localhost/#test
console.log(oldURL); // http://localhost/
}, false);
ページロード時には発生しない
ブラウザの戻る・進むでは Hash が変われば発生する
Hash でのルーティングの動き
ページロード時
現在のルート( location.hash の値)に応じて画面を表示する
ユーザーの画面遷移操作
location.hash を変更する
hashchange イベント
現在のルート( location.hash の値)に応じて画面を表示する
Hash でのルーティングの特徴
Hash より前の URL の要素(パスとか)は変化しない
http://localhost:8080/path/to#hoge
ブラウザは Hash を HTTP リクエストとしてサーバへ送らない
サーバサイドレンダリングできない
(余談) escaped fragment
Google が過去に出した Hash なルーティングをクロールしてくれる仕組み
現在は Deprecated
「 #! 」みたいな感じでやっていた
https://developers.google.com/webmasters/ajax-crawling/docs/getting-started
History API
History API によるルーティング
History API を利用した方法
location.pathname ( location.search, location.hash )
history.state
history.pushState ( history.replaceState )
popstate イベント
http://localhost:8080/path/to/hoge
History API ( JavaScript でのルートの扱い)
サーバにリクエストが行かないように次のようにする
遷移先ルートの設定
history.pushState(state, title, '/hoge');
現在のルートの取得
console.log(location.pathname); // -> '/hoge'
History API ( a タグでの扱い)
サーバにリクエストが行かないようにクリックのデフォルト挙動を止める
<a href="/hoge">Hoge</a>
function handleClick(e) {
e.preventDefault();
const { href } = e.target;
const state = { /* なんらかの状態 */ };
history.pushState(state, null, href);
}
Array.from(document.querySelectorAll('a')).forEach(el => {
el.addEventListener('click', handleClick, false);
});
popstate イベント
ブラウザの戻る・進むで発生する
history.pushState メソッドを実行したタイミングで起こるわけではない
イベントリスナーで状態が取得できる
window.addEventListener('popstate', e => {
const { state } = e;
console.log(state);
}, false);
ページロード時には発生しない
History API でのルーティングの動き
ページロード時
現在のルート( location.pathname の値)に応じて画面を表示する
history.state から状態を取り出して利用する
ユーザーの画面遷移操作
history.pushState で遷移先ルートを設定する
遷移先ルートの画面を表示する
popstate イベント
現在のルート( location.pathname の値)に応じて画面を表示する
e.state から状態を取り出して利用する
History API でのルーティングの特徴
状態をオブジェクトとして保存できる
同じ origin のパスならどこでも書き換えられる
http://localhost:8080/path/to
サーバ側で rewrite が必要になる
apache -> mod_rewrite
nginx -> rewrite
サーバサイドレンダリングと組み合わせることができる
History API の開発環境
開発用に Web サーバを起動して使っているようなケース
何もしないと URL のパスにアクセスしてしまって 404 になる
historyApiFallback を使う
connect を使っている場合は connect-history-api-fallback をミドルウェアに使う
webpack-dev-server の場合はオプションで有効にする
Hash と History API の比較
Hash History API
難易度 お手軽 いろいろ考慮が必要
サーバサイドの設定 不要 必要
サーバサイドレンダリング できない できる
状態の保持 なし あり
用途 裏画面
Electron アプリ
表画面
URL のルーティング定義
サーバサイドでやってたときと同じ感じ
Hash
一覧画面系だったら #/users
詳細画面系だったら #/users/1
History API
一覧画面系だったら /users
詳細画面系だったら /users/1
ライブラリでの定義フォーマットもサーバサイドと同じ感じ
/users/:id みたいな感じ
まとめ
SPA ではクライアントサイドでルーティングが必要になる
ルーティングの方法は 2 通り
Hash
History API
SPA ルーティングあるある
「 SPA ルーティングあるある」と書きましたが ...
SPA のルーティングでやらかしてきた話
要は失敗談
ブラウザで戻ると壊れる
ブラウザで戻ると壊れる
ルーティング管理外の画面を入れてしまっときに起こる
一覧から選択して詳細に行くやつとか
ツリーを展開していくやつとか
ウィザード的に進んでいくやつとか
一つ前に戻ったつもりが、予想もしていなかった画面に戻る
まったくルーティング入れないとブラウザの新規タブ開いた状態に戻ったりする
⇒ 意識してルーティング管理下に置く
リロードすると壊れる
リロードすると壊れる
状態やパラメータをメモリ中にしか持っていなかった場合に起こる
Ajax でデータ取ってくるためのパラメータがなくて取れないとか
絞り込み条件フォームの入力状態がクリアされてしまうとか
ページネーションのページ番号がリセットされるとか
⇒ 必要に応じてメモリ以外の場所に保持しておく
URL を共有したら壊れる
URL を共有したら壊れる
URL にパラメータが含まれていない場合に起こる
ページネーションのパラメータとか
http://localhost:8080/users?page=10
検索条件のパラメータとか
http://localhost:8080/users?group=developers
⇒ URL (クエリストリングなど)で持つべきものは持っておく
別タブで開けなくなる
別タブで開けなくなる
a タグのクリックイベント制御が雑だと起こる
Ctrl +クリックやミドルクリックとかで別タブで開こうとすると開けない
⇒ 押されているボタンを調べて正しくハンドリングする
el.addEventListener('click', e => {
// button 0:left 1:middle 2:right
if (e.button === 1 || e.shiftKey || e.altKey || e.ctrlKey || e.metaKey) {
return; // skip
}
e.preventDefault();
} , false);
まとめ(反省)
思った以上にブラウザの標準機能は使っている
ブラウザの標準機能を自然に使えるようにする必要がある
開発中も戻る・進むなどの動きをよく確認しておく
状態をどこに・どこまでもたせるかよく考える

More Related Content

What's hot

そんなトランザクションマネージャで大丈夫か?
そんなトランザクションマネージャで大丈夫か?そんなトランザクションマネージャで大丈夫か?
そんなトランザクションマネージャで大丈夫か?
takezoe
 
オブジェクト指向できていますか?
オブジェクト指向できていますか?オブジェクト指向できていますか?
オブジェクト指向できていますか?
Moriharu Ohzu
 
オブジェクト指向エクササイズのススメ
オブジェクト指向エクササイズのススメオブジェクト指向エクササイズのススメ
オブジェクト指向エクササイズのススメ
Yoji Kanno
 

What's hot (20)

SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)
SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)
SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)
 
私にとってのテスト
私にとってのテスト私にとってのテスト
私にとってのテスト
 
Java ORマッパー選定のポイント #jsug
Java ORマッパー選定のポイント #jsugJava ORマッパー選定のポイント #jsug
Java ORマッパー選定のポイント #jsug
 
開発速度が速い #とは(LayerX社内資料)
開発速度が速い #とは(LayerX社内資料)開発速度が速い #とは(LayerX社内資料)
開発速度が速い #とは(LayerX社内資料)
 
Redisの特徴と活用方法について
Redisの特徴と活用方法についてRedisの特徴と活用方法について
Redisの特徴と活用方法について
 
イミュータブルデータモデル(入門編)
イミュータブルデータモデル(入門編)イミュータブルデータモデル(入門編)
イミュータブルデータモデル(入門編)
 
世界一わかりやすいClean Architecture
世界一わかりやすいClean Architecture世界一わかりやすいClean Architecture
世界一わかりやすいClean Architecture
 
導入から 10 年、PHP の trait は滅びるべきなのか その適切な使いどころと弱点、将来について
導入から 10 年、PHP の trait は滅びるべきなのか その適切な使いどころと弱点、将来について導入から 10 年、PHP の trait は滅びるべきなのか その適切な使いどころと弱点、将来について
導入から 10 年、PHP の trait は滅びるべきなのか その適切な使いどころと弱点、将来について
 
Springを何となく使ってる人が抑えるべきポイント
Springを何となく使ってる人が抑えるべきポイントSpringを何となく使ってる人が抑えるべきポイント
Springを何となく使ってる人が抑えるべきポイント
 
そんなトランザクションマネージャで大丈夫か?
そんなトランザクションマネージャで大丈夫か?そんなトランザクションマネージャで大丈夫か?
そんなトランザクションマネージャで大丈夫か?
 
MagicOnion入門
MagicOnion入門MagicOnion入門
MagicOnion入門
 
こわくない Git
こわくない Gitこわくない Git
こわくない Git
 
さくっと理解するSpring bootの仕組み
さくっと理解するSpring bootの仕組みさくっと理解するSpring bootの仕組み
さくっと理解するSpring bootの仕組み
 
Where狙いのキー、order by狙いのキー
Where狙いのキー、order by狙いのキーWhere狙いのキー、order by狙いのキー
Where狙いのキー、order by狙いのキー
 
SPAセキュリティ入門~PHP Conference Japan 2021
SPAセキュリティ入門~PHP Conference Japan 2021SPAセキュリティ入門~PHP Conference Japan 2021
SPAセキュリティ入門~PHP Conference Japan 2021
 
人生がときめくAPIテスト自動化 with Karate
人生がときめくAPIテスト自動化 with Karate人生がときめくAPIテスト自動化 with Karate
人生がときめくAPIテスト自動化 with Karate
 
オブジェクト指向できていますか?
オブジェクト指向できていますか?オブジェクト指向できていますか?
オブジェクト指向できていますか?
 
オブジェクト指向エクササイズのススメ
オブジェクト指向エクササイズのススメオブジェクト指向エクササイズのススメ
オブジェクト指向エクササイズのススメ
 
REST API のコツ
REST API のコツREST API のコツ
REST API のコツ
 
アジャイルにモデリングは必要か
アジャイルにモデリングは必要かアジャイルにモデリングは必要か
アジャイルにモデリングは必要か
 

Similar to SPAのルーティングの話

自作node.jsフレームワークとnginxを使ってラジオサイトを作ってみた
自作node.jsフレームワークとnginxを使ってラジオサイトを作ってみた自作node.jsフレームワークとnginxを使ってラジオサイトを作ってみた
自作node.jsフレームワークとnginxを使ってラジオサイトを作ってみた
Yuki Takei
 
AngularJSでの非同期処理の話
AngularJSでの非同期処理の話AngularJSでの非同期処理の話
AngularJSでの非同期処理の話
Yosuke Onoue
 
Data api workshop at Co-Edo
Data api workshop at Co-EdoData api workshop at Co-Edo
Data api workshop at Co-Edo
Yuji Takayama
 
Go言語で作る webアプリ@gocon 2013 spring
Go言語で作る webアプリ@gocon 2013 springGo言語で作る webアプリ@gocon 2013 spring
Go言語で作る webアプリ@gocon 2013 spring
Takuya Ueda
 
Twitter連携chrome extension作り方
Twitter連携chrome extension作り方Twitter連携chrome extension作り方
Twitter連携chrome extension作り方
Hiroshi Oyamada
 
html5j.orgがHTML5+JavaScriptで Metro Style アプリを作ってみた
html5j.orgがHTML5+JavaScriptで Metro Style アプリを作ってみた html5j.orgがHTML5+JavaScriptで Metro Style アプリを作ってみた
html5j.orgがHTML5+JavaScriptで Metro Style アプリを作ってみた
Shumpei Shiraishi
 

Similar to SPAのルーティングの話 (20)

Pjax1
Pjax1Pjax1
Pjax1
 
後期03
後期03後期03
後期03
 
densan2014-late01
densan2014-late01densan2014-late01
densan2014-late01
 
HTML5 on ASP.NET
HTML5 on ASP.NETHTML5 on ASP.NET
HTML5 on ASP.NET
 
自作node.jsフレームワークとnginxを使ってラジオサイトを作ってみた
自作node.jsフレームワークとnginxを使ってラジオサイトを作ってみた自作node.jsフレームワークとnginxを使ってラジオサイトを作ってみた
自作node.jsフレームワークとnginxを使ってラジオサイトを作ってみた
 
WordPressと外部APIとの連携
WordPressと外部APIとの連携WordPressと外部APIとの連携
WordPressと外部APIとの連携
 
ASP.NET MVC のルーティング設定を少しだけ REST ぽくする
ASP.NET MVC のルーティング設定を少しだけ REST ぽくするASP.NET MVC のルーティング設定を少しだけ REST ぽくする
ASP.NET MVC のルーティング設定を少しだけ REST ぽくする
 
後期02
後期02後期02
後期02
 
HTML5&API総まくり
HTML5&API総まくりHTML5&API総まくり
HTML5&API総まくり
 
AngularJSでの非同期処理の話
AngularJSでの非同期処理の話AngularJSでの非同期処理の話
AngularJSでの非同期処理の話
 
Data api workshop at Co-Edo
Data api workshop at Co-EdoData api workshop at Co-Edo
Data api workshop at Co-Edo
 
20081003
2008100320081003
20081003
 
Go言語で作る webアプリ@gocon 2013 spring
Go言語で作る webアプリ@gocon 2013 springGo言語で作る webアプリ@gocon 2013 spring
Go言語で作る webアプリ@gocon 2013 spring
 
Twitter連携chrome extension作り方
Twitter連携chrome extension作り方Twitter連携chrome extension作り方
Twitter連携chrome extension作り方
 
Web area 2013-07-16
Web area 2013-07-16Web area 2013-07-16
Web area 2013-07-16
 
html5j.orgがHTML5+JavaScriptで Metro Style アプリを作ってみた
html5j.orgがHTML5+JavaScriptで Metro Style アプリを作ってみた html5j.orgがHTML5+JavaScriptで Metro Style アプリを作ってみた
html5j.orgがHTML5+JavaScriptで Metro Style アプリを作ってみた
 
Paint Tool 2013-05-14
Paint Tool 2013-05-14Paint Tool 2013-05-14
Paint Tool 2013-05-14
 
初めての Data api cms どうでしょう - 大阪夏の陣
初めての Data api   cms どうでしょう - 大阪夏の陣初めての Data api   cms どうでしょう - 大阪夏の陣
初めての Data api cms どうでしょう - 大阪夏の陣
 
初めての Data API CMS どうでしょう - 仙台編 -
初めての Data API   CMS どうでしょう - 仙台編 -初めての Data API   CMS どうでしょう - 仙台編 -
初めての Data API CMS どうでしょう - 仙台編 -
 
Chrome Extensionsの基本とデザインパターン
Chrome Extensionsの基本とデザインパターンChrome Extensionsの基本とデザインパターン
Chrome Extensionsの基本とデザインパターン
 

Recently uploaded

Recently uploaded (10)

Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
 
新人研修 後半 2024/04/26の勉強会で発表されたものです。
新人研修 後半        2024/04/26の勉強会で発表されたものです。新人研修 後半        2024/04/26の勉強会で発表されたものです。
新人研修 後半 2024/04/26の勉強会で発表されたものです。
 
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
 
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
 
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアルLoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
 
Utilizing Ballerina for Cloud Native Integrations
Utilizing Ballerina for Cloud Native IntegrationsUtilizing Ballerina for Cloud Native Integrations
Utilizing Ballerina for Cloud Native Integrations
 
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
 
LoRaWANスマート距離検出センサー DS20L カタログ LiDARデバイス
LoRaWANスマート距離検出センサー  DS20L  カタログ  LiDARデバイスLoRaWANスマート距離検出センサー  DS20L  カタログ  LiDARデバイス
LoRaWANスマート距離検出センサー DS20L カタログ LiDARデバイス
 
知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx
知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx
知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx
 
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
 

SPAのルーティングの話