この記事は、anyプロダクトチーム Advent Calendar 2025、6日目の記事となります。
こんにちは! any 株式会社のプロダクトチームに参画している @thesugar です。
私は Web 開発を中心に業務を行っているエンジニアで、普段はフロントエンドを触ることが多いです。
今回は any アドベントカレンダーの記事ということで、実際のプロジェクトで直面した課題とその調査および対応策について紹介します。
きっかけ
今年の春頃、 any が提供するナレッジマネジメントアプリ Qast の開発において、スマートフォンブラウザ UI リニューアル(ご参考)というプロジェクトを進めていました。
社内での動作テスト中、「スマホで見ると画面表示が遅い」というフィードバックがありました。
それを受けて自分も改めて確認してみると、どうやらスマホにかぎらず、PC であっても Safari で開いたときに、画面表示が遅いページがたしかにありました。
これまでは PC(Chrome)での利用がメインのプロダクトでしたが、すべてのページで発生しているわけではないということもあり、スマホ対応に伴い Safari での利用を前提に入念に検証を行ったことで今回初めて顕在化したようです。
調査
調査開始
さっそく調査に着手しました。まずは Safari の Dev Tool の「タイムライン」タブを見てあたりをつけていきますが、出てくるログが多いうえ、処理にかかっている時間が長いものからソートして調べていっても糸口が見出せず。
Dev Tool から離れてソースコードを具体的に見ていくことにしました。仮想スクロール技術を使用している箇所や、CSS の指定、コンポーネント構造(DOMの組み立て)など、少しでも原因になりえそうな部分を一つずつ見直す作業を行なっていきました。
しかし原因はなかなかわからないまま。呼び出している関数や、画面に表示する何らかの要素を丸ごと消して「この関数や要素を消しても変化なし」など一つずつ地道に調査していきました。
ようやく見つけた手がかり
そうして調べていくなかで、ようやく「この要素があるかないかで読み込みの速度が全然違うぞ」というものを見つけました。
<!-- ページ表示が遅くならない -->
<div>こんにちは</div>
<!-- ページ表示が遅くなる -->
<div>こんにちは😄</div>
つまり、絵文字があるだけで画面表示が遅くなっていたのです。そして、実際には絵文字そのものが問題ではなく、アプリケーションで指定していた font-family との組み合わせと関係がありました。
原因
原因は font-family に指定されていた Noto Color Emoji フォントのようでした。
Noto Color Emoji は CBDT/CBLC 1 という形式のカラーフォントですが、Safari はこの形式をサポートしていません。
参考: https://github.com/googlefonts/noto-emoji?tab=readme-ov-file#using-notocoloremoji
NotoColorEmoji uses the CBDT/CBLC color font format, which is supported by Android and Chrome/Chromium OS. Windows supports it starting with Windows 10 Anniversary Update in Chrome and Edge. On macOS, only Chrome supports it
Safari 環境で Noto Color Emoji が絵文字テキストに対して実際に適用されると、Safari の描画エンジンにおいてフォントの解析などの内部処理になんらかの問題をきたし、結果としてパフォーマンスが悪化していたものと思われます。
対応
実際のアプリケーションで使用しているフレームワークは Next.js だったので、_document.tsx にて User Agent を判定し、Safari では <link> に Noto Color Emoji を含めないようにしました。
これにより、Chrome 等ではこれまで通り Noto Color Emoji が読み込まれますが、Safari では当該フォントリソースが読み込まれず、パフォーマンスの劣化が起こらなくなりました。
// _document.tsx の getInitialProps 内などで判定
const userAgent = ctx.req?.headers['user-agent'] || '';
const isSafari = /^((?!chrome|android).)*safari/i.test(userAgent);
// render 内
{!isSafari && (
<link
href="https://fonts.googleapis.com/css2?family=Noto+Color+Emoji&display=swap"
rel="stylesheet"
/>
)}
再現
今回はたまたま Next.js で構築しているアプリにて事象が確認されましたが、Next.js 固有の問題ではありません。
素の HTML で試してみても再現します。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Emoji font test</title>
<link rel="preconnect" href="https://fonts.gstatic.com" />
<link
href="https://fonts.googleapis.com/css2?family=Noto+Color+Emoji&display=swap"
rel="stylesheet"
/>
<style>
body {
font-family: "Roboto", "Noto Sans JP", "Noto Color Emoji", sans-serif;
}
</style>
</head>
<body>
<div>😄</div>
</body>
</html>
HTTPサーバーを起動するといったことをするまでもなく、ローカルのファイルをブラウザで表示するだけで事象が確認できました。

図1. 絵文字を表示する場合:レイアウトの処理で 1.5s ほどかかっており、体感としても画面を開いてから描画完了まで少し待つ感覚

図2. 通常のテキストを表示する場合:すべて ms 単位で処理が終わっており、画面を開くと同時にテキストが見える
通常のテキストの表示に比べて、絵文字の場合はページの表示が遅いのがわかると思います。
これは簡易的なサンプルですが、実際のアプリケーションにおいて、複数の箇所で絵文字が使用されていたり、ある程度複雑な DOM 構造の中に絵文字が存在していたりするとさらに画面表示は遅くなってしまいます。
終わりに
今回は、実際のアプリケーションで発生したパフォーマンス低下事例と、その調査過程および原因と対策について紹介しました。
調査はなかなか地道なステップの連続で、かつ今回のような調査だと AI からもなかなか有効なアドバイスを引き出しづらく、最終的な原因が絵文字の表示という予想外の点であったことも印象的でした。フロントエンドにおけるパフォーマンス改善の実際の様子をお伝えできたのではないかと思います。
any 株式会社では、ユーザー体験まで丁寧に追いかけて改善を積み上げていく姿勢を大切にしています。
私は any フレンズ2として参画していますが、立場を問わず垣根なくものづくりに向き合える環境に魅力を感じています。
興味を持っていただけた方はぜひ以下のページもご覧ください。
-
CBDT/CBLC: OpenType 仕様で定義された、ビットマップ形式のカラーフォント(特に絵文字)の画像データとその位置情報を格納するためのフォントテーブル。
参考: https://learn.microsoft.com/en-us/typography/opentype/spec/cbdt, https://learn.microsoft.com/en-us/typography/opentype/spec/cblc ↩ -
any では、業務委託など正社員以外の雇用形態で関わる人を any フレンズと呼ぶ文化があります。 ↩