Nuxt.js Generate後の<script>window.__NUXT__=を消したい

2021-12-08

Nuxtにはgenerateという機能があり、サイト全体を静的なHTMLファイル(cssやjsも)として書き出すことができる。そしてほぼ無料のホスティングサービスなんかにアップして公開したり、はたまたS3などのストレージで公開することも可能だということだ。例えばLPサイトなんかはこのような公開方法が向いていると思われる。

検証バージョン

  • nuxt@2.8.1

NuxtGenerateにはゴミがたくさん

generateした後のファイルを見ればわかるが、静的HTMLにすると明らかに必要のない情報まで吐き出されてしまうようだ。

<!doctype html>
<html data-n-head-ssr lang="ja" data-n-head="lang">
  <head data-n-head="">
<!--省略-->
  </head>
  <body data-n-head="">
<!--省略-->
<!--ここから-->
<script>window.__NUXT__=(function(a){return {hoge: 'fuga'}],error:null,serverRendered:true,logs:[]}}(""));</script>
<script src="/_nuxt/runtime.js" defer></script><script src="/_nuxt/pages/index.js" defer></script><script src="/_nuxt/vendors.app.js" defer></script><script src="/_nuxt/vendors.app.hoge.js" defer></script><script src="/_nuxt/app.js" defer></script><script src="/_nuxt/app.huga.js" defer></script>
<!--ここまでのスクリプトたち-->
  </body>
</html>

nuxtのasyncDataでセットしたプロパティが「window.__NUXT__=」に書き込まれている。asyncDataはサーバーサイドの処理であり、SSRを実現するためには必要なものだ。

    async asyncData(context) {
      // サーバーサイドにてAPIでこのページの情報を取得する
      const model = await axios.get('hoge')
      return {
        model: model // サーバーサイドで予めデータをセット
      }
    }

asyncDataでセットする、例えばページ内に表示するデータのmodelなどがbodyタグ内のscriptタグで一旦書き出されて、それを元にレンダリングしてHTMLを描写しているが、Generateの場合はすでにレンダリング後のHTMLがファイルとして書き出されているので、このscriptタグたちは必要ないと思われる。

もし、asyncDataで大量のデータを取得して、そのうち一部のみをVueで使用する場合、明らかにHTMLファイルのサイズが大きくなってしまうし、model構造など見られたくないものまでソースに書かれてしまう。

Generate後のHTMLファイルからscriptタグを削除

Generate時にscriptタグを削除するには、nuxt.config.jsに以下を追加するだけだ。

const cheerio = require('cheerio')
export default {
  // 省略
  hooks: {
    'generate:page': page => {
      const doc = cheerio.load(page.html);
      doc(`body script`).remove();
      page.html = doc.html();
    },
  },
  // 省略
}

cheerioというスクレイピングのライブラリを仕様しているが、他の方法でdom操作しても良い。

要はgenerate時のページ生成をフックしていらないものを削除しちゃう方法。今回はbody内のscriptを全て削除しているが、「window.__NUXT__=」だけを削除するようにしても良い。

これでよりシンプルでセキュアな静的ファイルを書き出すことができる。