Today I Learned

日々の仕事と学びの振り返りです。何をして、何を学んだかを記録します。

2026년 10월

2026-10-01

「関連テストだけ実行する」は、グラフを信用できないときに全体実行へ戻るルールがあって初めて安全になる

並列作業のたびに全体の単体テストを繰り返していたプッシュフックと PR の CI を、変更ベースの選択実行に切り替えながら、基準点を推測しない方法と、削除・グローバル設定の変更を全体実行へ回すルールを整理した記録

  • 変更ベースのテスト選択は import グラフの精度に頼る最適化なので、グラフを信用できない変更(削除・名前変更・グローバル設定)を全体実行へ流すルールが一緒に必要である
  • 基準点は推測しない。CI は PR の base コミット、プッシュフックは Git が渡してくれる以前のリモート SHA を使い、新しいブランチは人が明示する

2026년 9월

2026-09-25

2つのキーを同時に2回押したら、一方向にしかダッシュしなかった — 最初のイベントで確定しない

ブラウザは同時に押したキーもkeydownイベントとして別々に送るため、最初のキーで方向を確定すると2つ目のキーを合成できないことと、50msの収集ウィンドウで解決した方法

  • ブラウザは同時に押したキーも、キーごとにkeydownイベントを順番をつけて別々に送ります
  • 最初のキーイベントで結果を確定すると、イベントの間にフレームやシミュレーションのステップが挟まった時点で、2つ目のキーを合成できなくなります
2026-09-18

ロックで1件ずつしか処理しないサーバーの前では、キューよりもワーカー内のジッター付きリトライが先です

同時に送信されたフォーム数件が「ただいま混み合っています」で失敗していた問題を、キューとワーカーに分けて解決しながら、キューの再配信だけでは競合が解消されないことと、例外をackすると静かに失われることを確認した記録

  • 相手がロックで1件ずつしか処理しない場合、キューの再配信だけでは競合は解消されません。再配信も同じ時刻に集中してまた衝突するので、ワーカー内のランダムなジッター付きリトライが先で、キューのバックオフは障害用です
  • すでに「受付完了」と答えた後は、ワーカーが想定外の例外をackしてはいけません。ackはそのまま静かな消失です

2026년 8월

2026-08-23

再利用可能なテーブルコンポーネントを型で固める

カラム配列からソートキーの union を導出し、ドメインごとに異なる行の型を合成コンポーネントの各パーツまで届けながら学んだこと — そしてその過程で何度も顔を出した変性の話

  • 値から型を導出する書き方と const 型パラメータはセットです。どちらか一方が欠けると、もう一方もエラーなく静かに無意味になります
  • const 宣言には型パラメータを付けられないので、ジェネリックな context は関数のクロージャの中で作る必要があります
2026-08-14

実装より先に正解の基準を固定する

コード生成ツールに作業を任せる際、判定基準を先に文書化し、コード・画面・レビュー意見を証拠へ格下げし、確信が足りなければ止める設計を整理した

  • 判定基準の出どころを人と承認済み仕様に限定すると、実装を仕様と取り違える失敗が消える
  • 完了の定義をテスト通過の後ろへ動かすと、assertion を緩める理由がなくなる
2026-08-09

ブラウザ拡張機能のリクエスト応答と変更通知を分けて追跡する

分離された拡張機能の実行空間でメッセージベース RPC によって保存を依頼し、変更信号と query 無効化で別画面が単一の原本を読み直す流れを整理した

  • Chrome メッセージ API は転送手段であり、リクエスト検証・ルーティング・エラー応答はアプリケーションが定義する
  • 命令応答と別画面への変更通知は目的が異なるため分離する
2026-08-07

中間層は何を通し、何を推測するのか — プロキシ・入力確定・画像比率

rewrite がアップストリームの 3xx をそのまま流して起きた無限リダイレクト、変換が終わる前に確定された日本語入力、16:9 と推測されていた画像比率 — 中間層の素通しと推測を点検して学んだこと

  • rewrite はリダイレクトではなくプロキシなので、アップストリームの 3xx をそのままブラウザへ渡す
  • 日本語入力のバグは値の正規化ではなく、まずコミット境界の問題として切り分ける

2026년 7월

2026-07-31

旧ブラウザ互換は babel 一つではない — 構文・ポリフィル・条件ロード・スモークの多層契約

5 年超の旧ブラウザでアプリが丸ごと死ぬバグを直しながら学んだこと — 複数の機能が同時に死んだらハイドレーションを疑い、構文ダウンレベルとランタイムポリフィルを分離し、ポリフィルは feature-detect で旧ブラウザにだけロードし、スモークは実際のインタラクションを実行する

  • 複数の UI 機能が同時に死んだら、個別のバグではなくハイドレーション/バンドルのパースといった共通の根本原因をまず疑う
  • 構文ダウンレベル(babel)とランタイム API(ポリフィル)は別々のレイヤーである — トランスパイラは構文は変えても存在しない関数は作らない
2026-07-25

初回ペイントスプラッシュとオフラインファースト — ISR を守りつつ即時反映する

ネイティブアプリのようなローディングスプラッシュを初回ペイントから表示しつつボットには隠すインラインスクリプト技法、そしてオフラインファーストで『自分の書き込みの即時反映』を staleTime ではなく invalidate と durable キューで作る方法

  • 初回ペイント前の表示 + ボット隠蔽はインラインブロッキングスクリプト注入 — UA ゲートは headers() で ISR を dynamic に壊す
  • react-query で「自分の書き込みの即時反映」は staleTime を下げるのではなく書き込み後の invalidateQueries で作る(invalidate は staleTime を無視)
2026-07-24

LCP のボトルネックが画像ではなく hydration のとき、そして節度あるスクロールモーション

