Flutter WebでDriftを使用したらハマりました。
はじめに
「Drift」と言うライブラリはWebでも使用できるデータ永続化ライブラリですが、Webで使用したらデータが永続化されずハマったので、ここに解決策を残しておこうと思います。
したこと
サンプルのカウンターアプリを改造して、DBにカウント値を保持するようにしました。
こちらの「Drift support in Flutter and Dart web apps.」に従って実装を進めました。sqlite3.wasm
を使用する方法です。
動作の確認までは特にハマらずに実装できましたが、ブラウザを閉じてもデータが残っているかを確認したところ...
事象
カウントアップしブラウザを閉じて、もう一度実行してみるとカウント値は「0」に戻っていました。
普通にバグだと思い何度もプログラムを見直しました。print("ここまできた")
も沢山仕込んで動作を見ましたが、どう見てupdateまで実行されていました。(ちなみにブレークポイントは気まぐれでヒットするのであまり使っていません。)
調査
マイグレーションや初期値の設定がバグってるんじゃないか...なんて疑って調べましたが糸口はつかめませんでした。「ブラウザの仕様かも?」と思い、indexeddbのサンプルをgithubから探して動かしてみましたが、こちらはしっかりデータが残っていました。
ふと、データの実態はどこのファイルにあるかを調べてみました。indexeddbのデータはユーザーデータ領域にあるそうですので確認しました。テストで動かしたindexeddbのサンプルのデータは残っていましたが、flutterのほうは残っていません。なぜ...
ちなみに、IndexedDBはオリジン単位で保存されます。ポート番号が変われば領域も変わります。しかし今回はあまり関係ありませんでした。
原因
Flutterのデバッグでchromeを起動するときのコマンドライン引数を確認したところ、起動するたび一時領域にユーザーデータを作成していました。このため、一度ブラウザを閉じたらもう二度とその領域は使用されません。
解決
Flutterアプリを起動するときに次のコマンドを使用しましょう。
flutter run -d web-server --web-hostname=0.0.0.0 --web-port=5555
ウェブサーバーモードで起動します。この後は普通にブラウザでアクセスすれば、作ったアプリが表示されます。
普普段通りショートカットなどからブラウザを立ち上げてください。その時のユーザーデータ領域は普段通りだと思います。再起動してもユーザーデータ領域は変わらないはずですので、カウント値も保持されているはずです。
Discussion