プログラミング入門

たった4行のリストに2MBも転送していた話:フロントエンドの無駄を見つけるデバッグ実践

「ページを開いたら一瞬だけ白くなって、その後全部表示される…」

こんな経験、ありませんか?ちょっとしたリストを表示するだけなのに、なぜか重い。原因を調べてみたら、たった4行のテキストを表示するために2MB近いデータを転送していた——そんな驚きの事例が話題になっています。

今回はこの実例をもとに、「フロントエンドのパフォーマンス問題をどうやって特定するか」を一緒に見ていきましょう! 🔍

なにが起きていたのか

frontend performance debugging
frontend performance debugging / Photo by Markus Spiske via Pexels

問題のページはシンプルな構成でした。顧客向けエリアに設置された、日付と見出しが並ぶちょっとしたリスト。エディターが手動で更新するだけの、いわゆる静的に近いコンテンツです。

ところがそのページを開くたびに、一瞬ブランク(白紙)になってからコンテンツが出現するという怪しい挙動が。体感的には「遅い」とは言えないかもしれないけど、何かがおかしい。

こういうときに最初にやるべきことは、ブラウザの開発者ツール(DevTools)でネットワークタブを開くことです 🛠️

DevToolsで原因を掘り下げる

ネットワークタブを開いてページをリロードしてみると、転送量が異常に多いことがすぐわかります。4行しかないリストなのに、合計で約2MBのデータが流れていたんです。

よくある犯人としては、こんなものが挙げられます。

  • 📦 巨大なJavaScriptバンドル:使っていない機能まで全部まとめてロードしている
  • 🖼️ 最適化されていない画像:WebP変換やリサイズをしていない
  • 🔁 不要なAPIレスポンス:表示に必要ないフィールドまでJSON丸ごと返している
  • 🧩 重いUIフレームワークの読み込み:ちょっとしたリストにフル機能のSPAを使っている

実際に確認する際は、こんなコードでAPIレスポンスのサイズを簡単にチェックできます。

# PythonでAPIレスポンスのサイズを確認するシンプルな例
import requests

url = 'https://example.com/api/items'
response = requests.get(url)

# バイト数をMBに変換して表示
size_bytes = len(response.content)
size_mb = size_bytes / (1024 * 1024)

print(f'レスポンスサイズ: {size_bytes} バイト ({size_mb:.2f} MB)')
print(f'HTTPステータス: {response.status_code}')

# JSONの中身を確認
data = response.json()
print(f'返ってきた件数: {len(data)} 件')
print(f'フィールド一覧: {list(data[0].keys()) if data else "空"}')

これを実行すると、「4件のリストを返しているだけのはずのAPI」が大量のフィールドを含むJSONを返していることが一目瞭然になります。

実際の犯人:APIが「全部入り」だった

この事例の場合、APIのレスポンスを詳しく見てみると衝撃の事実が判明しました。

表示に使っているフィールドは titledate の2つだけ。ところがAPIが返しているJSONには、本文全文・画像の埋め込みデータ・編集履歴・メタデータ・タグ・カテゴリ・関連コンテンツ…と、数十個ものフィールドが詰め込まれていました。

# 問題のある「全部入り」レスポンスのイメージ
bad_response = [
  {
    'id': 1,
    'title': '2024年1月のお知らせ',   # ← 使う
    'date': '2024-01-15',             # ← 使う
    'body': '...3万文字の本文...',    # 使わない
    'thumbnail': '...base64エンコードの画像データ...', # 使わない
    'author': {...},                  # 使わない
    'edit_history': [...],            # 使わない
    'related': [...],                 # 使わない
    # ...以下、延々とフィールドが続く
  },
  # × 4件分
]

たった4件のリストなのに、1件あたり500KB近いデータが含まれていたというわけです。これが4件で約2MB——謎が解けましたね。

解決策①:APIのレスポンスをスリム化する

最もシンプルな解決策は、APIが返すフィールドを必要最低限に絞ることです。

# Pythonで「必要なフィールドだけ」を返すAPIを作るイメージ(Flask使用)
from flask import Flask, jsonify

app = Flask(__name__)

# ダミーデータ(本来はDBから取得)
all_items = [
  {'id': 1, 'title': '1月のお知らせ', 'date': '2024-01-15', 'body': '...長い本文...', 'thumbnail': '...'},
  {'id': 2, 'title': '2月のお知らせ', 'date': '2024-02-10', 'body': '...長い本文...', 'thumbnail': '...'},
]

# ❌ 悪い例:全フィールドをそのまま返す
@app.route('/api/items/bad')
def get_items_bad():
    return jsonify(all_items)  # 不要データも全部流れる

# ✅ 良い例:必要なフィールドだけに絞る
@app.route('/api/items/good')
def get_items_good():
    slim = [{'id': item['id'], 'title': item['title'], 'date': item['date']} for item in all_items]
    return jsonify(slim)  # 必要なものだけ!

これだけで転送量が劇的に減ります。「全部返しておけば後で使えるかも」という発想が、こういった無駄につながりがちです。

解決策②:JavaScriptバンドルを見直す


もう一つよくある原因が、巨大なJavaScriptバンドルです。ReactやVueなどのSPAフレームワークを使っていると、ちょっとしたリスト表示のためだけに数百KBのJSファイルが読み込まれることがあります。

