LoginSignup
0
0

More than 1 year has passed since last update.

Nuxt.jsでFull Static Generationできない場合

Last updated at Posted at 2023-02-20

Nuxt.jsでの完全静的生成(Full Static Generation)がうまく機能していないケースがあった。
状況と原因を理解するのに丸一日かかってしまった。検索してもそれに該当する情報に行き当たらなかったので、やり場のない怒りを供養するために、ここに放流する。

環境

Nuxt.js 2.15.8

Full Static Generationとは何か

デプロイ時に全てのデータをソースファイルに組み込んでサイト生成をすることである。
それの何が良いのか。
CMSなどのウェブAPIからサイト掲載データを取得する場合、
ページロード時にクライアント(ユーザーPC)からAPIにアクセスすると、ブラウザの開発者ツールを使えばAPIキーが見えてしまう。
完全静的生成ならば、あらかじめAPIから取得したデータを含めてビルドするので、クライアントからAPIアクセスする必要がなくなり、APIキーを隠蔽できるわけだ。

詳細は公式。
https://nuxt.com/blog/going-full-static

どうやって実現するか

  • nuxt.config.jsに target: "static"を追加
  • nuxt.config.jsのprivateRuntimeConfigにAPIキーなど、隠蔽したい情報を指定
  • ページコンポーネントで、asyncDataでAPIアクセスしてデータを取得
  • nuxt generate でビルド実行
// nuxt.config.js
modules.exports = {
    mode: "universal",
    target: "static",
    // ...
    privateRuntimeConfig: {
        apiKey: 'xxxxxxxx',
    },
}
// pages/index.js
exports default {
    async asyncData({ $config }) {
        // $config に privateRuntimeConfigで指定したプロパティが入っている

        console.log('fire asyncData');
        const data = await axios.get(
            'https://example.com/',
            { apiKey: $config.apiKey }
        );
        return {
            data,
        };
    },
}

asyncData()は、コンポーネントがcreateされる前にサーバサイドでのみ実行される。
そのためSSGの場合には、ビルド時のみ実行され返却値が埋め込まれることになる。

私の環境ではどうなったか

ビルド後のサイト(/dist)にアクセスしてみたところ、
apiKeyがないというエラーが表示されると同時に、なんと asyncData がブラウザ上で実行されている(consoleにlogが出ている)のだ。

「SSGでasyncDataが実行される(asyncData of Nuxt.js is called on Static genarated page)」
とかで検索しても全然出てこない。
どこの記事でも、SSGの場合には、asyncDataはビルド時にのみ実行されて、ページ表示時には実行されないと書いてある。
いやいやいや、実行されているんですけれども。

ページ表示時にasyncDataが実行されるということは、つまりビルド時には実行されていない
すなわち、APIからデータを取得できていないということだ。
そして、ブラウザで実行されているので、privateRuntimeConfigの値もundefinedだ。
公式ドキュメントでは、privateRuntimeConfigで指定した値は、asyncDataの中で$configで取れるよ、と素朴に書いてある。できねーじゃんよ。

なぜSSGなのに、asyncDataが実行されるか。

私の環境における原因は、@nuxtjs/auth-nextを使った認証機能を組み込んでいるからであった。
認証機能に限らないのだろうが、おそらくmiddlewareを組み込んでいるとfull static generationされないのだと思われる。

middlewareは、ページを表示する際に都度実行されなければならない。
認証機能を考えればわかるが、「あらかじめ処理しておく」ということはできない。
middlewareの処理は、asyncDataより先なので、asyncDataもビルド時あらかじめ実行しておいて返り値を埋め込んでおく、ということができない。ゆえに、Full Staticな生成ができなくなる、ということなのであろう。
(状況から考えた雑な理解なので、間違っていたら指摘してもらえると助かります)

どうするか

私の場合、当初の目的はAPIキーの隠蔽であった。
それは、Nuxt.jsの機能として実装することは諦め、別途自前で処理を書くことにする。

APIにアクセスして取得したデータをJSONファイルとして保存するコードを書く、自前で。
そして、ビルド時にnuxt generateコマンドを実行する前に、その処理を走らせる。
Nuxt.jsのページでは、保存したそのJSONファイルからデータを読み込むこととする。

フレームワークに疲弊させられるというのは気分が良くない。やれやれ。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0