mod_sedでjavascriptを移動する

Webの高速化手法の一つに、javascriptをページ末尾へ移すって方法があります。javascriptの読み込みが始まるとその時点でコンテンツの並列ダウンロードが中断され、それ以降のレンダリングが中断されます。

トータルではページのダウンロード、レンダリング完了までにかかる時間はスクリプトがどこにあろうが変わらないのですが、ブラウザ上にページが表示されるまでの速度はスクリプトが後ろにあるほうが早い。

ということですが、Webページ作成に使っているツールやなにやらの都合で、スクリプトを後ろへ持っていけないってなことがあります。
なので、フロントエンドのapacheでなんとかする。

外部読み込みスクリプトを後ろへもっていく

こういう行があった場合の後ろへ移動。こういうsedスクリプトです。

/<script type=["\']text\/javascript["\'].*<\/script>/{
H
d
}
/<\/body>/G

mod_sedで利用する場合は、OutputSedディレクティブに続いてシングルクオート。こんな感じです。

OutputSed '/<script type=["\']text\/javascript["\'].*<\/script>/{'

HTML中に入っているスクリプトも移動したい

上記のmod_sedフィルタは意図したとおりに動作するのですが、HTML中に含まれているスクリプトも移動したい。スクリプトは複数行にわたるので、範囲指定でやる。

/<script *[^>]*>/,<\/script>/{
  H
  d
}
/<\/body>/G

まとまらないの?

上記二つのスクリプトで動作することはするんですが、HとかdとかGの部分同じじゃない。それにこれ実施するとスクリプトの読み込みの順番とかインラインのスクリプトの順番がかわってしまう。
ってなことでいろいろ試行錯誤してこんなスクリプトが出来上がりました。

/<script *[^>]*>/{
  :loop
  /<script *[^>]*.*<\/script>/{
    H
    d
    b end
  }
  N
  b loop
:end
}
/<\/body>/G

sed入れ子になったブロックは初めて書いた。