文系プログラマによるTIPSブログ

文系プログラマ脳の私が開発現場で学んだ事やプログラミングのTIPSをまとめています。

SSR無しのReact・Angular製のSPAサイトはGooglebotにどれくらい認識されるのか?

実際私が開発している2サイトの実例出しますよ〜


f:id:treeapps:20170917230836p:plain

WEBサイトの開発者に取って常に気になるこの話題について、今回は私が開発している2サイトを実例として、結果をお伝えしようと思います。

※ 最後の「雑感」の後に、Angular製サイトをGolang化してみた結果を追記しました!

概要

大分昔からSPA(シングルページアプリケーション)サイトはGoogleに正しく認識されないため、SEO的には最悪だと言われてきました。そのため、SSR(サーバサイドレンダリング)をし、初回画面表示時は本来ReactやAngularが生成するhtmlを、サーバサイドでレンダリングしてクライアント側はそれを表示するだけ、という手法を用います。

しかしSSRをするためにはほぼNode.jsが必須になるのが現状です。私が愛用しているGoogleAppEngineではまだNode.jsのStandard Environment(無料のやつ)が無いため、Node.jsを無料で使用する事ができません。

わざわざお金をかけてFlexible EnvironmentでNode.jsを使いたくないなと思い、今日までSSR無しのSPAサイトをGoogleAppEngineで運用してきました。

では、SSR無しのSPAサイトは、どれくらいGoogleに認識されるのか?今回はそれを簡単に紹介します。

GooglebotはどれくらいのJavaScript処理能力があるか

以下は2017年の有名SEOサイトの記事ですが、GooglebotはChrome41相当のレンダリング能力を持っているとのことです。
www.suzukikenichi.com

前提

※ 2018/04/04 追記

SSR無しといっても、title・description・各種ogpについてはサーバサイドレンダリングしています。(ここだけ頑張ってます)

SSR無しといっっているのは、React等が生成する筈のjsをサーバサイドで生成しない、という事です。

React製サイト: tree-maps

ここから実例を紹介していきます。

www.tree-maps.com

以下で開発・運用しています。

インフラ Google Appengine Standar Environment
ランタイム Golang
サーバサイド:フレームワーク Echo
サーバサイド:ビルド goapp
フロントエンド:フレームワーク React v16, Redux, react-router
フロントエンド:ビルド webpack v4
UIフレームワーク material-ui
CSS PostCSS, Sass(sugarss)
その他 ServiceWorker, Electron

サイトの開設日

tree-mapsは一度フルリニューアルしており、リニューアル前はGAE/Javaで非SPAサイトで、リニューアル後はSPAサイトになっています。

2017/02/10にリニューアルサイトを開設しており、サイトの開設から1年以上経過しています。

PCデバイスでの認識

f:id:treeapps:20180401014756p:plain

f:id:treeapps:20180401014809p:plain

😁 トップページもプロットページもGooglebotはヘッダーが大きく崩れ、多少CSSのレイアウトがおかしいものの、まあまあ正しく画面を描画できているようです。

モバイルデバイスでの認識

f:id:treeapps:20180401014933p:plain

f:id:treeapps:20180401014945p:plain

モバイル表示の実装はmaterial-uiにお任せ状態です。

😁 どうやらモバイルの場合はGooglebotは相当な再現ができているようですね。これは嬉しいです。

サイトマップxmlとインデックスの登録数

サイトマップxml https://www.tree-maps.com/assets/sitemap.xml

f:id:treeapps:20180401015516p:plain

😁 17URL中16URLは認識して貰えました。上出来ですね。

Angular製サイト: StringUtility

www.string-utility.com

以下で開発・運用しています。

インフラ Google Appengine Standar Environment
ランタイム Java v1.8 (Kotlin v1.2)
サーバサイド:フレームワーク Spark framework
サーバサイド:ビルド Gradle v4.2
フロントエンド:フレームワーク Angular v5.2
フロントエンド:ビルド angular-cli v1.7
UIフレームワーク angular-material
CSS Sass
その他 ServiceWorker

サイトの開設日

StringUtilityは最初からSPAサイトです。

2017/10/07に開設しており、開設してから5ヶ月程度経過しています。

PCデバイスでの認識

f:id:treeapps:20180401020953p:plain

f:id:treeapps:20180401021010p:plain

😱 ・・・うーん、これは・・・

モバイルデバイスでの認識

f:id:treeapps:20180401021025p:plain

f:id:treeapps:20180401021042p:plain

😱 ・・・やっぱり駄目なのか

本来レンダリングされる筈の画面

このままだと本来の画面はどうな感じなのか解らないと思うので、一応本来のサイトのスクリーンショットも載せておきます。

トップページはこうです。
f:id:treeapps:20180401025726p:plain

CSV・TSV相互変換ページはこうです。
f:id:treeapps:20180401025751p:plain

こうして見比べると、Googlebotが全然認識してくれていない事が明確に解りますよね・・・

サイトマップxmlとインデックスの登録数

サイトマップxml https://www.string-utility.com/data/sitemap.xml

f:id:treeapps:20180401021423p:plain

😱 ・・・10URL中2URLしか認識されず

