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
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Yoshinobu Wakamatsu
August 21, 2019
Technology
1.8k
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
ReactベースのSPA開発で開発者が気をつけたいSEOのお話
【シューマイ】Tech Lead Engineerから最新技術を学べ!React編
https://shuuu-mai.connpass.com/event/140002/
Yoshinobu Wakamatsu
August 21, 2019
More Decks by Yoshinobu Wakamatsu
See All by Yoshinobu Wakamatsu
金融領域におけるサービス開発の進め方
yshnb
0
800
資産運用スタートアップの開発で採用した、PlayによるClean Arcitectureでの設計・開発事例
yshnb
5
1k
Fundsのアーキテクチャについて
yshnb
0
300
ScalaによるDDDライクなプロダクト開発
yshnb
0
530
Applivの開発体制から考える、理想の開発体制とは?
yshnb
2
10k
Other Decks in Technology
See All in Technology
20260804_Q4AzureUpdateBite_FabricDataAgentの精度を高める設計.pdf
matayuuu
1
140
トヨタ⽣産⽅式(TPS)⼊⾨
recruitengineers
PRO
3
930
LanceDB入門
mocobeta
8
570
AIペネトレーションテスト・ セキュリティ検証「AgenticSec」紹介資料
laysakura
2
9.1k
Agent 時代の Kaggle 展望 / kaggle-in-the-agentic-era
upura
1
780
Sansan Engineering Unit 紹介資料
sansan33
PRO
1
4.9k
認知負荷をGemini で溶かす — GKE 基盤「Orbit」における AI エージェントの実践
sansantech
PRO
1
320
ガバメント AI 源内を地方自治体は活用できるのか可能性と課題、期待について
takeda_h
2
430
Bits AI を制するものは Datadog を制す / The player that controls Bits AI, controls Datadog
kaminashi
0
110
AIコーディングの次。コードレビューと理解負荷を解消して組織の開発生産性を高める
moongift
PRO
2
2.6k
AWS ネットワーク構築でハマった(ハマりかけた) 5選とそこから得た教訓
nagisa53
4
240
『三匹の子ぶた』から学ぶネットワークセキュリティの昔と今 / Network Security: Then and Now Through the Lens of The Three Little Pigs
nttcom
1
6.2k
Featured
See All Featured
Balancing Empowerment & Direction
lara
6
1.2k
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
21
1.6k
Keith and Marios Guide to Fast Websites
keithpitt
413
23k
A Guide to Academic Writing Using Generative AI - A Workshop
ks91
PRO
1
370
Future Trends and Review - Lecture 12 - Web Technologies (1019888BNR)
signer
PRO
0
3.7k
Being A Developer After 40
akosma
91
590k
A Tale of Four Properties
chriscoyier
163
24k
YesSQL, Process and Tooling at Scale
rocio
174
15k
KATA
mclloyd
PRO
35
15k
Rails Girls Zürich Keynote
gr2m
96
14k
Six Lessons from altMBA
skipperchong
29
4.4k
How People are Using Generative and Agentic AI to Supercharge Their Products, Projects, Services and Value Streams Today
helenjbeal
1
260
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