追記
Nuxt.js v2.12.0 がリリースされました。前バージョンから約 3 ヶ月ぶりのアップデートです。 本バージョンにて、「HMR support for server middleware」ということで、HMR サポートが無事に追加されました。
導入
Nuxt.js で開発するにあたり、serverMiddleware で簡易的な BFF(Backends for Frontend)を構成したい、もしくは簡易サーバーとして活用したいという要件は結構多いように思います。
今回 serverMiddleware の HMR がサポートされるようになるとのことで期待を膨らませています。 この記事では、まずそもそも Nuxt.js でサーバー処理ってどうやって実装するの、という所を整理していきます。
HMR とは?
Hot Module Replacement の略で、リロード無しでモジュールを差し替えてくれるものです。ホットリロードというとイメージしやすいと思います。
以下の webpack 公式のページが詳しいです。 https://webpack.js.org/concepts/hot-module-replacement/
Nuxt.js のサーバー実装パターン
- Nuxt.js で serverMiddleware を構成する
- Express のミドルウェアとして Nuxt.js を構成する
- 別途 Node サーバーを確保する
弊社では、BFF が必要な案件においては別途 Node.js サーバーを挟んで BFF を実装することが多いです。 なぜかと言いますと、1 番目と 2 番目の実装では DX(Developer Experience)が非常に悪いという欠点がありました。 基本的には、Express 側のコードを修正すると Nuxt.js 全体が再ビルドされ非効率でした。 なお、厳密にはホットリロードを効かせる方法もあるにはあるのですが正直そこまでして、、という想いもあり、別途 BFF 用に Node サーバーを確保しています。
serverMiddleware の HMR がサポートされる
この問題は 2 年以上前から問題提起されていました。 https://github.com/nuxt/nuxt.js/issues/1509
暫く進捗がありませんでしたが、最近動きが出ています。 https://github.com/nuxt/nuxt.js/issues/6877
What problem does this feature solve? Currently Nuxt rebuilds the full project when you touch any serverMiddleware. Because this reloads the full Nuxt server, any file listeners are removed during the build causing Nuxt to not detect file changes during the build process (which can often take 10-30s). What does the proposed changes look like? Dont rebuild the webpack bundle if only serverMiddleware is touched
現在の serverMiddleware は更新するとプロジェクト全体が再ビルドされていました。 この対応により、serverMiddleware を更新した場合でも webpack バンドルは再ビルドしないようになるとの記述があります。
最新の進捗はこちらで確認可能です。 https://github.com/nuxt/nuxt.js/pull/6881
なぜサーバー処理が必要なのか
WordPress を使っている方はフロント側から PHP から DB 処理する場合に Ajax 処理を書くと思いますが、そのイメージを持ってもらうといいかもしれません。 なぜサーバー側で処理が必要なのでしょうか?上記の WordPress の例で考えると、クライアントサイドの JS から直接 DB を叩かないのはなぜでしょうか? DB の接続情報がクライアント側に露出するのは問題だというのは直感的に分かると思います。そもそもクライアントサイドの JS から DB を叩こうと考えること自体ないのではないかと思います。
しかしながら、特に個人開発では Nuxt.js の単独構成でフロントから DB リクエストまで実装するケースもあると思います。チュートリアル記事にも簡易的な実装例としてそのような記載が多くあることも一因かもしれません。
実際のプロダクトとして Nuxt.js を採用する際には、セキュアな情報をどのように保管するかが必要となります。間違ってもクライアントサイドでセキュアな情報(シークレットキーなど)をprocess.env.xxxx
として参照しないようにしてください。Nuxt.js のクライアントサイドの処理に環境変数を書くとコード上に露出しますので悪意のあるユーザーから情報を盗まれるリスクが発生します。
では、どのようにセキュアな情報を管理するのか、そこで登場するのがサーバー処理です。
serverMiddleware の使い所
API リクエストや Node.js のミドルウェアとして使うことができますが、バックエンドとの繋ぎとして使われている方が多いと思います。 環境変数は外部から注入が可能なので Nuxt.js のビルドプロセスと分離することが可能になるメリットもありますが、環境変数周りの扱いに関しては別記事で扱う予定です。
コードサンプル
// pages/index.vue
async getUser() {
const user = await this.$axios.$get('/api/getUser')
}
// server/index.js
app.use('/getUser', async function(req, res, next) {
try {
const data = await DBやAPIリクエスト処理 //process.env.secret_keyなどで参照
res.status(200).json(data)
} catch (err) {
res.status(400).json(...)
}
})
まとめ。HMR 対応で今後の Nuxt.js の開発がどう変わるか
BFF を別サーバーで立てるメリットは開発効率以外にもありますが、簡易的にサーバー実装がしたいという要件であれば今後 serverMiddleware をどんどん活用していけるのではないかと思います。
これまでは serverMiddleware では依存関係ファイルも含めたモジュールのホットリロードに対応できなかったため DX に難がありましたが、今後 HMR サポートがあることでフロント開発と同等程度の効率で開発を行うことができるようになるのではないでしょうか。
(Express のミドルウェアとして Nuxt.js を立ち上げる方法を採用するメリットはあまりなくなりそうですね。)
なおリリースはまだで、2020/1/30 時点で最新の v2.11.0 に本機能は盛り込まれていません。 以上です。 2020/3/18 に v2.12.0 で本機能が導入されました。