ogochan
ここのCMSをヘッドレスに移行しました。
移行した当初は爆速になって喜んでいたのですが、いくつかの不都合があったため、一部SSRにしました。
不都合の一番大きなものは、OGPがダメになることです。簡単に言えば、SNSでリンクをシェアした時にサムネが出ません。
OGPの情報はヘッダ部にあるので、コンテンツロードした時にシレっと書き換えるようなコードで書き換えるようにしていました。
window.addEventListener('load',() => {
for ( let target of document.querySelectorAll('.title') ) {
target.innerHTML = title;
}
let el;
if ( el = document.getElementById('og_title') ) {
el.setAttribute('content', `${title} | ${el.getAttribute('content')}`)
}
if ( description ) {
for ( let target of document.querySelectorAll('.description') ) {
target.innerHTML = description;
}
if ( el = document.getElementById('og_description') ) {
el.setAttribute('content', description);
}
}
});
これで一見動いているように見えたのですが、OGPは情報を取得するサービス側(SNS側)からコンテンツのヘッダを取得して、そこから情報を拾うような動作をします(クライアントがpushするわけではない)。そのため、クライアントサイドのJavascriptで書き換えるようなことをしていても、
そもそもJavascriptを実行しない
ということで、テンプレートに書いてあった元々のもの(デフォルトにしている)しか取得されません。つまり、HTML自体がそうなっていないとダメだということです。
これに対してGoogleのクローラはコンテンツがクライアントサイドのJavascriptの実行を前提としていても、最終的に取得されて構築されるHTMLをベースに情報取得するので、正常に情報が取得されます。
これについての解決はいろんなものが提案されているのですが、どれも
要するにSSRしろ
という解決でしかありません。スマートそうに見える解決であっても、結局SSRしているわけです(どこかでSSR相当の処理がある)。
これが「CMSのコンテンツサーバ」の上であれば、SSRを入れることはわけのないことだと思うのですが、弊社のサイトはNapierの内蔵ウェブサーバなので、そういった機構を組み込むには躊躇します。
Napierの内蔵ウェブサーバは「オマケ」として作ったものではありますが、HTMLの断片をサーバサイドで組み立てるような機能はあります。しかし、それは静的なコンテンツを組み立てられるだけであって、ブログエントリのような動的なものには対応できません。そもそも、「コンテンツを取得する」ということはアプリケーション依存の動作ですから。そこまで組み込みたいとは思えないわけです。
あれこれ考えた結果、動的にコンテンツを取得するようなApacheのSSIで言うところのexec
のような動作を組み込めるようにすることにしました。SSIと言うかむしろCGIですね。つまり、サーバサイドのJavascriptで書いたコードを実行して、その結果にテンプレートを適用して生成したHTMLをサーバサイドで組み立てて送信するための機構を作ったわけです。
アイディアとしてもそれほど高度でもなく、きっと誰でも同じコードと同じ問題を見れば考えつくことだろうと思います。
実際のコンテンツを取得して... の部分はCMS固有のコードで動的に組み込まれるものとなっているので、Napierの方には実行のための機構を用意するだけで、専用処理を入れたわけでもありません。
このOGPとSSRの問題は常にセットの問題となりそうなので、多分この辺のことがあってヘッドレスCMSがもてはやされなくなったのだろうなと思います。URLをシェアしたら、やっぱりサムネやタイトルは出て欲しいですからね。動的なコンテンツ、特にブログやニュースのようなコンテンツはSNSでシェアされることが重要な入口になるので、それを整備するには工夫が必要となると、あまり好意的には思えないですね。気軽にコンテンツを流用できるのは良いのですが、SNSのシェアで使えないのは現代では致命的とも言えます。まぁ、
結局解決してしまいました
けどね。
CMSに限らず「ヘッドレス」っていろいろ良いアプローチだと思うのですが、実のところSNSとの相性が悪いというのはなんだかなぁと思います。「動的に引用」するような主なコンテンツが別にあるのであればいいのですが、ページの主となるのは難しいです。
もう組み込んでしまったので結果はご覧の通りなんですが、主なコンテンツ部品を組み立ててから送出するようになったので、ページが開き始めるまでの時間が長くなりました。取得するデータのアクセス量は結局大差はないので、ページ全体が表示されるまでの時間は多分同じくらいです。出方がちょっと変わったなという感じです。開き始めるまでの時間は短い方が嬉しいので、ちょっと残念です。
まぁ問題が解決して良かったということにしておきます。