この記事には新しいURLが設定されています

背景

  • document.writeを使ってる外部ライブラリを動的読込する必要があった
  • そのライブラリが読み込まれた後にしなければならない処理がある

document.writeは使うなってあれほど言ってるのに!!

それでもそんなライブラリ(内製だった…)を使わなければならない場面もあります。しかも<script src="..."></script>で読み込めず、動的読込(※)しなきゃいけない場面もあります。それが人生です。

※動的読込の例

<script>
if (conditions) {
  var scriptElement = document.createElement('script');
  scriptElement.src = '//cdn.hoge.com/library.js';

  var headElement = document.getElementsByTagName('head')[0];
  headElement.appendChild(scriptElement)
}
</script>

でもdocument.writeが使われているライブラリは動的読込しようとしても読み込めません!💢💢
HTML解析が始まりDOM操作によって追加された外部スクリプトのdocument.write無視されます。そのせいで普通に動的読込しても何も起こらないのでした😉

結論

  • iframeで動的読込する
  • iframe.onloadを使って後続処理をする

解説

1. create iframe to load a library

document.writeを含むライブラリを読み込むための、iframeを準備します。
iframeを使うことで擬似的に別のHTMLをつくり、そいつにライブラリを読み込んでもらう算段です。iframeは今この場で生成しているのでHTML解析がまだ始まっていないから、document.writeのあるライブラリも読み込めます。

ちなみにここではiframeを用意しただけで中身(ライブラリを読み込むためのscriptタグ)はまだ書いていません。

2. some functions after loading a library

ライブラリ読込後の後続処理はonloadを使います。onloadイベントはsrc属性により指定されたリソースの読み込み完了時に発生します。ありがたや。

3. write sctipt tag in iframe

iframeにscriptタグを書き込みます。document.writeにはちょっとひとクセあって、文書ストリームを勝手に開いて文字列を書き込むんですね。そして開いたら開きっぱなし(これが使うなと言われる所以)。なので明示的にopen, closeをします。
(closeだけすりゃいいんだけども。見栄え的にopenもしてみた)

参考

こんな感じに少々ゴリ押し技を組み合わせて実現しました。今回は一時凌ぎの実装だったのでこのような手段を取りましたが、あまりおすすめできる技ではありませんのでご利用は程々に。