Skip to content

[Bug] iframeのsrc代入が履歴を積むため、成果物ページから「戻る」を押すと画面が真っ白になる #11

Description

@takke1986

起きたこと

ダッシュボードで成果物ページを開いた状態(/app/index.html#/<slug>)からブラウザの「戻る」を押すと、画面が真っ白になります。

一覧には戻らず、URLは #/<slug> のまま、ページ枠だけが残って中身が消えます。macOS Safari で確認しましたが、原理上ブラウザは選びません。

原因

select() が成果物を表示するとき、iframe の src へ代入しています。

// web/app/index.html
} else {
  home.classList.remove('on');
  frame.hidden = false;
  frame.src = current.href;   // ← ここ

iframe の src への代入は、そのたびにブラウザの履歴にエントリを積みます。

そのため「戻る」を押すと、親フレームより先に iframe の中身だけが1つ前(=空)へ戻ります。親は #/<slug> のままなので hashchange も発火せず、枠だけが残って真っ白に見えます。

ページを何枚か開いてから戻ると、開いた枚数ぶん「戻る」を押さないと一覧へ到達しない状態にもなります。

修正案

履歴を積まない location.replace() に変えると解消しました。

// iframe の src への代入は履歴を積むため、「戻る」で iframe だけが空へ戻る。
// location.replace は履歴を積まず、クロスオリジンでも呼べる。
// 読み取り(location.href の取得)はクロスオリジンで例外になるため行わない。
function loadFrame(url) {
  const view = frame.contentWindow;
  if (!view) { frame.src = url; return; }
  try {
    view.location.replace(url);
  } catch {
    frame.src = url;   // 想定外の環境では従来どおりに倒す
  }
}

呼び出し側は2箇所です。

if (!current) {
  frame.hidden = true;
  loadFrame('about:blank');   // 旧: frame.removeAttribute('src')
  
} else {
  frame.hidden = false;
  loadFrame(current.href);    // 旧: frame.src = current.href

Location インターフェースの replace() はクロスオリジンでも呼び出せるため、成果物が別オリジン(contentDomain)でも動作します。

再現手順

  1. ダッシュボードで任意の成果物ページを開く(URLが #/<slug> になる)
  2. ブラウザの「戻る」を押す
  3. 一覧へ戻らず、画面が真っ白になる

確認したこと

手元で上記の修正を当てて html-share publish し、実機の Safari で「戻る」が一覧へ正しく戻ることを確認しました。

環境

  • macOS Safari
  • Node.js 24
  • main ブランチ相当(2026-08-17 時点)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions