Blitz.js、Next.js辞めるってよ

[Blitz](https://blitzjs.com/)は、ざっくり言うとReact版Ruby on Railsです。
Reactの面倒なところを全てすっ飛ばし、技術選定なんてどうでもいいから今すぐアプリを動かしたいんだよ、という要望を叶えるのに適したフルスタックフレームワークです。
概要は[Blitz.js - React on Rails](https://qiita.com/nitaking/items/edfaae19d0b54aae7f9c)、実際の使い方は[Blitz.jsチュートリアル：投票サービスを15分で作ってみる](https://zenn.dev/rince/articles/c9ba86a07e794f)あたりを見てもらうとして、とにかくチュートリアルに従ってコマンド打てばとりあえず動くものが一瞬でできるとかそんなかんじです。

技術的にはReact + Next.jsで動いています。

ということだったのですが、先日どうも雲行きの怪しいRFCが提出されました。
以下は[[RFC] Time to maintain a fork of Next.js?](https://github.com/blitz-js/blitz/discussions/1990)の紹介です。
なお提案者の[Brandon Bayer](https://github.com/flybayer)はBlitz.jsの作者です。

# [RFC] Time to maintain a fork of Next.js?

## Problem

我々のカスタムコンパイラのアプローチは、これまではうまくいっていましたが、そろそろ限界に達しつつあります。
現在は、我々は`blitz`のコードベースを`next.js`のコードベースにコンパイルし、そして`.blitz/build`から`next`を実行しています。
これによって、`next.js`のほとんどの機能をオーバーライドすることが可能になっています。

しかし、正直これはハックじみた方法であり、そして多くの問題が発生していて、問題回避のために余分な労力が発生しています。
たとえばランタイムの実体は`.blitz/build`の中にあって、思っているファイルのパスと異なる場所にあります。
しかし`next.js`のログを操作しているので、ログに表示されるパスは正しくなっています。
ただブラウザのエラーには対応していないので、こちらでは正しくないパスが表示されます。
さらに、これのせいで`node.js`のデバッガーが正しく動きません。
そしてブレークポイントは`.blitz/build`の中にあるコードに仕掛けなければなりません。

また、このディレクトリ構造のため、blitzが開発ディレクトリを監視し、変更があれば`.blitz/build`にコピーし、さらに`next.js`が`.blitz/build`を監視し、変更があればコンパイルするという、二重の監視プロセスになってしまっています。
さらに他にも様々な問題があり、多くは未だに解決していません。


## Solution

カスタムコンパイラを取り除き、よりネイティブなアプローチを採用する。

### Needs

babelプラグインで多くの事柄を解決できます。
以下はbabel以外に必要なものです。

- 必須：queries/mutationsファイルをAPI routesに変換する機能。
- 必須：複数のページとAPIフォルダを一括でマージする。
- ほしい：Next.jsより前の段階で任意のカスタマイズ。`next.config.js`のかわりに`blitz.config.js`を使い、TypeScriptに対応させるなど。


### Approaches

ふたつのアプローチが考えられます。

#### 1. Change blitz to be only an add-on to next.js

blitzをnext.jsのアドオンとしてのみ使用する。

この場合、blitzで行っている幾つかの変更を元に戻す必要があります。
たとえば`blitz.config.js`を`next.config.js`に戻し、その中にblitz用のラッパーを入れるなどです。

このためには、next.jsチームと協力し、next.js側にRPCレイヤーを追加しなければなりません。
技術的には可能ですが、next.jsチームとこれらの変更について合意できるかどうかは不明です。

Next.jsの内部実装を変更できないので、やりたいカスタマイズやオーバーライドができません。
たとえば、多くの人が望んでいるにもかかわらず、設定ファイルのTypeScriptサポートを追加することができません。

これによって、Next.jsの保守的な実装に縛られてしまうことになります。
Next.js上での実装は、たとえばRedwoodと比較すると今でも多くの制限がありますが、これではさらに制限が強まってしまいます。

#### 2. Fork Next.js, make changes to core, and keep up to date with the main next.js repo

Next.jsをforkし、コアに変更を加える。

これによってメンテナンスの複雑さは増加しますが、同時に全ての制限から解放されます。
フルスタックのDXを改善するために、Next.jsを直接変更することができるからです。
うまく実装すれば、本家をマージする際のコンフリクトは最小限に抑えられます。

Next.jsの保守的な実装から解放され、より迅速に機能を確信することができます。
またファーストクラスレイアウトのように、変更がNext.jsにバックポートされる可能性もあります。

もうひとつの利点としては、babelプラグインではなくnext.jsを変更することは、よりシンプルになることです。


私はforkアプローチを採用すべきだと考えています。
なにしろ我々は、新機能の追加やDXのフルスタックフレームワークへの最適化などにおいて、Next.jsよりずっと積極的です。

forkすることで、多くのチャンスを得ることができます。
これまでのところ、ネイティブなNext.jsよりも、我々が加えたカスタマイズのほうに満足している人の方が多いと思います。

この変更についてどう思いますか？
Blitzを使ったことがあるかないかも含め、回答をください。


# コメント

## stevenpetryk

fork自体には賛同です。
ただ、Blitz固有の機能をNextに追加する意図でforkするのではなく、BlitzをNextのプラグインとしてビルドする意図でforkしたほうがいいでしょう。
そうすればそのうちforkがNextにマージされ、独自にメンテする必要がなくなるかもしれません。

## adamsoffer

stevenpetryk氏の言うとおり、プラグインとして構築することをお勧めします。
Nextチームはプラグインシステムに取り組んでいます。

## flybayer

ところがどっこい彼らは当初のプラグインシステムを放棄しました。
既に完全に削除されています。
かわりに実装されたのは、一度にひとつのフックだけを追加するという、より保守的なアプローチです。
さらにこのフックは、任意のコードを実行することができません。

## leerob

待って放棄されてないよ。
[mdx](https://github.com/vercel/next.js/tree/canary/packages/next-mdx)みたいにプラグインはあるし、より多くのフックを提供しようとするFRCもあるよ。

## AndriusBartulis

Blitzがいったいどこを目指しているのか、そのゴールによると思います。
フルスタックなモノリシックフレームワークを目指しているのであれば、Nextをforkするのは理にかなっているでしょう。
独自のエコシステムを構築していくのであれば、Nextの互換性を維持することは意味がないと思います。



# 感想

正確には辞めるのではなく、forkして独自の変更を加えていくという方向です。
これまではNextの機能を使っていて、そしてNextで対応しきれないところはNextをハックして上書きするような使い方をしていたのですが、その運用が辛くなってきたのでどうにかしようということです。
Nextを使わないようにするという手段もあったかもしれませんが、Blitzの開発チームはNextをforkする方向を選んだようです。

ただ、チケットでは本家の変更もマージしていくよとは言っていますが、実際それができるかというと正直疑問です。
そのうちマージに耐え切れなくなって、[Hack](https://ja.wikipedia.org/wiki/Hack_(%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E8%A8%80%E8%AA%9E))のように分離の道を歩むことでしょう。
しかし道をたがえたFork元とFork先が両方ともうまくいった例ってのはこれまでもあんまりないので、そのまま続いていくかというと怪しい気がしないでもありません。

果たしてBlitz.jsの未来はどうなるでしょうか。