Successfully reported this slideshow.
Your SlideShare is downloading. ×

SPAのルーティングの話

Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Upcoming SlideShare
Pjax1
Pjax1
Loading in …3
×

Check these out next

1 of 35 Ad
Advertisement

More Related Content

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

Recently uploaded (20)

Advertisement

SPAのルーティングの話

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

×