未分類
財務データ全量表示の遅延読み込み設計
概要
proportional-animation-qqq.vueページの「財務データ一覧」セクションに、SQLiteに格納された全メトリクスを表示する機能を追加した際の設計について記録する。
背景と課題
現状のアーキテクチャ
data/koyfin.db (SQLite)
↓ [node scripts/generate-financial-data.mjs]
app/composables/financial-data.ts (3.4MB)
↓ [import]
app/pages/financial-quiz/proportional-animation-qqq.vue
- チャート表示に必要なメトリクスのみを TypeScript ファイルに事前生成
- 初期ロード時にすべてのデータが読み込まれる
- 問題: DBには約100種類のメトリクスがあるが、チャートでは約30種類のみ使用
要件
- 「財務データ一覧」で全メトリクスを表示したい
- しかし、全メトリクスを TypeScript に含めると初期ロードが重くなる(推定 30MB+)
解決策: 遅延読み込み (Lazy Loading)
アーキテクチャ
data/koyfin.db (SQLite)
↓ [node scripts/generate-raw-metrics.mjs]
public/data/raw/{TICKER}.json (50-60KB/企業)
↓ [fetch() on demand]
app/components/financial-quiz/FinancialDataTable.vue
ポイント:
- チャート用データ: 従来通り TypeScript で即時読み込み
- 全メトリクス: JSONとして
public/data/raw/に配置し、タブクリック時に fetch
データフロー
┌─────────────────────────────────────────────────────────────┐
│ Initial Load │
├─────────────────────────────────────────────────────────────┤
│ financial-data.ts (3.4MB) │
│ └─ チャート用メトリクス ~30種類 │
│ → BS/PL/CF図、収益チャート、バリュエーション等 │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ On "全データ" Tab Click │
├─────────────────────────────────────────────────────────────┤
│ fetch(`/data/raw/${ticker}.json`) │
│ └─ 全メトリクス ~100種類 (50-60KB) │
│ → セクション別テーブル表示 │
└─────────────────────────────────────────────────────────────┘
実装詳細
1. データ生成スクリプト
ファイル: scripts/generate-raw-metrics.mjs
// 使用方法
cd apps/web
node scripts/generate-raw-metrics.mjs
// 出力
public/data/raw/{TICKER}.json // 101企業分
出力JSONの構造:
{
"ticker": "NVDA",
"periods": ["2016", "2017", ..., "LTM"],
"sections": [
{
"id": "highlights",
"label": "ハイライト",
"metrics": [
{
"name": "Diluted EPS",
"values": {
"2016": "0.03",
"2017": "0.06",
...
}
}
]
},
{
"id": "income_statement",
"label": "損益計算書",
"metrics": [...]
}
// ... 他のセクション
]
}
セクション一覧:
| ID | 日本語名 |
|---|---|
| highlights | ハイライト |
| income_statement | 損益計算書 |
| balance_sheet | 貸借対照表 |
| cash_flow | キャッシュフロー計算書 |
| profitability | 収益性指標 |
| multiples | マルチプル(株価倍率) |
| enterprise_value | 企業価値 |
| solvency | 安全性指標 |
| roic | ROIC関連 |
2. コンポーネント実装
ファイル: components/financial-quiz/FinancialDataTable.vue
<script setup lang="ts">
// タブ状態
const activeTab = ref<'summary' | 'raw'>('summary')
// rawデータの状態
const rawData = ref<RawData | null>(null)
const isLoading = ref(false)
const loadedTicker = ref<string | null>(null)
// 「全データ」タブクリック時に読み込み
async function loadRawData() {
activeTab.value = 'raw'
// キャッシュチェック: 同じtickerなら再読み込みしない
if (loadedTicker.value === props.company.ticker && rawData.value) {
return
}
isLoading.value = true
try {
const response = await fetch(`/data/raw/${props.company.ticker}.json`)
rawData.value = await response.json()
loadedTicker.value = props.company.ticker
} catch (e) {
loadError.value = `データの読み込みに失敗しました`
} finally {
isLoading.value = false
}
}
// 企業切り替え時: rawタブなら自動再読み込み
watch(() => props.company.ticker, () => {
if (activeTab.value === 'raw') {
loadRawData()
}
})
</script>
ファイルサイズ比較
| ファイル | サイズ | 読み込みタイミング |
|---|---|---|
| financial-data.ts | 3.4MB | 初期ロード |
| raw/{TICKER}.json | 50-60KB | タブクリック時 |
| 全rawファイル合計 | 5.4MB | - |
効果: 初期ロードサイズを増やさずに全メトリクス表示を実現
設計のメリット
- 初期ロード維持: チャート表示に必要なデータのみ初期読み込み
- オンデマンド読み込み: 全データが必要な場合のみ追加fetch
- キャッシュ効率: 同一企業の再読み込みを防止
- CDN対応:
public/配下の静的JSONはCDNキャッシュ可能 - デプロイ簡素化: JSONは静的ファイルとしてビルドに含まれる
Cloudflare Pages の容量制限
無料枠での制限と現在の使用状況:
| 制限項目 | 上限 | 現在の使用状況 | 余裕 |
|---|---|---|---|
| 1ファイルあたり | 25 MB | 50-60 KB | 十分 |
| ファイル数 | 20,000 ファイル | 101 ファイル | 十分 |
| 総デプロイサイズ | 1 GB | 約 5.4 MB | 十分 |
| 月間デプロイ回数 | 500 回 | - | - |
| 帯域幅 | 無制限 | - | - |
将来的なスケーリング
- 1000企業に増えても約 60MB(1GB上限には余裕)
- ファイル数も 20,000 の上限に対して余裕
- 25MBを超える大きなファイルが必要な場合は Cloudflare R2 を検討
注意事項
データ更新時の手順
SQLiteデータが更新された場合:
cd apps/web
# 1. チャート用データを再生成
node scripts/generate-financial-data.mjs
# 2. 全メトリクスJSONを再生成
node scripts/generate-raw-metrics.mjs
# 3. ビルド&デプロイ
pnpm build
スクリプトの制限事項
generate-raw-metrics.mjsは年次データ (Annual) と LTM のみ出力- 四半期データは含まれない(必要であれば別途対応)
関連ファイル
scripts/generate-raw-metrics.mjs- JSON生成スクリプトcomponents/financial-quiz/FinancialDataTable.vue- 表示コンポーネントpages/financial-quiz/proportional-animation-qqq.vue- 親ページcomposables/financial-data.ts- チャート用データ