#概要
Single Page Applicationを実装するにあたって、気になることの質問・回答集。
ここで言う「Single Page Application」とは、画面遷移(リロード)をせず、1ページ内で
ajaxなどを使用してページ遷移(のような動き)を実装しているものを指します。
また、Vue.jsを使用して実装することを想定しています。
※随時更新していきます。
#FAQ
Google Analyticsの測定はできるの?
可能です。
vue-routerでURLを切り替える際に、手動でGA側にページ遷移を通知することで測定されます。
(ブラウザバックではページカウントが増えません)
任意のイベントを通知することも可能ですが、懸念点としては下記が挙げられます(未検証)
- GAタグ以外で、手動でページ遷移を通知する方法がない計測タグは対応できない
- Google Tag Managerを使ってページごとに任意の処理を行いたい場合、対応できない可能性がある
参考
https://developers.google.com/analytics/devguides/collection/gtagjs/single-page-applications
http://sys1yagi.hatenablog.com/entry/2016/11/30/233414
Googleにちゃんとindexされるの?
sitemap.xmlを設置してSearch Consoleで登録すればindexされます。
また、indexされたページもtitleやmeta情報などが反映されており、
Google側でjsが実行された状態でindexされます。
sitemap.xmlの自動生成ツールは使えるの?
使えません。
sitemap.xmlを自動生成するツールは多数Web上にありますが、
SPAに対応してるものはありませんでした。
なので、SPAの場合においては、sitemap.xmlを手動作成する必要があります。
ページのURLを自由にカスタマイズできるの?
できます。
Vue.jsがもつvue-routerというモジュールがあり、ページURLと使用するモジュールを紐付けることができます。
- vue-router
https://jp.vuejs.org/v2/guide/routing.html
URLに動的なパラメータを持たせることも可能です。
下記のページで商品URLの例を確認することができます
ただし、対応する場合はサーバー側でリライトモジュールの設定が必要です。
任意のパラメータを付与させることはできるの?
できます。
vue-routerではパラメータを下記の記載で取得可能です
{{ $route.query.name}}
効果測定タグをページ毎に出し分けできるの?
できます。
ただし、ページ遷移をした時点でHTMLの評価は行われるようなので、
Vue.jsのif構文で表示制御をする必要があります。
コンバージョンなどについては当記事内の
「ブラウザバックで戻ったときにコンバージョンタグが複数回カウントされたりしないの?」
の回答を参考のこと
title/metaをページ毎にカスタマイズできるの?
Vue.jsのプラグインである「Vue-Meta」を利用することで実現できます。
Vue-Meta
https://github.com/declandewet/vue-meta#recognized-metainfo-properties
このプラグインでは下記のことが可能です。
- titleをページ毎に書き換える
- metaタグ(keywords、description、OGPタグなど)をページ毎に設定する
- 任意のCSSファイル・javascriptファイルを読み込む
- nosriptタグを埋める
- html/bodyに属性を指定する
ブラウザバックで戻ったときにコンバージョンタグが複数回カウントされたりしないの?
実装で回避することができます。
以下のような処理順で行うことで、重複カウントは防げます。
(下記は処理完了ページの例)
※処理完了ページの例
1)ページアクセス
2)APIにてセッションチェック
3)2がOKであれば、完了ページ表示フラグを立てる
4)コンバージョン用のHTMLが出力される
ブラウザバックでアクセスされた場合、2のチェックでエラーになるため、
3以降が行われることなく、エラーページが表示されます。
Vue.js内にHTMLとして普通に記載していると、セッションチェックが終わる前にHTMLを評価してしまうので、
出力フラグを用意し、そのフラグによって出力制御をすることで実現可能です。
各ページのアクセスログって残るの?
残りません。
Single Page Applicationはすべてクライアント側でHTMLの描画を行うので、サーバー側にログは残りません。
ただし、APIを呼び出したログは残ります。
SPA側で「ページ切り替えを行った」ということは検知できるので、その際にログ記録用のAPIに
URL情報を付与して送るなどしておけば、アクセスログを取ることは可能です。
例)
https://~.co.jp/api/accesslog.asp?url=/pd/cosme/test001
ログ記録用APIをわざわざ呼ぶと、APIコール1回分がコストになるので、セッション確認APIに
付与するようにするなどすればより良いです。
そもそもSPAって早いの?
処理自体は変わっておらず、その処理をクライアント側で行うか、サーバー側で
行うかだけの違いなので、処理速度はクライアント側のPCスペックや通信環境に依存します。
SPAでは初回ロード時に必要なjavascriptファイル・CSSファイルはダウンロードされるため、
2ページ目以降の表示は早くなります。また、ヘッダー・フッターなど
共通の部分は最初のページのみでロードされるので、2ページ目以降は少し早くなります。
ただし、SPAではHTMLの構築をすべてjavascriptで行い、ページ遷移がないため、
メモリリークが発生するリスクがあります。
(構築されたHTML情報はメモリに展開されるため)
そのため、場合によっては任意のページでリフレッシュする方が良い場合もあります。
これは状況によるのでサイト毎に考えてください。
SPAで多言語対応ってどうやるの?
Vue.jsのi18nプラグインで対応可能です。
https://qiita.com/_upto_me_/items/6d76dcd2d2c09b1bcb88
手順は以下の通り。
1)i18nプラグインをインストール
2)Vue.jsインスタンス生成時に多言語設定を追加
3)初期値のlocaleを設定
4)JSON形式のmessageファイルを作成
5)HTML内にmessage埋め込み
6)言語切替処理を実装
messageファイルは下記のような形式で作ります。
{
"ja": {
"message": {
"title": "タイトル",
"dashbord": "ダッシュボード",
"subtitle": "ここがサブタイトルになります"
}
},
"en": {
"message": {
"title": "title",
"dashbord": "Dashboard",
"subtitle": "sub title"
}
},
"han": {
"message": {
"title": "標題",
"dashbord": "儀表盤",
"subtitle": "副標題"
}
}
}
言語毎にjsonファイルを分けることも可能です。
また、HTML内の記載はこうなります。
<h1>{{$t("message.dashbord")}}</h1>
手順の3で設定したlocaleを「jp」や「en」に変更することで、
message.jsonに定義された言語に変わります。
{{$t("message.dashbord")}}
の形式で記載されてない箇所は変わりません。
サンプル
http://spa-sample.ivp.co.jp/entry1
(ページ最上部の「ダッシュボード」が変わります)
ページスクロールした位置って記憶してるの?
記憶してます。下記のような動作になります。
1)検索結果ページでページ下部までページスクロール
2)別ページへ遷移
3)ブラウザバックで戻る
4)ページ下部で表示される
また、ブラウザバックではなく、リンクで戻った場合はページ最上部に行きます。
1)検索結果ページでページ下部までページスクロール
2)別ページへ遷移
3)リンクで商品一覧に戻る
4)ページ最上部で表示される
セキュリティでCSRF対策はどのようにすればよいか?
基本的にはサーバーサイドで制御するときと同じです。
1)入力確認画面でトークンを発行する
2)完了画面で1で発行したトークンが生きてることを確認する
3)2がOKであれば登録処理を行い、1のトークンを無効化する
この内容で完了画面への直接アクセス(CSRF)は防げます。
確認画面でのトークン発行は「登録完了」Buttonを押下したタイミングで発行します。
なので、確認→完了のあたりの処理順は下記のようになります。
1)確認画面表示
2)完了画面へ進むボタンクリック
3)トークン発行APIをコール(この時点ではURLは確認画面のまま)
4)完了画面へ遷移
5)登録APIをコール
6)3のトークンが無効化
7)直接完了画面にアクセスしてもトークンがないのでエラーになる
参考情報として、
Laravel(PHPフレームワーク)では、サーバ側でCSRFトークンを発行する形で対応しているようです。
http://blog.asial.co.jp/1496
sitemap.xmlは設置できるの?
設置可能です。
ただし、vue-cliを使ってドメイン直下にファイルを置く場合には、
vue-routerでのルーティング設定か、webpackの設定調整が必要です。
上記サイトではwebpackの設定を調整したので、
staticフォルダ以下に配置しています。
拡張子の制限はないの?
ありません。
faviconを設置したいんだけどこに置けばいいの?
sitemap.xmlや画像フォルダと同じ場所におけばOKです。
httpステータスコードは制御できるの?
できません。
SPAの場合は大本になってるファイルがあり、その中で仮想的にHTMLを構築するため、
存在しないページURLでアクセスされても、200が返却されます。
200が返却された後、ページ表示処理で404のような表示をすることは可能ですが、
httpステータスコード自体を404にすることは不可能です。
ファイル更新したときにキャッシュはどう処理されるの?
色んなアプローチがあると思いますが、Vue.jsではWebPackという技術を使用することで回避しています。
Vue.jsには、vue-cliという開発するためのツールや設定がまとまったものがあるのですが、
その中にwebpackの設定が同梱されています。
vue-cli
https://jp.vuejs.org/2015/12/28/vue-cli/
vue-cliに含まれてるwebpackの設定では、複数のjsファイルやcssファイルを
結合して出力する際、ソースの内容からハッシュ値を生成しファイル名に付与します。
たとえば、
この状態からvue.jsで管理されているhtmlに修正をいれてbuildしなおすと
こうなります。
変更が入っていないファイルはそのまま、で変更が入っているファイルはハッシュ値が変わっています。
これでキャッシュされることはありません。
ただし、これはwebpackで管理されているファイルだけなので、webpackの管理外に
なっているファイルは、ハッシュ値の付与がされないので、キャッシュの問題が発生します。
完全に回避しようとすると全てをwebpack管理する必要がありますが、
ルーティングに関するjsファイルは標準でwebpack管理されているので、
ページ遷移できないなどのリスクは少ないのでは・・・・と考えています。
#その他
質問などあればコメントに書いていただければと思います!
判明したものから随時アップデートしていきます!