◆ IE で document.write すると内部でページを置き換えてるみたい
  ◆ グローバル変数やタイマーなどがリセットされる
◆ document.write の HTML にある script タグは実行されない
  ◆ write 後のページで JavaScript の実行手段がない

ネットで昔の IE で SPA 作るみたいな記事を見かけました
よくやるなぁ と思うと同時に変に高度なことしないで document.write で全書き換えで十分じゃないのって気もしました

その方法だと 私も ESModules や customElements を前提にこんなことしたことがあります

IE だと ESModules は使えないですが 単純に昔ながらの JavaScript にすればいけそうな気がします
JavaScript ファイルが毎回ロードと実行されますが IE を使うユーザに速度追求する必要もないので気にしません
複数回実行しても全部上書きして変な影響出ないようにだけ気をつけておきます

簡単につくってみる

そういう考えで簡単にこういうものにしました
まずそれぞれのページです

[top.html]
<html>
<head>
<script type="text/javascript" src="/common.js"></script>
</head>
<body>
<h1>Pages</h1>

<ul>
<li><a href="javascript:navigate('/page1')">Page1</a></li>
<li><a href="javascript:navigate('/page2')">Page2</a></li>
</ul>
</body>
</html>

[page1.html]
<html>
<head>
<script type="text/javascript" src="/common.js"></script>
</head>
<body>
<h1>Page1</h1>

<p>page1page1page1</p>

<p><a href="javascript:navigate('/top')">Back</a></p>
</body>
</html>

[page2.html]
<html>
<head>
<script type="text/javascript" src="/common.js"></script>
</head>
<body>
<h1>Page2</h1>

<p>page2<br />page2<br />page2<br />page2<br />page2<br />page2<br /></p>

<p><a href="javascript:navigate('/top')">Back</a></p>
</body>
</html>

ページ遷移は navigate 関数を実行するようにしておきます
これは common.js で定義して common.js はこういうのです

[common.js]
function navigate(to) {
var scr = document.createElement("script")
scr.src = to + ".html.js"
scr.type = "text/javascript"
document.getElementsByTagName("head")[0].appendChild(scr)
}

function redraw(html) {
document.open()
document.write(html)
document.close()
}

ページの HTML を取得したいのですが fetch はないですし 古い IE 想定なので xhr もないかもです
なので JSONP でロードすることにしています

page1.html.js のような URL をロードすると ページの HTML を引数に redraw 関数が呼び出されます
JSONP 部分はサーバで動的に作っても良かったのですが とりあえずの仮状態だったので 静的ファイルだけで済むように事前に HTML を変換しました

[convert.js]
const fs = require("fs")

function convert(path) {
const html = fs.readFileSync(path).toString()
const js = `redraw(${JSON.stringify(html)})`
fs.writeFileSync(path + ".js", js)
}

convert("top.html")
convert("page1.html")
convert("page2.html")

これでページ切り替えの仕組みはできたはずです

最初にページを開いたときは普通に静的ファイルの HTML をロードします
リンクをクリックすると navigate 関数が呼び出されて JSONP で JavaScript を読み込み実行します
リンク先の HTML テキストを引数に redraw 関数が呼び出され document.write を使ってページ内を全書き換えします

Chrome で確認

まずはデバッグしやすい Chrome で確認しました

URL を変える仕組みはいれてないので リロード時に問題はありますが 問題なくページ遷移できています

IE 11 で確認

まずは IE 11 で確認してみました

うまく動いてません

/top.html から /page1.html への移動は問題なしです
しかしそこから /top.html へ戻れません
なぜか /top が開かれます

原因がわからず苦戦したのですが common.js が呼び出されないのが問題でした
それなのになぜかページ遷移して /top に行くのが謎でしたが IE ではデフォルトで navigate というグローバル関数が存在しました
Chrome や Firefox には存在しない独自仕様なので知りませんでした
偶然わかりづらいバグになったという感じです

common.js に alert を入れて呼び出されないことからロードされないのはわかりました
しかし document.write をする前にすでにロードしてるので ロードされないのは別に困らないのではと思います
ですが IE の場合 document.write のタイミングでこれまでの JavaScript 環境がリセットされます
setInterval で毎秒 console.log するようにしてから document.write で書き換えると書き換え後に console.log が表示されなくなりました
URL はそのままに新しいページに移動してる感じです

新しいページになっていて JavaScript 状態が引き継がれないのは これ単体だとありがたい部分でもあります
document.write 前の状態で引き継ぐと困るタイマーなどをクリアしなくて済みます
しかし それに加えて document.write で追加した HTML 内の script タグが実行できないのは困ります
これだと新しいページで JavaScript を実行する手段がありません

また document.write で内部的にページ切り替わってるような動きに関連して IE ではリロードにも影響が出ました
top.html を開いて document.write で page1.html を表示します
このとき URL は top.html で画面は page1.html です
ここでリロードすれば本来の top.html に戻るように思います
しかし IE では page1.html 表示のままです

document.write を行うと DOM を変えるだけでなくブラウザが管理してるキャッシュも含めて top.html の中身を置き換えてしまってる感じです
リロードで開き直しても top.html の中身が page1.html のものになってるので変化がありません
これは別のページに一旦移動してから top.html を開き直したり 新しいタブで開けばもとに戻りました

簡単にはできなそう

こういうブラウザの問題があるので やるとしたら head と body の中身だけを書き換えることになります
DOMParser もない IE でやるのは辛いので JSONP を使って呼び出す引数を head と body と script にわけてそれぞれ置き換えていくことになります
script もあるのは innerHTML を書き換えてもダメなので 独自に script タグ作って append するためです

そこまでやろうとする面倒なのでこの辺にしておきます
簡単にできるなら と思ってはじめてみましたが簡単にはできなかったです
さすがは IE ですね

IE5

ついでにエミュレータの一番古い設定の IE5 で動かしてみました
すると別の理由で動きませんでした

document.write による書き換えや JSONP 自体は動きます
しかし それが組み合わせられませんでした
JSONP が呼び出す関数の中で document.write すると何も起きません

script タグをロードしたときの実行時はダメみたいです
ユーザがクリックしたときに同期的な処理として document.write すれば画面を更新できました

リンクをクリックしたら HTML をどこかの変数に入れて 更新ボタンを押したら document.write で置き換え とやれば動きました
ただ ページ遷移に 2 回クリックはけっこう不便です