ランディング性能を改善して学んだこと — LCP が遅いのに画像が小さいなら render delay(hydration)を疑いクライアント JS を外す、派手なスクロールモーションより進入スタッガーリビール、構造化データは画面と 1:1

  • LCP が遅いのに TBT が 0 で画像が小さければ element render delay(=クライアント境界の hydration)を疑い、そのサーフェスのクライアント JS を外す
  • 派手なスクロール従属モーション(scroll-jacking)より短いビューポート進入スタッガーリビールが汎用的な正解であることが多い
2026-07-23

断続的に崩れる画像 — objectURL レース、WebP フォールバック、サービスワーカーシェル

リロードのたびに見えたり見えなかったりする画像バグを追って学んだ三つ — objectURL のライフタイムレース、ブラウザ専用 lib のテスト hang 防止、サービスワーカーのシェルフォールバックを navigation リクエストに限定すること

  • サーバーが URL で渡す画像は objectURL blob で包まず直接レンダリングする — createObjectURL のライフタイムレースを根本から取り除く
  • ブラウザ専用(canvas)lib をテスト経路に入れるときは、実行前の同期 capability ゲートで jsdom の hang を防ぐ
2026-07-22

無限リスト機能をコードなしで移す — クリーンルーム契約と keyset ページネーション

仮想化された無限リスト+スクロール復元機能を別スタックへ移しながら学んだこと — 実装コードではなく見た目の振る舞いを契約として書くクリーンルーム方式、そして無限スクロールの安定性を左右する offset と keyset ページネーション

  • 機能を移す文書は「使ったライブラリ」ではなく「外からどう振る舞い、失敗時に何を保証するか」を契約として書く
  • 無限スクロールリストの安定性は大半がページネーション方式で決まる — offset は挿入/削除で重複・欠落、keyset は値基準なので安定
2026-07-20

公開面・分析ファサード・モーションゲートで学んだこと

構造化データと可視 FAQ の一致、auth 解決後の fetch ゲート、分析イベントのファンアウトファサード、prefers-reduced-motion JS 遷移ゲートを汎用概念として整理した TIL

  • 構造化データ(FAQPage など)は、画面上に表示されるテキストと同じソースから出すべきである
  • 保護 API はセッションローディングが終わった後にだけ有効にし、ローディング中は !user だけで匿名・fetch を決定しない
2026-07-14

開発環境を整備していて出会った汎用概念:シェルの引用符・モノレポ公開・CIランナー・ガード設計

ツール・インフラを整備しながら遭遇したシェルの単語分割、workspace公開の書き換え、CIランナーの不一致、fail-openガードを汎用概念として整理したTIL

  • シェル変数に入ったパスは空白があると引用符なしで使うと複数の引数に分割され、コマンドが静かに壊れる
  • モノレポ内部の依存はworkspaceプロトコルでリンクし、公開時に実際のバージョンへ置換するマネージャーで上げるべきだ
2026-07-13

星明かりグラフ・SW キャッシュ・Playwright triage・ESLint guardrail

Canvas 星ノード、Service Worker SWR・generation セキュリティ、CI flaky 分類、デザインシステム ESLint guardrail を一日で整理した TIL

  • Canvas ノード装飾は ID ハッシュで安定化し、globalAlpha・shadowBlur は描画直後に必ず復元する
  • Playwright CI が赤いときは retry 結果で flaky と deterministic failed を先に分ける
2026-07-11

ホームヒーローの scroll-driven ナラティブ演出

GSAP なしで sticky scrolly·CSS keyframes·view-timeline を使い、TIL→Knowledge 昇格デモとパイプラインセクションを実装した一日

  • sticky scrolly はラッパーの高さぶんスクロールの時間軸を作り、phase は進行度から派生させると JS が薄くなる
  • ヒーローのライブデモは clip-path steps ワイプ + animation-delay だけでループを作れる
2026-07-10

Modal peek スタックと CSS layer パッケージ

単一 dialog 内の document push と @layer ベースの editor CSS 分離で、peek UX とテーマのカスタマイズを合わせた一日

  • gallery→peek は dialog を新しく開くより、同じ shell で documentId だけ替えるほうが連続的だ
  • async resolve は (newId, oldContent) 中間フレームを render-time reset で防がねばならない
2026-07-09

階層型ドキュメントナビと viewer バンドル分離

page push/peek navigator と read-only viewer entry の分離で、ポートフォリオのデモ深度とバンドルを同時に合わせた一日

  • ドキュメントグラフは page ブロック + push/peek navigator 契約で flat editor と分離するほうがよい
  • peek·embed は editor と DOM は同じでも import graph が違ってこそ viewer バンドルが小さくなる
2026-07-08

モバイルのポインタジェスチャとサーバ画像プロキシ

タッチのドラッグ・リサイズの安定化と、unoptimized 環境で画像プロキシにより転送バイトを減らした一日

  • タッチで引いてもページが一緒にスクロールしないようドラッグ動作を直した
  • 画像は原本まるごとではなく必要なサイズだけ送るようプロキシを付けた
2026-07-07

ネストされたUIの再レンダーをO(1)へ — read-model・external store・レンダー回数テスト

イミュータブルなツリーエディタで一行直しただけで全体が再描画される問題を、まずテストで固定してから、正規化projectionとid別購読で行・コンテナの再レンダーを減らした過程

  • イミュータブルなツリーpatchは祖先も新しいrefを受け取り、propsで下ろすとO(depth)の再レンダーになる — 正規化entry + id別購読でO(1)に減らせる
  • entryキャッシュは入力refではなく出力の値-等価で安定化すべきで、外部storeのsyncはsetState直前のchoke pointで同期実行する