Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
ReactベースのSPA開発で開発者が気をつけたいSEOのお話
Search
Yoshinobu Wakamatsu
August 21, 2019
Technology
2
1.6k
ReactベースのSPA開発で開発者が気をつけたいSEOのお話
【シューマイ】Tech Lead Engineerから最新技術を学べ!React編
https://shuuu-mai.connpass.com/event/140002/
Yoshinobu Wakamatsu
August 21, 2019
Tweet
Share
More Decks by Yoshinobu Wakamatsu
See All by Yoshinobu Wakamatsu
金融領域におけるサービス開発の進め方
yshnb
0
620
資産運用スタートアップの開発で採用した、PlayによるClean Arcitectureでの設計・開発事例
yshnb
5
920
Fundsのアーキテクチャについて
yshnb
0
210
ScalaによるDDDライクなプロダクト開発
yshnb
0
470
Applivの開発体制から考える、理想の開発体制とは?
yshnb
2
10k
Other Decks in Technology
See All in Technology
1等無人航空機操縦士一発試験 合格までの道のり ドローンミートアップ@大阪 2024/12/18
excdinc
0
150
2024年にチャレンジしたことを振り返るぞ
mitchan
0
130
オプトインカメラ:UWB測位を応用したオプトイン型のカメラ計測
matthewlujp
0
170
podman_update_2024-12
orimanabu
1
260
UI State設計とテスト方針
rmakiyama
2
310
サイバー攻撃を想定したセキュリティガイドライン 策定とASM及びCNAPPの活用方法
syoshie
3
1.2k
Amazon VPC Lattice 最新アップデート紹介 - PrivateLink も似たようなアップデートあったけど違いとは
bigmuramura
0
190
スタートアップで取り組んでいるAzureとMicrosoft 365のセキュリティ対策/How to Improve Azure and Microsoft 365 Security at Startup
yuj1osm
0
210
LINEスキマニにおけるフロントエンド開発
lycorptech_jp
PRO
0
330
Jetpack Composeで始めるServer Cache State
ogaclejapan
2
160
Qiita埋め込み用スライド
naoki_0531
0
860
プロダクト開発を加速させるためのQA文化の築き方 / How to build QA culture to accelerate product development
mii3king
1
260
Featured
See All Featured
Designing for Performance
lara
604
68k
Java REST API Framework Comparison - PWX 2021
mraible
PRO
28
8.3k
Practical Orchestrator
shlominoach
186
10k
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
5
440
Rails Girls Zürich Keynote
gr2m
94
13k
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
0
94
How To Stay Up To Date on Web Technology
chriscoyier
789
250k
Designing Experiences People Love
moore
138
23k
Large-scale JavaScript Application Architecture
addyosmani
510
110k
GraphQLの誤解/rethinking-graphql
sonatard
67
10k
Principles of Awesome APIs and How to Build Them.
keavy
126
17k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
26
1.9k
Transcript
ReactベースのSPA開発で 開発者が気をつけたいSEOのお話 株式会社クラウドポート IT・業務管理部⻑/エンジニア 若松 慶信
Introduction 2019/8/21 2
⾃⼰紹介 株式会社クラウドポート IT・業務管理部⻑/エンジニア 若松 慶信 2019/8/21 3 • クラウドポートのFundsではフロントエンド含む開発・運⽤全般を担当 •
SEOについては前職で経験
資産形成をしたい個⼈とお⾦を借りたい企業を結ぶ、 「貸付ファンド」のオンラインマーケット 第⼆種⾦融商品取引業者のクラウドポートが運営
None
2019/8/21 6 今回のテーマについて
2019/8/21 7 Reactなどを使うモダンなフロントエンド開発での SEOに関する情報は少ない・・・
FundsでのReactの使い⽅を SEOという視点からお話します 2019/8/21 8 ※SEOの話多めです
SEOとフロントエンドエンジニアの役割 2019/8/21 9
SEO(検索エンジン最適化)とは Webサイトが検索エンジンで⾒つかりやすくすること 2019/8/21 10
SEOに取り組む上での基本的な考え⽅ • ベストエフォートで取り組み、結果が出るのを待つ • 銀の弾丸はない 2019/8/21 11
今回はフロントエンドエンジニアの役割にフォーカスした話をします 2019/8/21 12
SEOにおけるフロントエンドエンジニアの役割 クローラーが正しくWebサイトを解釈できるようにし サイトが正当な評価を受けられるようにする 2019/8/21 13
「正当な評価を受けられる」とは︖ 2019/8/21 14
正当な評価を受けられないケースの例 • クローラーが正しくレンダリングできない • ページ間の関係性をリンクで伝えられていない • 複数のURLで同じコンテンツを表⽰できてしまう • 存在しないページなのに、200でコンテンツが表⽰できてしまう 2019/8/21
15
SEOにおけるフロントエンドエンジニアの役割 クローラーが正しくWebサイトを解釈できるようにし サイトが正当な評価を受けられるようにする 2019/8/21 16
SEOにおけるフロントエンドエンジニアの役割 クローラーが正しくWebサイトを解釈できるようにし サイトが正当な評価を受けられるようにする 2019/8/21 17 エンジニアの考慮不⾜で機会損失を⽣まないことが重要
SEOを考慮したレンダリング⼿法の選択 2019/8/21 18
レンダリング (今回の⽂脈では) HTMLとJavaScriptからブラウザ上へ描画するための DOMツリーを構築すること 2019/8/21 19
レンダリング 正しくレンダリングさせることは、正当な評価を受ける必要条件の1つ 2019/8/21 20
Googlebotのレンダリング能⼒ • (〜2019/5)Chrome 41 程度のレンダリング能⼒ • ES6などのシンタックスは未サポートでpolyfillが必要 • (2019/5〜現在)最新のChromium エンジンを適⽤可能に
• ES6などにも対応 • クローラー向けのpolyfillは不要になっている 2019/8/21 21
2019/8/21 22
SPAの主なレンダリング⽅式 • CSR (Client Side Rendering) • ブラウザ上でJavaScriptによりレンダリングする⽅式 • SSG
(Static Site Generator) • ビルド時に静的なHTMLを出⼒する⽅式 • Dynamic Rendering • ⼀般のユーザー向けにはCSRを適⽤する • クローラー向けの配信に限りレンダリング済みの結果を返す • SSR (Server Side Rendering) • コンテンツ配信時にサーバサイドでレンダリングする⽅式 • Rehydration により継続して CSR でレンダリングできるようにすることも多い • ⾯倒だが確実性はある 2019/8/21 23
SSRは必要か︖ • レンダリングの問題に限ればSSRは必須ではない • SSRでなければ対応できない問題もある 2019/8/21 24
SSRでなければできないこと • ステータスコードを適切に返す • ページ単位のURL正規化/ソフト404エラーの防⽌に必要 • メタ要素 (title, meta, link
タグなど)を確実に認識させる • URL正規化で使⽤する rel=canonical はSSR以外では解釈されない • その他のメタ要素もサーバサイドでレンダリングして返すことが望ましい • 頻繁に更新されるコンテンツ • JavaScriptを使⽤するレンダリングは遅い(次に説明) • これはDynamic Renderingでも対応できる 2019/8/21 25
引⽤元: https://developers.google.com/search/docs/guides/javascript-seo-basics GoogleがJavaScriptをレンダリングするプロセス JavaScriptのレンダリングには このプロセスが追加で必要 レンダリングされるまで時間を要する 2019/8/21 26
SEOを考慮したレンダリング⼿法の選択 ⾃然検索流⼊が重要な集客チャネルかどうか︖に注⽬する 2019/8/21 27
SEOを考慮したレンダリング⼿法の選択 ⾃然検索流⼊が重要 ⾃然検索流⼊はあまり重要ではない サイトの例 • Webメディア • ECサイト/マーケットプレイス • ポータルサイト
• コーポレートサイト • 会員登録が必須のサイト • 他の集客チャネルがメインのサイト 採⽤する アプローチ SSRを採⽤することが望ましい SSRを採⽤するかはUX次第 2019/8/21 28
Fundsの集客チャネルと要件 ⾃然検索流⼊が重要 ⾃然検索流⼊はあまり重要ではない サイトの例 • Webメディア • ECサイト/マーケットプレイス • ポータルサイト
• コーポレートサイト • 会員登録が必須のサイト • 他の集客チャネルがメインのサイト 採⽤する アプローチ SSRを採⽤することが望ましい SSRを採⽤するかはUX次第 2019/8/21 29 ⾃然検索流⼊は主要な集客チャネルではないが、機会損失がないようにしたい + UXも考慮してSSRを採⽤
Fundsのフロントエンド概要 2019/8/21 30
Fundsのフロントエンド概要 Service app (JavaScript on Browser) Service API (Scala) Service
app (Node.js) on Server on Browser ClientとServerの双⽅で動作するIsomorphicなアプリケーション 2019/8/21 31
Fundsのフロントエンド概要 • ES6 + Flow(TypeScript移⾏したい) • React + Redux •
WebpackでPC⽤, SP⽤, SSR⽤に3種類のビルドを⽣成 • Node.js + Express での SSR(Next.js など使⽤せず) 2019/8/21 32
3種類のビルド⽣成 • 単⼀のコードベースからPC⽤とSP⽤のビルドを⽣成 • またNode.jsでの実⾏⽤にSSR⽤のビルドを別に⽣成 source code build (PC) build
(SP) build (server) webpack 2019/8/21 33
clientではPC/SPでentrypointを分離 (webpack.client.config.js) client/server⽤の設定 (webpack.config.js) 3種類のビルド⽣成: Webpackの設定(抜粋) 2019/8/21 34 const client
= require('./webpack.client.config’); const server = require('./webpack.server.config’); module.exports = [client, server]; entry: { appPc: [ './src/funds_pc.jsx’, ], appSp: [ './src/funds_sp.jsx’, ], }, …
Dynamic Serving(動的な配信) PC・SPで異なるコンテンツを表⽰する⽅式 Server Browser (PC) Browser (SP) HTML (for
SP) request request HTML (for PC) 2019/8/21 35
Dynamic Serving(動的な配信) UserAgent⽂字列を識別して、PC/SPのレンダリング内容を分離 // モバイル判定 const isMobile = (req) =>
{ const md = new MobileDetect(req.headers['user-agent']); return !!md.mobile() && !md.tablet(); }; // モバイル判定結果に応じてレンダリングするコンポーネントを変更 <StaticRouter location={location} context={context}> {isMobile(req) ? <AppSP /> : <AppPC />} </StaticRouter> 2019/8/21 36
ReactでのSEOを加味したアプローチ例 2019/8/21 37
エンジニアが注意すべきSEO上のポイントの⼀例 • レンダリング • 正しく有効なマークアップ • ステータスコードの制御 • URL正規化 •
ページの表⽰速度 • モバイルフレンドリー化 • 構造化データ (ほかにもあるよ) 2019/8/21 38
今回お話するトピック • レンダリング • 正しく有効なマークアップ • ステータスコードの制御 • URL正規化 •
ページの表⽰速度 • モバイルフレンドリー化 • 構造化データ 2019/8/21 39
今回お話するトピック • レンダリング • 正しく有効なマークアップ • ステータスコードの制御 • URL正規化 •
ページの表⽰速度 • モバイルフレンドリー化 • 構造化データ 2019/8/21 40
レンダリング • FundsではReactでSSR • SSR時のstateをクライアント側でRehydrationし CSRできるようにしている 2019/8/21 41
SSR with Rehydration FundsではReactのSSRにRehydrationでCSRを組み合わせています Browser Server state state API ②更新されたredux
stateで renderToString ①レンダリングに 必要な情報取得 ③クライアントサイドに stateを引き継ぎ ④ブラウザ上で差分更新 2019/8/21 42
SSR with Rehydration // react-redux の Providerでreactとredux stateを結合 const provider
= ( <Provider store={store}> <StaticRouter location={location} context={context}> ... </StaticRouter> </Provider> ); // サーバサイドでレンダリング const renderedContent = renderToString(provider); ... // レンダリングしたコンテンツを埋め込み <div id="app">${renderedContent}</div> ②更新されたredux stateを注⼊しrenderToString on Server 2019/8/21 43
SSR with Rehydration // state はrenderToStringで使⽤したRedux State const state =
store.getState(); const serializedState = JSON.stringify(state); // SSRでレンダリングしておきクライアントサイドで利⽤ <script type="text/javascript">var __CWP_INITIAL_STORE=${serializedState};</script> // クライアントサイドでは以下のようにロード const store = configureStore(window.__CWP_INITIAL_STORE, history); ③クライアントサイドにstateを引き継ぎ on Server on Browser 2019/8/21 44
SSR with Rehydration FundsではReactのSSRにRehydrationでCSRを組み合わせています Browser Server state state API ②更新されたredux
stateで renderToString ①レンダリングに 必要な情報取得 ③クライアントサイドに stateを引き継ぎ ④ブラウザ上で差分更新 2019/8/21 45
今回お話するトピック • レンダリング • 正しく有効なマークアップ • ステータスコードの制御 • URL正規化 •
ページの表⽰速度 • モバイルフレンドリー化 • 構造化データ 2019/8/21 46
ソフト404エラー • ステータスコード200で、エラー⾵のページを表⽰している状態 • クローラーは404ページであることを認識できない 404 HTTP上では・・・ HTTP/2 200 Content-Encoding:
gzip Accept-Ranges: bytes Cache-Control: max-age=604800 Content-Type: text/html; charset=UTF-8 … 2019/8/21 47
SPA固有の404ページに関する問題 SPAでは⼀度200で返したHTML・JavaScriptから CSRでレンダリングするため、ステータスコードを404に設定できない 404 CSR前のページを表⽰ この時点で200 ⾒た⽬が404⾵のページをレンダリング 実際はステータスコード200 2019/8/21 48
Fundsの404ページ ステータスコード404で404ページを表⽰(あたりまえですが・・・) 2019/8/21 49
Fundsの404ページ ステータスコードに対応するフィールドをredux state上に定義 SSR時にredux stateを参照しステータスコードを変更する ステータス変更⽤のredux action⽣成 ステータスコードに対応するフィールドを更新 SSR時にstateからステータスコードを変更 Fundsで404ページを表⽰する場合の流れ
2019/8/21 50
今回お話するトピック • レンダリング • 正しく有効なマークアップ • ステータスコードの制御 • URL正規化 •
ページの表⽰速度 • モバイルフレンドリー化 • 構造化データ 2019/8/21 51
重複コンテンツとURL制御 複数のURLで同じコンテンツにアクセス可能だと、 本来得られるべき適切な評価が得られない ページ ページ /cat /cat/hoge ページ /cat/fuga ミスなのか、本当に表⽰したいページが複数あるのかわからない
2019/8/21 52
重複コンテンツとURL制御 まずは正しいURL以外でアクセスできないようにするのが原則 ページ ページ /cat /cat/hoge ページ /cat/fuga 2019/8/21 53
重複コンテンツとURL制御 • react-router でURLに対応するコンポーネントを選択 • できる限りexactを指定 import { Route, Switch
} from 'react-router’; return ( <Switch> <Route exact // exact を指定することで /cat/hoge などはマッチしない path="/cat” component={CatPage} /> ... 2019/8/21 54
URL正規化 クエリパラメータの有無など、複数のURLでアクセス可能になる場合もある ページ /cat/1 ページ /cat/1?foo=1 2019/8/21 55
URL正規化 ステータスコード 301でリダイレクト ページ /cat/1 ページ /cat/1?foo=1 正しいURLの場所をHTTP Responseで明⽰ リソースが直接参照できるURLを1つに限定する(URL正規化)
HTTP/1.1 301 Location: /cat/1 2019/8/21 56
rel=canonical によるURL正規化 301リダイレクトの代わりに rel=canonical で正しいURLを指定することで評価の分散を防⽌ ページ /cat/1 ページ /cat/1?foo=1 クローラーは
/cat/1 の⽅をインデックスすべきURLと解釈し /cat/1?foo=1 はインデックスしない <link rel="canonical” href="https://example.com/cats/1"> 2019/8/21 57
react-helmetでのメタ情報設定 // Helmet (react-helmet) import Helmet from 'react-helmet’; ... return
( <Helmet title=“ファンドを探す” meta={[ { name: 'description’, content: 'Funds(ファンズ)のファンド⼀覧ページです。', }, react-helmet はメタ要素を挿⼊するためのライブラリ <Helmet>で定義すると ⾃動的に <head /> 内へ含めてくれる 2019/8/21 58
rel=canonical によるURL正規化 rel=canonicalを指定する場合も react-helmet を使⽤ // Helmet (react-helmet) import Helmet
from 'react-helmet’; ... return ( <Helmet link={[ { ref: ‘canonical’, href: ‘https://funds.jp/fund/list', }, 2019/8/21 59
react-helmet で設定可能なメタ要素の例 • title • meta description • SERPs(検索結果のページ)に表⽰される内容には影響する •
meta robots • OGP • og:image など。Facebookなどでのシェアの際に有効 • Twitter Cards • Twitterでのシェアの際の表⽰ • rel=canonical • URL正規化で使⽤ このあたりの指定は SSR or Dynamic Renderingが必要 2019/8/21 60
まとめ 公開サイトを開発するフロントエンドエンジニアなら SEOについても知っておこう 2019/8/21 61