2024.12.19
システムの穴を運用でカバーしようとしてミス多発… バグが大量発生、決算が合わない状態から業務効率化を実現するまで
リンクをコピー
記事をブックマーク
宍戸俊哉氏(以下、宍戸):フロントエンドの話をしていきます。「高速化のためにフロントエンドですべきこと」を4つあげさせてもらいました。「あとでいいことはあとでやる」「必要なことは先にやる」「使い回せるものは使いまわす」「クライアントにとって最適なものを配信する」。だいたいこの辺の原則に則って今のフロントエンドの高速化のプラクティスってあるのかなと思っています。
「あとでいいことはあとでやる」というところで、1つはクリティカルレンダリングパスですね。これを減らしていくというところですね。
クリティカルレンダリングパスはもう説明いらないかなと思うんですけど、CSS、JavaScriptのファイルが読み込みにいくときにレンダーブロッキングを発生させているので、なるべく非同期化したり、インラインしたりしようというところですね。
JavaScriptは基本的に全部非同期で読み込むようにしています。普通にasync/deferをつけてscriptタグから読み込むという方針でおおむねよいと思うんですけど、r.nikkei.comの場合はpolyfill serviceというライブラリを使っています。このライブラリはブラウザ間によってはまだ実装されていないAPIなどの差分を吸収してくれるサービスです。
こいつを使っているのでほかのコードというのは全部polyfillが存在する前提で書いているんですね。なので、polyfillをロードしてからほかのスクリプトを実行するような書き方をしています。DOMContentLoadedは一切使わずに、ほとんどのものがpolyfillのonloadイベントをキャプチャして初期化するようになっています。
CSSはどうかというと、Critical CSSという概念があると思うんですけど、一番最初に画面に映るスタイル以外は全部あとから読み込もうというようなアプローチですね。
これやるとCSSのクリティカルレンダリングパスをなくすことができるんですけど、r.nikkei.comでは、いろいろ試行錯誤はしたんですけど、まだ入っていないです。なんでかというと、会員種別によって画面が違うだとか、レスポンシブ対応が必要だとか、そういった要素が入ってきてまだうまく行ってないですね。
ライブラリとしては自動生成するものが、npmの「critical」というやつと、あとはGoogleのPageSpeed ModuleというのがNginxのプラグインを出していて、そいつが動的にCritical CSSをインラインに埋め込むというようなライブラリがあったりします。
たぶんこれでも、いろいろトライした結果、「最終的にはマニュアルで全部メンテしていく勇気と覚悟が必要そう」という結論に今はいたっています。
次はセクションの遅延ロードですね。画像は遅延ロードするのはみんなやっているかなと思うんですけど、r.nikkei.comだとセクションごとに遅延ロードを行ったりしています。
「コンテンツのサイズ」というのはDOMノードの大きさとか深さですね。これはパフォーマンスにすごい大きく影響してきて、モバイルだとさらに顕著だったりします。
今のPCの日経電子版ってトップページだけだと60記事以上リンクがあって、ビジネスサイド的には全部出してほしいというような要望があったので対応しました。最上部除いてセクションごと全部遅延読み込みさせるような仕組みで、初回レンダリングのコストを下げる工夫をしています。
セクションのLazy Loadingをやるために「スケルトンスクリーン」というのを実装していました。これはなにかというと、Intersection Observerを2回に分けて非同期で読み込むような処理ですね。
最初に長めのthresholdでIntersection ObserverでスケルトンだけのセクションをDOMに追加します。そのあとスクロールが進んできたら実体で入れ替える。
そうすることで、このIntersection Observerの長めの1回目の読み込みでこのスケルトンスクリーンに出しているDOMサイズを減らす処理をしています。これによってリフローもあんまり起きないかなという感じですね。
それと「必要なことは先にやる」というところで、HTTP/2のServer Pushですね。画面の表示に必要になるリソースというのはなるべく速く読み込むようにする必要があって、これもFastlyのHTTP/2の機能を有効化して実現しています。
Curlでちょっと見づらいんですけど、Curlでr.nikkei.comのトップページを叩いてみると、中は死ぬほどLinkヘッダが入っているんですね。
効率最適化できているかというと自信ないんですけど、トップページの表示に必要になるリソースを基本的にリンクヘッダに一緒につけてあげて、ブラウザのPush Cacheの中に入れておく。そうすると、index.htmlを読み込んだあとに、例えばCSS取りに行ったりJS取りに行ったりでネットワークリクエストを発生させずに返すことができる仕組みになっています。
次はResource Hintsですね。日経電子版だと、朝夕刊といってその日の紙の新聞とまったく同じ構成の記事を表示するページがあります。
ほとんどユースケースとしては、毎日紙の新聞を読む人が1面からなんとか面までずっとガーって読んでいくのと同じように、各面をバッと舐めるように閲覧するユーザーが多いんですね。次のページはResource Hintsでキャッシュしてしまおうという処理ですね。これはprefetchというものを使っています。
prerenderとdns-prefetchというのも使っていて。prerenderは検索への導線ですね。マウスカーソルがアイコンに近づいたらリンクタグを動的に挿入します。あとは広告のサードパーティドメインに対してdns-prefetchをするなどして先読みを行っています。
あとはService Workerを使った事前キャッシュですね。トップページやその画面のページからPostMessageを投げて、Service Workerの中でAPIから記事の一覧を取りに行って、その返ってきた記事の一覧から実際に記事のオブジェクトを取り出すというような処理ですね。その返ってきたオブジェクトをService WorkerのCache APIの中に入れてあげる感じですね。
だいたいこれを使うと記事のページというのは20〜30msぐらいで返せるようになっています。あとはオフラインで使えるようになるなどいろいろな恩恵があります。
サブリソースは、先ほどのService Workerのレスポンスからだと記事のページのレスポンスは取れるんですけど、必要になるJSとかCSSとかそういうサブリソースが取れないんですね。
それはService Workerの中でレスポンスヘッダをパースしてあげて必要なリンク、必要なサブリソースのURL一覧を取ってきて、それをService WorkerのaddAllを使ってキャッシュすることで実現しています。
キャッシュ同期の問題というのがありまして、ログインしたとき、あとは非ログインのとき、古いキャッシュがどうしても残ってしまうというのがあります。有料会員のはずなのに「この記事は有料会員限定です」という画面が表示されてしまいました。
古いキャッシュがストレージに残っているというのも問題というところで、それにどう対応してるかというと、ログイン・ログアウトのURLをService Worker内でキャプチャして対応しています。そのログイン・ログアウトのURLをキャプチャして該当のURLが来たらキャッシュ削除する処理ですね。
もう1つはpostMessageですね。Service Worker内、Service Workerから返されたレスポンスに含まれるユーザーの会員属性、それとCookie内に保持している最新の会員属性。それが違えばクライアントからService Workerにメッセージを投げてキャッシュ削除するという形ですね。
古いキャッシュの削除どうやってやっているかというと、キャッシュしたURLとタイムスタンプをIndexedDBに入れています。そのIndexedDBに入れたデータとCache Storage内のリソースを同期させることで実現しています。
だいたいこんな感じですね。
BackgroundSyncを使ってService Workerにキャッシュ要求を投げて、Service Workerは新しいキャッシュ要求を行う前にIndexedDBを参照して、そして古いキャッシュが残っていればそれを削除するといった処理ですね。
「使いまわせるものは使いまわす」は一般的な話なんですけど、静的ファイルにはハッシュ値をつけて長時間キャッシュするようにしています。リロードの対策としてimmutableをつけてあげると、リロード時もキャッシュの再読み込みがなくてよいなという感じですね。
デザインシステムですね。UIコンポーネント。「NIKKEI UI」というコンポーネントベースのスタイルガイドを作成していて、それをr.nikkei.comでは使うようにしています。
どういうメリットがあるかというと、マークアップの開発コスト削減やスタイル定義が重複しないように開発ができます。UIに一貫性が出ることと、アクセシビリティ、このあたりを担保できます。
いろいろキャッシュの話をしてきたかなと思うんですけど、あなたのキャッシュはどこから? 私は鼻から……。あ、これ言いたかっただけです(笑)。
(会場笑)
どこからキャッシュしたのかけっこうわからなくなるんですけど、これは現状アクセスログ、Chrome Dev ToolsのNetworkパネルのInitiator、あとはsizeの部分から判断するしかないかなと思っています。あとはApplicationタグを使うとService Workerの設定でBypass for networkというチェック項目があるので、それを使ってService Workerを無効化する。
このあたりはサイト高速化の教科書とも言っていい『超速! Webページ速度改善ガイド』、これを読むといいかなと思っています。
「最適なリソースを配信する」というところでpictureタグですね。pictureタグを使ってクライアントの画面幅に合わせて最適な大きさの画像を設定しています。
これはHandlebarsのヘルパーを使って実装しています。
これつい先週のやつなんですけど、画像配信を少し見直したんですね。今までjpeg画像のクオリティはけっこう高めに設定してたんですけど、見た目に大きな変更のない範囲で、見た目に大きな劣化のない範囲で変更して、だいたいコンテンツのサイズが半分ぐらい改善することができました。
Performance Budgetを定義しておくと、定期的にBudgetオーバーしてるから改善しなきゃねというきっかけになるので便利です。
「Network Information APIが使えるよ」というところで、通信の種別環境の種類を取得できるAPIなので、Wi-Fiかcellularなのか、3Gなのか4Gなのか、Round-Trip Timeなのか、こういったものが取得可能になります。
Service Workerで大きめなリソースをガッとキャッシュすることがあるんですけど、そういうのはWi-Fi接続時のみに限定したりしています。
最後まとめになります。高速化は一番根本的なUX改善になるのかなと思っています。
まずは分析です。Lighthouseを使ったりwebpagetestを使って分析をしていきましょう。SpeedCurveなどを使って継続的にモニタリングできる仕組みを作ると、一気にパフォーマンス改善というのはやりやすくなります。フロンドエンドだけじゃなくてCDNやサーバサイドのパフォーマンスというのも重要になっています。
あとはキャッシュの効率化、クリティカルレンダリングパスの削減、そういう手がつけられるわかりやすいところから始めるといいのかなと思ってます。さっきのこの画像と同じように、パフォーマンスの改善というのは定期的にやっていくとよいです。そのときにBudgetを定義しておくとやりやすいです。
速くすることを考えるよりも、遅くなる要素を減らしていくことが一番大事かなと思っています。
以上です。ありがとうございました。
(会場拍手)
関連タグ:
2024.12.12
会議で発言しやすくなる「心理的安全性」を高めるには ファシリテーションがうまい人の3つの条件
2024.12.19
12万通りの「資格の組み合わせ」の中で厳選された60の項目 532の資格を持つ林雄次氏の新刊『資格のかけ算』の見所
2024.12.16
32歳で成績最下位から1年でトップ営業になれた理由 売るテクニックよりも大事な「あり方」
2023.03.21
民間宇宙開発で高まる「飛行機とロケットの衝突」の危機...どうやって回避する?
2024.12.10
メールのラリー回数でわかる「評価されない人」の特徴 職場での評価を下げる行動5選
2024.12.13
ファシリテーターは「しゃべらないほうがいい」理由 入山章栄氏が語る、心理的安全性の高い場を作るポイント
PR | 2024.12.20
モンスター化したExcelが、ある日突然崩壊 昭和のガス工事会社を生まれ変わらせた、起死回生のノーコード活用術
2024.12.18
「社長以外みんな儲かる給与設計」にした理由 経営者たちが語る、優秀な人材集め・会社を発展させるためのヒント
2024.12.12
今までとこれからで、エンジニアに求められる「スキル」の違い AI時代のエンジニアの未来と生存戦略のカギとは
PR | 2024.11.26
なぜ電話営業はなくならない?その要因は「属人化」 通話内容をデータ化するZoomのクラウドサービス活用術
Climbers Startup JAPAN EXPO 2024 - 秋 -
2024.11.20 - 2024.11.21
『主体的なキャリア形成』を考える~資格のかけ算について〜
2024.12.07 - 2024.12.07
Startup CTO of the year 2024
2024.11.19 - 2024.11.19
社員の力を引き出す経営戦略〜ひとり一人が自ら成長する組織づくり〜
2024.11.20 - 2024.11.20
「確率思考」で未来を見通す 事業を成功に導く意思決定 ~エビデンス・ベースド・マーケティング思考の調査分析で事業に有効な予測手法とは~
2024.11.05 - 2024.11.05