【Flutter Web】 既存アプリをWeb対応する際につまずいた点とその対応方法

こんにちは、株式会社Pentagonでアプリ開発をしているyoshidaです。
私はスマホアプリの一部の機能をWebアプリとしても利用できるようFlutter Webを利用して実装しました。
今回はその中で私がつまずいた箇所と、その対応方法をご紹介します。
Flutter Webでよく起こる(と思われる)問題をまとめましたので、Flutter Webを導入予定の方はご一読いただけると事前に回避できていいと思います。

【こんな人に読んで欲しい】

  • スマホアプリをWebアプリでも対応させたいと考えている方
  • Flutter Webを触ったことない方

【この記事を読むメリット】
Flutter Webでよく起こる(と思われる)問題と解決法がわかる

【結論】

  • 一部のWeb非対応パッケージは別でWeb側の書き分けが必要だが、その他はちゃんと動いてくれるので、機能が少ないアプリだと対応コストはさほどかからないかも
  • Flutter Web特有のエラーはまだ情報が少ない
  • WidgetをスマホアプリとWebアプリで使いまわせるので実装が少なくて済む!(レスポンシブ対応は必要)
目次

Flutter Webではパッケージの選定に注意

特に一番気をつけたいのはパッケージの選定ではないでしょうか。
Web対応されていないパッケージを選んでアプリを実装してしまうと、その箇所をWeb・アプリと実装の書き分けが必要になる、もしくはパッケージを変更して実装し直しのリスクがあるのでパッケージの導入はWeb対応しているか調べておく必要があります。

pub.devで各パッケージ名の下に対応のプラットフォームが記載してあるので、Webと書いてある事を確認して使用してください。

(2022/9月時点 yoshida調べ)

対応していた主なパケージ

  • Riverpod
  • flutter_hooks
  • get
  • dio
  • shared_preferences

対応していないパッケージ

  • image_piker

特に苦戦したのがimage_pickerです。
アプリはimage_picker (https://pub.dev/packages/image_picker)
Webはimage_picker_for_web (https://pub.dev/packages/image_picker_for_web)
のパッケージを使用しないといけません。

image_pickerでは import 'dart:io';
image_picker_for_webでは import 'dart:html’;
それぞれ上記のimportが必要ですが、こちらをビルドしようとするとコンパイルエラーが発生してしまいます。

そこで、Dartにはファイルを条件付きでインポートまたはエクスポートできる実装があるのでそちらを利用して実装しました。(https://dart.dev/guides/libraries/create-library-packages#conditionally-importing-and-exporting-library-files)

詳しくはこちらを参考にさせて頂きました。ありがとうございます!!
みなさんも参考にされてください。
(https://qiita.com/strivesdfpx379/items/a2e9493405f4d754a982)

  • flutter_secure_storage

メジャーなパッケージで公式ページにも[PLATFORM|Web]と記載されていて、使用可能な表記ですが、ローカルデータを取得できませんでした。

代わりにshared_preferencesを使用しました。

よく読んでみるとREADMEには「現段階では自己責任で使用してください」とのことなので、できるだけFlutterWebでの使用は避けた方が良さそうです。
(https://github.com/mogol/flutter_secure_storage/tree/develop/flutter_secure_storage#configure-web-version)

ブレークポイントが使えない!?

(私はVSCodeで実装しています。)
Flutter Webはブレークポイントが動作しないイメージでしたが、有効化は確認できました。

ですが、ブレークポイントが上手く動作しない場合があります。

Flutter2.10.2で開発していたので、version 3.3.9に上げてみたところ、低いバーションよりはブレークポイントが良くなっていますが、ステップオーバーがうまく止まってくれないのでデバッグしにくい印象です。
なるべくFlutterのバージョンは最新にして、細かくブレークポイントを打つか、printやlogを利用して値を出力するなどの対応が必要です。

初回起動時の読み込みが遅い

スマホアプリ側では取得できていたデータが、Webアプリだとうまく取得できずUIが表示されないこということが起きました。FlutterWebでのUIの描画が終わる前に、データ取得ロジックが走ってUIへの反映が上手くいってないのではないかと思います。そこで、UIの描画後にデータ取得ロジックを呼ぶために、5秒遅延させて実行させました。
(元々、遅延処理していたのですがそれでも表示されませんでした。)

Future.delayed(const Duration(seconds:5),()async{
state = state.copyWith(isLoading: true);
//データを取得する。APIを叩くなどの処理
});

そうすることで、初回画面を問題なく表示することができました。

XMLHttpRequest error が発生したときの対処法

こちらはCORS(Cross-Origin Resource Sharing)に関連したエラーで、バックエンドの対応が必要です。
詳しくはこちらをご覧ください。(https://blog.pentagon.tokyo/3119/

開発環境でしたら下記対応で実装は進められます。
1.flutter/bin/cache のファイルに移動して flutter_tool.stampを削除

2.flutter/packages/flutter_tools/lib/src/web/chrome.dartファイルを開き
--disable-extensionsの下に--disable-web-security,を追記

追記したコードの最後にはカンマを忘れずに!

まとめ

今回Flutter Webで対応した箇所は一部の機能ですが、画像周りの実装に時間がかかってしまい苦戦しました。
あと、FlutterWebでのエラーはまだ情報が少ないので解決策や対応案が分かりづらいです。
アプリの内容によってはパッケージがFlutterWeb対応しておらずWebアプリとスマホアプリとで書き分けが必要でコードが複雑になる事もあるので、パッケージを使用する際は注意してください。

FlutterWebで使えないメジャーなパッケージもあるものの、画像周りやローカルデータの保存以外は割と問題なく動いてくれるので、それには感動しました!
既存のスマホアプリのコードを流用してWebアプリを実装できるのがクロスプラットフォームであるFlutterの魅力ですね!

おまけ

Flutterに関する知識を深めたい方には、『Flutterの特徴・メリット・デメリットを徹底解説』という記事がおすすめです。

この記事では、Flutter アプリ開発の基本から、Flutter とは何か、そして実際のFlutter アプリ 事例を通じて、その将来性やメリット、デメリットまで詳しく解説しています。
Flutterを使ったアプリ開発に興味がある方、またはその潜在的な可能性を理解したい方にとって、必見の内容となっています。

ぜひ一度ご覧ください。

採用情報はこちら
目次