開発時と本番時では画像等のリソースを異なるサーバに配置することがよくあると思います。例えば、画像等はAWSのS3に配置しアプリケーションはEC2に配置するなどです。今回は、Nuxt3で画像等の静的リソースを配置する方法について整理したいと思います。
環境
- nuxt 3.6.2
- node 16.19.1
- macOS Catalina 10.15.7
静的リソースの配置場所による違い
Nuxt3では、publicとassetsというディレクトリに静的リソースを配置することができます。それぞれの違いについて公式ドキュメントを参照すると以下のような内容があります。
- public
- ファイル名がキープされる必要のあるrobots.txtやfavicon.icoのようなリソース。serverのrootからのパスでリソースが返される。
- assets
- cssやsass、fontなど、publicから返されない画像などのリソース。webpackやviteのようなビルドツールのプロセスに加えられるもの。
viteの公式サイトにも詳しい説明があります。Nuxt3はviteを使っているので思想は同じだと思います。assetsのものはハッシュ値が付加されたファイル名になります。
Assets · Get Started with Nuxt
assets/ · Nuxt Directory Structure
public/ · Nuxt Directory Structure
静的アセットの取り扱い | Vite (vitejs.dev)
コンポーネント内でのassetsとpublicのリソースの参照
assetsとpublicのリソースの参照方法の違いは以下のようになります。
1 2 3 4 5 6 7 8 9 10 |
<template> <div> <!-- assets下の8870101.png --> <img src="~assets/8870101.png" /> <!-- public下の8870101.png --> <img src="/img/8870101.png" /> </div> </template> |
assetsとpublic/assetsのリソースが重複した場合にどうなるか?
このような疑問が生じるかと思います。実際に試してみました。
結果から言うと、筆者の手元では開発モードと本番モードで異なる解決がされていました。
コンポーネントのソースは以下のようにし画像ファイル名は同じで中身を変えて識別できるようにしてみます。
1 2 3 4 5 6 7 |
<template> <div> <img src="~assets/1.png" /> <img src="/img/1.png" /> <img src="/assets/1.png" /> </div> </template> |
~assets/1.png | |
/img/1.png | |
/assets/1.png |
開発者モード(dev)で起動した場合
~assetsのリソースは、デフォルトで/_nuxt/というプリフィックスで展開されています。ただ、左と右の画像が異なる想定でしたが同じ画像が表示されました。
起動している状態でpublic/assetsの1.pngのファイル名を適当な名前に変えると、今度は~assetsの画像が表示されました。
本番ビルド(preset: node)で起動した場合
左と右で解決されたパスは同じ~assetsに展開されています。画像も~assetsのもので解決されています。意図しない結果になり得るのでpublic/assetsのような紛らわしいディレクトリ構造にして誰かが誤って配置しないようにチームで決めて管理するのが良いでしょうか。
Debuggerで調ると、viteのmiddlewareでservePublicMiddleware、serveStaticMiddlewareの順にミドルウェアが呼ばれており、publicの方に先にヒットしていたようです。そのため、public/assetsにファイルが存在していた場合、○画像が表示され、public/assetsのファイルを消した場合、staticMiddlewareでヒットし~assetsのものである⭐️画像が返されていたようです。
リクエスト: /assets/x.png
projectRoot/public + /assets/x.png -> exists? false で next
projectRoot + /assets/x.png -> exists !!
本番ビルド時にpublic/assetsが~assetsに置換される件については別の機会に調査。
Assetsの配置
~assetsのリソースは、ビルドで.output/publicに展開されます。publicディレクトリのリソース一式をAWS S3等に配置することで異なるサーバから静的リソースの提供が可能です。配信先のURLは、nuxt.config.tsのapp.cdnURLまたは環境変数NUXT_APP_CDN_URLで設定ることが可能です。この値はビルド時に解決され、実行時でもNUXT_APP_CDN_URLで上書きすることができます。
実際にやってみます。
起動時に環境変数で異なるURLを設定します。
1 |
NUXT_APP_CDN_URL=https://debug-life.net PORT=3001 node .output/server/index.mjs |
上記のHTMLレスポンスを見ると、環境変数で設定したURLに解決されていることが分かります。preset nodeでビルドするとserverソースにassetsのrouteも含まれているのが分かります。
NUXT_APP_CDN_URLに外部サーバを設定することで、クライアント(ブラウザ)の静的リソースのアクセス先をアプリケーションサーバでなく外部サーバに向けることができます。
まとめ
Nuxt3で静的リソースを設定する方法について確認しました。また、~assetsを異なるサーバに配置し実行時に配信先を変更する方法ついても見ていきました。~assetsは柔軟に配置先を変えることができるので開発時と本番時の切り替えもスムーズに対応できます。
参考リンク
- Assets · Get Started with Nuxt
- public/ · Nuxt Directory Structure
- assets/ · Nuxt Directory Structure
- 静的アセットの取り扱い | Vite (vitejs.dev)
- @vitejs/plugin-vue – npm (npmjs.com)
コメント