DevToolsの「ソース」タブや、Webpack Bundle Analyzerなどのツールを使うと、どのライブラリが何KBを占めているかが可視化できます。

# npmでBundle Analyzerを使う場合(ターミナルで実行)
# npm install --save-dev webpack-bundle-analyzer

# package.jsonのscriptsに追記
# "analyze": "webpack --profile --json > stats.json && webpack-bundle-analyzer stats.json"

# 実行
# npm run analyze

よくある改善ポイントとしては以下のようなものがあります。

  • 🗂️ コードスプリッティング:ページごとに必要なJSだけを読み込む
  • 🌲 Tree Shaking:使っていない関数・モジュールをビルド時に除外する
  • 📉 ライブラリの見直し:moment.jsをday.jsに換えるだけで数十KB削減できることも
  • 🚀 遅延ロード(Lazy Load):最初の表示に不要なものは後から読み込む

解決策③:キャッシュを活用する

静的に近いコンテンツなら、キャッシュを使うのも効果的です。毎回APIを叩くのではなく、一定時間はキャッシュしたデータを使い回すだけで、体感速度が大幅に改善します。

import requests
import time

# シンプルなインメモリキャッシュの実装例
cache = {}
CACHE_TTL = 60  # 60秒間キャッシュを保持

def get_items_with_cache(url):
    now = time.time()

    # キャッシュが有効ならそれを返す
    if url in cache:
        cached_data, cached_at = cache[url]
        if now - cached_at < CACHE_TTL:
            print('キャッシュを使用しました ✅')
            return cached_data

    # キャッシュがないor期限切れならAPIを叩く
    print('APIからデータを取得しています...')
    response = requests.get(url)
    data = response.json()

    # キャッシュに保存
    cache[url] = (data, now)
    return data

# 使い方
items = get_items_with_cache('https://example.com/api/items')
print(f'{len(items)} 件取得しました')

本番環境ではRedisやMemcachedを使うのが一般的ですが、原理はこれと同じです。「毎回サーバーに取りに行かなくていいもの」はキャッシュする——これだけでパフォーマンスが大きく変わります。

改善前後の比較

今回の事例を整理すると、こんな感じになります。

# 改善前後のイメージ比較
改善前:
  転送量: 約2MB
  内訳: 全フィールドJSON × 4件 + 重いJSバンドル
  初期表示: 一瞬白くなる(ブランク発生)

改善後:
  転送量: 約80KB(-96%!)
  内訳: 必要フィールドのみJSON × 4件 + スリム化したJS
  初期表示: スムーズに表示

96%削減——数字で見るとインパクトがありますね。やったことは「不要なフィールドを返さないようにした」「使っていないライブラリを整理した」というシンプルなことだけです。

パフォーマンス改善のデバッグフロー まとめ

今回の事例を踏まえた、フロントエンドのパフォーマンス問題を調査するときの基本フローをまとめます。

  1. 🔍 DevToolsのネットワークタブを開いて転送量・件数を確認
  2. 📊 Lighthouseタブでパフォーマンススコアを計測(Google提供のツールが内蔵されています)
  3. 🧐 APIレスポンスの中身を確認して、不要なフィールドがないかチェック
  4. 📦 JSバンドルのサイズを確認して、不要なライブラリを排除
  5. 🖼️ 画像の最適化(WebP変換・適切なリサイズ)を確認
  6. 🗄️ キャッシュ戦略を導入して無駄なリクエストを減らす

難しいツールは必要ありません。まずはブラウザのDevToolsを開くことが、パフォーマンス改善の第一歩です。

まとめ


「たった4行のリストなのに2MB転送していた」という一見ありえない話も、APIが全フィールドを返している・重いJSバンドルが読み込まれているといった、よくある原因が積み重なった結果でした。

フロントエンドのパフォーマンス問題は、「なんか重いな」という感覚を無視しないことが改善への入り口です。DevToolsを開いて数値を見るだけで、原因の大半はすぐに特定できます。

「遅い気がするけど、まあいいか」で放置せず、一度DevToolsで確認してみてください。きっと驚く数字が出てくるかもしれません 😄

📚 関連商品・おすすめ書籍

スッキリわかるPython入門 第2版 (スッキリわかる入門シリーズ)

もしも

スッキリわかるPython入門 第2版 (スッキリわかる入門シリーズ)

初心者に定番のPython入門書

Amazonで見る

実践Claude Code入門―現場で活用するためのAIコーディングの思考法

もしも

実践Claude Code入門―現場で活用するためのAIコーディングの思考法

AIコーディングの現場活用法を学ぶ一冊

Amazonで見る

Python Web開発実践入門 ―― FastAPIによるWebAPI開発と非同期処理

もしも

Python Web開発実践入門 ―― FastAPIによるWebAPI開発と非同期処理

FastAPIでWebAPI開発を実践的に学ぶ

Amazonで見る

※本記事にはアフィリエイトリンクが含まれます。

ABOUT ME
やまちゃん
これまで学生と社会人を合わせて5000人以上にプログラミング学習を指導。 ゼロからイチをわかりやすく解説する専門家として活動しており、本業ではArduinoを用いたIoT開発とロボットプログラミングが専門。 Pythonを用いたアプリ開発、ウェブアプリケーションの開発で業務の効率化をサポートしています。

COMMENT

メールアドレスが公開されることはありません。 が付いている欄は必須項目です