Nuxt.jsにserverMiddlewareのHMRサポートが追加されました(2020年3月18日追記)

18

3月

Nuxt.jsにserverMiddlewareのHMRサポートが追加されました(2020年3月18日追記)

2020年03月18日 BFF, Nuxt.js, serverMiddleware

追記

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公式のページが詳しいです。

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年以上前から問題提起されていました。

暫く進捗がありませんでしたが、最近動きが出ています。

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バンドルは再ビルドしないようになるとの記述があります。

最新の進捗はこちらで確認可能です。

なぜサーバー処理が必要なのか

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サポートがあることでフロント開発と同等程度の効率で開発を行うことができるようになるのではないでしょうか。

(ExpreessのミドルウェアとしてNuxt.jsを立ち上げる方法を採用するメリットはあまりなくなりそうですね。)

~~なおリリースはまだで、2020/1/30時点で最新のv2.11.0に本機能は盛り込まれていません。
以上です。~~
2020/3/18にv2.12.0で本機能が導入されました。