こんにちは、Nash です。
この記事は「React Native (Expo/managed)+SQLite 用の RawSQL なマイグレーション npm パッケージを作った話」です。
実際の成果物は下記です。
(気が向いたら Star してもらえると嬉しいです)
では、見ていきましょう。
フリーランスの仕事にて ReactNative(Expo/managed)での開発をしていて、だいたい 1 年くらい経過しました。「せっかくなので、簡単なアプリでも自分用にも作ってみよー」ということで SQLite を DB に持つアプリ開発をしていたのですが、この中で「Expo 用に SQLite で使える raw SQL なマイグレーションライブラリがない」という課題が出てきてせっかくなので自作+公開しました。
ちなみに、rawSQL ではなくて、オレオレクエリビルダによるマイグレーションを実現する npm パッケージは存在して、最初はこのコードを参考にしてました。アプローチとしては OOP で、クラスを定義、クラスメソッドにてマイグレーションの実行を行う流れです。
せっかくなので、自分の npm パッケージは違うアプローチにて作成しました。
アプローチとして「TypeScript + React Hooks(Context)」にて実現してます。
SQLite 用のマイグレーション npm パッケージですが、ReactNative 専用なので Context/Provider をガンガン使う感じです。
詳細の使い方などは README に書いてありますので、こちらを参考に。
作ったモジュールをパッケージ化していきます。
だいたい下記のようなステップで npm パッケージ化しました。
各ステップについて説明します。
1)アプリの中でモジュールとして切り出して独立した存在にさせます。今回は、開発当初から npm パッケージ化させるつもりだったので、ほぼ工数は0です。仮に、あとからモジュールを切り出すにしても、そこまで大変ではないかと思います。
2)ローカルで検証するために、npm パッケージ用にリポジトリをローカルに作ります。1)でのモジュールをここに移動させ、アプリ側の package.json にてこのローカルリポジトリを参照させます。これで正常にアプリが動作するかを確認します。
3)リモートから npm パッケージを取ってきます。まず、ローカルの npm パッケージのリポジトリにて、build&publish します。その後、アプリ側のリポジトリにて普段のパッケージ同様に yarn add などでリモートの npm パッケージを取得します。これで正常にアプリが動作するかを確認します。
これで、npm パッケージ化が完成です。
詳細のコマンドなどは、参考文献にあるリンクを参照してください。困ってもググってもかなりの数の手順が出てきます。
今回の SQLite マイグレーション npm パッケージを作成するにあたって、得られたナレッジなどをまとめます。
npm パッケージ化にて、ハマりました。特に、ローカルで npm pack したものを別にリポジトリから参照して使ってもReact variable error
みたいな汎用的なエラーが出てきて困りました。
というわけで、先人たちの言葉通り小さく始めることにしました。具体的には「console.log をだけを吐き出す npm パッケージ」を作って動かすところからはじめて肉付けしていきます。
特に、npm パッケージ化の作業は詰まった内容をググりにくいので、困ったら小さく始めることをおすすめします。
npm パッケージの中身の話です。2 つ以上のクエリ発行にて Promise 化すると transaction.executeSql にて何も言わずに Kill されるという、不明瞭なバグ?ぽいものを踏んでかなりハマりました。
というのも、どうやらエラーもログもでないでプロセスが Kill されてるぽいです。
下記 Issue と同じ現象だと思うのですが、ただ Expo 側でこの Issue が Close/Lock されてて議論の余地がない状態です。。。これ以上調査する元気もないので原因究明を諦めました・・・。
なので、callback 地獄をやめたくて Promise/async/await 化してたコードを泣く泣く全部消し、すべて callback 化しました。おかえり callback 地獄。
今回自分が作成した npm パッケージは「React Native (Expo/manged)で SQLite を使ってるとき用の Raw SQL なマイグレーション npm パッケージ」です。
ですが、Expo 公式見解での SQLite のマイグレーション方法としては、「どこかに version を保存しておく+マイグレーションを実行するコードだけで十分」とのことです。
Back-end で開発をしていれば一般的なマイグレーションと言えばイベントソーシングなやり方だと思うんですが、Expo 公式のやり方だとより愚直にやる感じですね。スケールの観点では微妙ですが、スケールを考慮する必要はないよ!ってスタンスだと思ってます。
(以後、イベントソーシング的な方法を RailsWay と呼称しますね。多分 Rails が最初じゃないと思うけど。)
Rails Way と Expo Way を具体的にどうやって実現するかです。
RailsWay と ExpoWay のメリデメです。
今回、RailsWay でやりましたが、小さいアプリなら正直 ExpoWay が良さそうです。(まぁ、それを理解してたのですが、npm パッケージ作りたくて今回 RailsWay にしてます。)
Web エンジニア1年目くらいのとき、会社のテックリードの人が年に数本パッケージを公開してて、そのパッケージに star も結構ついてるのを見てかなり憧れてました。
今回、自分が作ったパッケージが誰に使われるかはわかりませんが、どんな形であれ、Example 的な npm パッケージリリースではなくて、プロダクションレベルで使えるものを publish できてかなり嬉しかったです。
ようやく自分もスタート地点に立てた感があり、夜にいい気分ワインを飲めたので、皆さんもこれを機にパッケージを publish して一緒においしいワインを飲みましょう。
npm パッケージ化にて参考にした記事