このバグは、閲覧履歴のエントリが破損するという形で現れることも判明しました。これはより深刻な問題だと考えています。具体的には、JSによってナビゲーションが処理されると、古いURLに新しいタイトルが割り当てられます。これはFirefoxではほぼ常に発生しますが、Chromeでは非常にまれです(これまでのところ1つのインスタンスが見つかりました。/topからトピックへの移動)。
@sam が指摘するように、これはURLとタイトルの変更の操作順序によって引き起こされます。どこかに、正しい順序を示すベストプラクティスガイドがあればいいのですが。常にhistory APIを使用した後にタイトルを更新することです。
デバッグを試みました(そして、中規模のnpm関連プロジェクトを構築することには非常に抵抗があることを事前に申し上げておきます)。最初は、簡単な偵察のためにこのコードを使用しました。
Object.defineProperty(document, "title", {
get() {
return document.head.querySelector('title').innerText;
},
set(t) {
console.debug('title', t, new Error("title!").stack)
debugger;
document.head.querySelector('title').innerText = t;
},
enumerable: true,
configurable: true,
});
let ___push___ = window.history.pushState;
window.history.pushState = function(...args) {
console.debug('push', args[0], new Error().stack);
debugger;
___push___.apply(this, args);
};
let ___replace___ = window.history.replaceState;
window.history.replaceState = function(...args) {
console.debug('replace', args[0], new Error().stack);
debugger;
___replace___.apply(this, args);
};
実際に、history API操作の直前にタイトルが1回変更されることが示されました。残念ながら、それ以上の助けにはなりませんでした。実行時に何が起こるかをソースコードに関連付けるのは非常に困難でした。関心のある操作はかなり散らばっており、実行がEmberのイベントループにすでに譲渡されていたため、コールスタックは誤解を招くものでした。そして一般的に、Firefoxでのデバッグ体験は非常に地獄のようでした。Chromeに切り替えたところ、少し成功しました。長くなりましたが、私の知る限り、EmberはURLの更新時期を自分で決定します。一方、タイトルの変更は2つの場所から開始できます。[1]と[2]。
history API呼び出しの前に実行されるのは、後者のみです。それらの「共通コード祖先」はここにあります。
// Run all the necessary enter/setup/exit hooks
this.setupContexts(newState, transition); // <- タイトル変更はここで開始され、`model.title:change`イベントがトリガーされます
// Check if a redirect occurred in enter/setup
if (transition.isAborted) {
// TODO: cleaner way? distinguish b/w targetRouteInfos?
this.state!.routeInfos = this.currentRouteInfos!;
return Promise.reject(logAbort(transition));
}
this._updateURL(transition, newState); // <- URL変更はここで開始されます
興味深いことに、「router.jsはEmber.jsで使用されているルーティングマイクロライブラリです。」
ここで、私とは対照的に、discourseのコードベースに多少なりとも精通している人に、この問題の処理を引き継ぎたいと思います。
編集:言及するのを忘れました:document.titleは、[2]とhistory APIによるURLの変更の両方の後に、[1]によって1回以上変更されます。