botはServiceWorkerのhtmlを取得しているのかどうか

React製のtree-mapsでもServiceWorkerを使用しており、サーバサイドorReactが生成するhtmlとServiceWorkerが配信するhtmlは同じですが、Angular製のStringUtilityの方はサーバサイドorAngularが生成するhtmlとServiceWorkerが配信するhtmlが異なっています。これはangular-service-workerが勝手にhtmlを作ってくれるので、そうなっています。

ではbotはServiceWorker側のhtmlを取得したのでしょうか?見てましょう。

サイト上で確認できるServiceWorker向けのhtml

f:id:treeapps:20180401022131p:plain

こんな感じにUglifyされ、$マークの変数が展開されていないものが配信されます。Googlebotが↑のhtmlを取得していたら、GooglebotはServiceWorkerのhtmlを参照していると言えます。

Googlebotが取得したhtml

f:id:treeapps:20180401022229p:plain

どうやらGooglebotはServiceWorkerのhtmlではなく、通常のサーバサイド、もしくはAngularが生成したhtmlを取得しているようです
(サーバサイドのhtmlもAngularのhtmlも、titleタグ等を動的に変更しているので両者の見分けがつきません)

まあ流石にServiceWorkerのhtmlを取得してはいないだろうとは思っていましたが、ちゃんと検証できるとホッとしますね。

雑感

React製サイトはいい感じにGooglebotに認識されているのに、Angular製サイトは酷い有様でした。

AngularはGoogle製のフレームワークなのでGooglebotと親和性高いかも!?とか思っていたらこれですよ。UIフレームワークもGoogle製のangular-materialなので、Googleフレンドリーなサイトの筈なのですけどね・・・なんという無慈悲な結果。

両者の違いはほとんど無い筈ですが、サイトの速度が異なります。

www.bunkei-programmer.net
www.bunkei-programmer.net

以前↑の記事を書きましたが、ランタイムがGolangの場合はスピンアップもフレーワーク初期化も無茶苦茶速いのですが、Javaの場合はスピンアップもフレームワーク初期化もかなり遅いのです。

もしかしたら、この初回起動の速度も影響しているのかもしれませんね。Angular製サイトのランタイムをGolangにしたら、React製のサイトと同様にレンダリングされたら・・・・それこそ無慈悲ですね。

という事で、React製サイトはSSR無しでもGooglebotにいい感じに認識され、Angular製サイトは惨敗でほとんどGooglebotに認識されない、という結果となりました!

Googlebotの挙動はGoogleの中の人にしか解りませんので、この記事で推測したものは全て外れている可能性がありますので、あくまで一例として参考にできれば、と思います!

おまけ 2018/04/04追記

Angular製サイトの結果が良くなかった点について、初回画面表示速度が影響している可能性(そもそもhtmlが返るのが遅くてタイムアウトしかけているか、クロールを諦めた等の可能性)があると思い、思い切ってGoogle Appengineのランタイムを、現在のJava8からGolang1.9に変更してみました!

www.string-utility.com

種別 変更前 変更後
GoogleAppengineランタイム GAE/Java8(Kotlin v1.2.30) GAE/Golang v1.9
サーバサイド:フレームワーク Spark Framework Echo Framework
サーバサイド:ビルド Gradle v4.6 goapp deploy
フロントエンド:パッケージマネージャ Yarn Yarn
フロントエンド:トランスパイラ Typescript Typescript
フロントエンド:フレームワーク Angular v5.2 Angular v5.2
フロントエンド:ビルド angular-cli angular-cli
フロントエンド:UIフレームワーク angular-material angular-material
フロントエンド:スタイル sass sass

元々tree-mapsでGolangを使っていたので、String UtilityのGolang化は2日程でサックリできました。

ランタイムが変わった事で、サーバサイドフレームワークとビルドが代わりましたが、フロントエンド側は全く同じです。

では、この状態でGooglebotにレンダリングさせたらどうなるでしょうか?高速化した事で何か変化はあったでしょうか?

Golang化して再度Googlebotにクロールさせてみる

f:id:treeapps:20180404171403p:plain
f:id:treeapps:20180404171414p:plain
f:id:treeapps:20180405174735p:plain

😅 結果が変わってる!!前回はタイトルの文字以外全くレンダリングできてなかったのに、今回は崩れているもののヘッダーも表示できているようです。

サーバサイド側の作りが悪かったのか、それともGolang化してスピンアップ+フレームワーク初期化の高速化によって、クロール速度アップが影響したのか。何かしらの影響はあったっぽいですね。ただし、これでGooglebotがクロールできるようになったかは不明です。改善はしたとは思います。


最近会社でJavaではなくサーバサイドKotlin + SpringBoot v2で開発していたりして、Kotlinが凄く良いと思っているのですが、やはりGolangの速度も捨てがたいですね。

GoogleAppengineやAWSLambda等のコンテナ系の場合、コールドスタート時に遅いjavaは少し辛いので(私のサイトのようにトラフィックが少なすぎてコールドスタート頻発サイトは特にそうです)、Golangはそういう部分では良いですね。書いていて楽しくて楽なのは断然Kotlinではあるのですが。。。