ICS MEDIAは2019年4月にリニューアルしました。シンプルでモダンなデザインへと見栄えは変わり、フロントエンドの最新技術によって爆速なサイトへと生まれ変わっています。
技術的におもしろいポイントは、WordPressを廃止したことです。
この記事では、オウンドメディアとしてWordPressをやめた理由、代用技術の選定で苦労したことを紹介します。
リニューアル前後の違い
リニューアルによってどのくらい改善したか、定量的な結果を紹介します。ウェブサイトの性能を示す指標としてLighthouse(Google ChromeのデベロッパーツールのAuditsタブ)というツールがあります。
Lighthouseの採点で、リニューアル前は80点ほどだったのが、ほぼ満点のスコアをたたき出せるようになりました。SEOやアクセシビリティの点数も満点です。
動画でもご覧ください。リニューアル後はページ遷移時の「つっかかり」がなくなり、滑らかにページを表示できています。リニューアル前も早いほうだったと思いますが、さらに読み込みが早くなりました。
リニューアル後の性能向上
検索機能も強力です。ポチポチっと文字入力すると一瞬で記事を絞り込みできます。「検索ページ」からぜひ試してみてください。
WordPressのデメリットとは
WordPressは導入が手軽で、ウェブサイト管理に必要な機能が充実しています。安価なレンタルサーバーでも動作するので、規模を問わず導入している方も多いでしょう。WordPressを利用できる人材も多く、今後も需要の多い技術であり続けると思います。
ICS MEDIAでは、サイトを立ち上げた2013年よりWordPressを使っていました。2015年には、当時は珍しかったHTTP/2の導入もあいまって、hetemlからAWS+AMIMOTOへの移行でWordPressとしては高い性能を獲得しています。
ここまで説明すると、WordPressでも問題なさそうですが運用の問題が発生していたのです。
メンテナンスの手間
世界のウェブサイトの3割はWordPressで動いていると言われています。ユーザー数が多いことはメリットですが、適切にアップデートしていないWordPressはハッカーに狙われやすいといった弊害があります。サイト管理者はアップデートを怠らず、管理していかなければなりません。WordPressの最新情報を追いながら、しかるべきタイミングで互換性を気にしながらアップデートするのは手間ではありました。
プラグインの問題もあります。WordPressではプラグインを導入して、カスタマイズするのが一般的です。プラグインは個人の方が開発していることが多いですが、メンテナンスが止まることは少なくありません。たとえば次のような問題が発生しました。
- FacebookやTwitterの仕様変更に対応できず、ソーシャルカウントプラグインが動作しなくなった
- コードハイライトのプラグインが時代遅れになり、新しい言語仕様で色付けができない
公式のメンテナンスが止まったプラグインは、自力で改修していましたが、時代の流れについていくのも苦労しました。
JavaScriptのコードハイライトを例に紹介すると、変数宣言に使うvar
は記事中のコードブロックでハイライトできるものの、ES2015で登場した新しい宣言のlet
やconst
はハイライトできないといった問題がありました。
執筆ワークフローの問題
ICS MEDIAでは記事はマークダウンで書いています。記事『CodeGridの作り方 - GitHubで文書管理』からヒントを得て、原稿はGitで管理しています。Gitでマークダウン管理というのは、エンジニアらしいやり方ですよね。
とはいえ、本番公開時にはマークダウンはWordPressにコピー&ペーストしなければなりません。GitとWordPressの両方で原稿が二重管理になることは課題でした。
専用のマークダウンエディターを開発して課題解決を目指しましたが、理想的なワークフローは確立できないままでした。ICS MEDIAは古い記事でもメンテナンスすることで読者に役立つ情報提供を心がけています。原稿のメンテナンスを続けるにあたり、一元管理されたマークダウンファイルを扱いたいというニーズが社内に生まれていました。
▲ 社内で開発した専用エディター。Electron製。マークダウンを書くと、右側のペインでウェブサイトの表示が確認できる。内部に「テキスト校正くん」原型のエンジンが組み込まれている
以上をまとめると根本的に問題視していたのは次の課題です。
- CMSとしてのメンテナンス性
- 原稿の執筆ワークフロー
リニューアル後の技術紹介
ICSはフロントエンドの制作会社なので、技術的に誇れるものを開発したいというモチベーションがありました。脱CMS(コンテンツ・マネジメント・システム)化して、静的サイトジェネレーターへの移行を決定したわけですが、その理由を紹介します。
静的サイトジェネレーターの採用
リニューアルにともないサーバーサイドにCMSを設置しないことを目指しました。
つまり、静的ファイルのみで運用します。静的ファイルの配信だけであれば、エンドユーザーはREAD権限しか持たないため、セキュリティー問題の多くは解決できます。また、配信負荷が下がり、耐障害性も向上します。コスト面でも有利です。
静的ファイルを配信するにあたり、GatsbyJSやVuePress、Next.js、Angularなどさまざまな候補から検証を繰り返し、Nuxt.jsの採用に至りました。
▲Nuxt.jsの公式サイト。ドキュメントは日本語訳されている
Nuxt.jsとはVue.jsのフレームワークです。開発効率をあげるだけでなく、ウェブサイト制作におけるベストプラクティスが集積されています。
Nuxt.jsを使えばシングルページアプリケーション(SPA)としてウェブサイトを公開できるため、ページ遷移が高速になります。さらに、Nuxt.jsはスクロールに連動して次のページを先読みする機能(スマートプリフェッチ)が搭載されているので、体感的にもページ遷移が高速です。
Nuxt.jsにはOGPやSEOの弱点はない
シングルページアプリケーションはSEOに弱いと思っている方が意外と多いようです。Nuxt.jsには静的ファイルの生成機能も搭載されています。次のコードはNuxt.jsで出力したHTMLの一部ですが、ページ内文言だけでなくOGP情報なども適切に出力されています。SEOやSNSシェアの弱点は解決されていると考えて問題ありません。
Nuxt.jsにはベストプラクティスが集約されている
Nuxt.jsの利点は適切な開発環境を用意してくれることです。最近のフロントエンドは、Babelやwebpackなどを使って複雑な開発環境を組み立てなければなりません。コンパイルの最適化はコンテンツのパフォーマンスにも影響するため、開発環境構築には高い専門知識を必要とします。Nuxt.jsならば、理想的な開発環境をコマンド1つで用意できます。
たとえば、ウェブサイト配信の高速化の定番手法として、CSSは外部ファイルにせずインライン展開することが定石として知られています。外部CSSだとファイルの読み込み完了を待つ必要がありますが、インラインCSSだと読み込み完了を待つ必要がないためレンダリングがブロックされません。Nuxt.jsでは定石にしたがい、インラインでCSSが展開されています。
新しい仕様のコードは、古いブラウザでも解釈できるように変換します。ES2019相当のJavaScriptはES5へ変換され、CSSは自動的にベンダープレフィックスが付与されます。結果として、IE11を含む古めのブラウザもサポート対象にできます。
▲IE10でも部分的な崩れはあっても表示できるようにしている
コーディング規約の適合判定をするLintも強力に設定されているので、共同開発者のコードのブレは解消されます。Nuxt.jsを使えば、これらの開発環境を自力で用意する手間がなくなります。
AMPの採用
設計的にイレギュラーな部分ですが、記事ページはNuxt.jsではなくAMPとしています。
AMPとはウェブページを高速に配信するための仕組みです。AMPは基本的にはHTMLファイルですが、HTMLコーディングにAMPの制約を課すことで高速配信できるようになります。AMPについては記事『AMPの利点と対応HTMLの作り方』を参照ください。
いま、みなさんが読んでいるこのページ自体もAMPです。モバイルやデスクトップでも、AMPで表示されています。
AMPはReactで作った
原稿のマーウダウンファイルは、2段階の処理を通してAMPファイルへ変換しています。
- マークダウンをHTML文字列へ変換
- Reactを使ってAMPファイルへと変換
マークダウンからHTML文字列への変換は後述しますが、先にReactを採用した理由を説明します。
AMPは制約の強い仕様なので、ゴミデータの入らないHTMLを生成できるツールが必要でした。VueやAngularだとScoped CSSのためにHTMLが汚れてしまいます。Scoped CSS自体は開発時に重宝しますが、プレーンなHTMLという観点だと少し扱いづらいという問題がありました。たいしてReact DOMだとDOM構造しか扱わないので、プレーンなHTMLを生成するのに適しています。
ReactDOMServer.renderToStaticMarkup()
メソッドを使うとプレーンなDOM文字列が出力されます。
import React from "react";
import ReactDOMServer from "react-dom/server";
import AmpApp from "./components/index";
export default (info) =>
`<!DOCTYPE html>` +
ReactDOMServer.renderToStaticMarkup(<AmpApp info={info} />)
}
Node.jsでその文字列をHTMLファイルとして保存しています。大量にあるマークダウンを、Reactを使ってHTMLに変換しています。
マークダウンからHTMLへの変換
マークダウンはオリジナルのNode.jsのツールで、HTML文字列に変換しています。
マークダウンからHTMLへの変換は「markdown-it」を利用しています。弊社では3年前よりCreateJS入門サイトやThree.js入門サイトの立ち上げの経験から、マークダウンをHTMLに変換するノウハウがたまっていました。
マークダウンのHTML変換で工夫したのは、レスポンシブイメージへの画像変換です。
レスポンシブイメージとは、デバイスに適した画像を配信する技術です。デスクトップならば大きなサイズの画像を配信し、モバイルであれば小さなサイズの画像を配信します。ユーザーの利用環境にあわせて、余計なデータを配信しないための工夫です。詳しくは記事『HTML 5.1のsrcset・sizes属性とpicture要素の使い方』を参照ください。
実はWordPressには自動的にレスポンシブイメージを配信する機能が組み込まれています。markdown-itには画像変換の仕組みは用意されていないため、マークダウン変換時にレスポンシブイメージを作成する機構を独自に開発しました。
具体的には、マークダウンで指定した画像ファイルは、ホスティング前に複数の解像度の画像ファイルを自動生成します。クライアント側では画面サイズに応じた画像ファイルが読み込まれます。そのため、デバイスに応じた画像ファイルが転送されるため、エンドユーザーの通信容量を圧迫しません。
独自で開発したのは画像変換ツールだけではありません。RSS出力やサイトマップ出力なども自前で開発しています。WordPressが搭載している機能をくまなく用意しなければならないのは、自前の静的サイトジェネレーターの大変なところです。
記事をSPAの管轄外とした理由
今回は次のような構成でNuxt.jsとAMPの領域を分離しました。AMPとNuxt.jsのハイブリッド構成です。
AMPは、通常版HTMLページとAMP専用ページとして、2バージョンのファイルを配信するのが一般的です。ですが、記事ページはAMP専用ページのみ、1バージョンで配信しています。
AMPだけで提供するメリットは次の通りです。
- GoogleのAMP Cacheを利用でき、検索エンジンから遷移が爆速になる
- 通常のURL遷移だと、DNSルックアップやSSLなど時間のかかる処理が発生する
- いくらサーバー構成を頑張っても限界がある
- AMP CacheだとGoogle管理下のドメインで配置される
- まずプリコネクトによってDNSやSSLが解決された状態になる
- さらにAMPだとプリレンダリングされた状態になる
- 結果としてAMPだと通常のHTMLサイトには到達できない速度が実現されている
- 通常のURL遷移だと、DNSルックアップやSSLなど時間のかかる処理が発生する
- Nuxt.js製のSPAより、AMPのほうが初期読み込みが早い
- 記事ページへのダイレクトアクセスが多い
- ユーザーの流入は、検索エンジンやSNSからが多いから
- ダイレクトアクセスが多いとすると、SPAであることよりもページ表示が素早いAMPのほうがメリットがある
- 記事ページへのダイレクトアクセスが多い
- 開発視点で、通常版ページとAMP専用ページの2バージョンを開発するより、AMP専用ページのみを用意するほうが工数が少ない
検索エンジンからのアクセスが超高速になるのは、AMP配信の特権ですね。
▲検索エンジンで雷マーク⚡️が表示されるとAMP Cache対応であることを示す。雷マークがあると、一瞬で遷移できる
PWAとサービスワーカーの導入
フロントエンドの技術としては、PWA(プログレッシブ・ウェブ・アプリ)に対応しています。PWA自体は国内のウェブ事情において重要とは思いませんが、関連技術のサービスワーカーは高速化には欠かせません。サービスワーカーを導入すると強力なキャッシュ機構を構築できます。
一般的にキャッシュには、さまざまな種類があります。ウェブサーバーからクライアントにおけるまで、さまざまなフェーズにキャッシュを設けられます。サービスワーカーを導入すれば、ブラウザキャッシュよりも、ユーザーに近いところへキャッシュを残せるようになります。
ブラウザキャッシュはもちろん設定していますが、サービスワーカーでさらにキャッシュを細かく制御しています。たとえば、記事中の画像ファイルは「キャッシュ・ファースト」というルールにしているので、キャッシュが存在すればネットワーク通信を一切することなく画面に表示できます。
サービスワーカーは高速化のためだけでなく、オフライン時にキャッシュからページを表示できるメリットもあります。日本国内でネット回線が途切れることは少ないので必要性は高くないですが、PWAの要件の1つです。
サービスワーカーはGoogle製のJSライブラリ「Workbox」を使えば、手軽に導入できます。Nuxt.jsにもサービスワーカーを組み込むためのプラグイン「Nuxt PWA」が用意されています。
ユーザーインターフェイスの改善
最後に、UIデザインの話も紹介しましょう。ユーザーインターフェイスには次の改良を加えました。
- 運用で野暮ったくなったデザインの解消
- ダークモードなどのトレンドの取り込み
Safariのような先進的なブラウザを使うと、ICS MEDIAはダークモードで表示されます。
▲macOSのダークモード設定に連動して見栄えが変わる
▲一部のページでは、画面右上のボタンでテーマを切り替えられる
ダークモードのUIデザインは、macOS MojaveやWindows 10をはじめ、TwitterやYouTubeなどサービスでも採用されています。ユーザーの多様性にあわせたインターフェイスがトレンドとして今後伸びていくでしょう。
ダークモードの実装にはCSS変数が役立ちました。CSS変数は少ないコード量で実装できるので、コツさえ覚えてしまえば比較的簡単に導入できます。
このほかにも技術的にはCSS Gridやオフスクリーン・キャンバスなど新しい仕様もふんだんに取り込んでいますが、新しい機能が動作しない古いブラウザでは閲覧に支障がないよう最低限の配慮をしています。
サーバー構成
AWS S3とCloudFrontで構築しています。S3は静的ファイルのホスティングに、CloudFrontはCDNとして使っています。このあたりは王道の構成といったところでしょうか。
まとめ
技術は「捨てやすさ」が大事です。
「コンテンツ」としての原稿データは長い期間運用するものです。今回のリニューアルによって作られた「ガワ」としてのNuxt.js+AMPの構成は数年後には陳腐化するでしょう。ツールに依存しない「コンテンツ(マークダウンの原稿)」が「ガワ」から分離されていることで、新しい技術へ移行しやすくなると期待しています。
ICS MEDIAのリニューアル後の構成が汎用的なものだとは思いませんが、みなさまの技術選定の参考になれば幸いです。一般的にはContentfulやWP REST APIをヘッドレスCMSとして使って、フロントを実装することが多いようですね。
今後もICS MEDIAではHTMLコーディングやフロントエンド技術の最新情報を紹介していきます。ICSでは最新のフロントエンド技術に興味のあるエンジニアやUIデザイナーを募集しています。この記事に興味をもった方は「採用サイト」をご覧いただければ幸いです。