はじめに
Flutterのバージョンを 3.27 から 3.29 に上げる際、以下のWarningが出ました。
Synthetic package output (package:flutter_gen) is deprecated:
https://flutter.dev/to/flutter-gen-deprecation. In a future release, synthetic-package will default tofalseand will later be removed entirely.
こちらのWarningについて少し勘違いしていたのと、どうして非推奨になるのかしっかり理解できていなかったので、整理してみました。
“flutter_gen”とは
https://pub.dev/packages/flutter_gen
Flutterプロジェクトのアセット(画像、フォント、カラーなど)へのアクセスを、型安全に扱えるようにするコード生成ツールです。
通常、画像などのアセットを使う場合、以下のような文字列でパスを指定します。
Image.asset('assets/images/my_profile_icon.png');
このコードの問題点は、パスの文字列をタイプミスした場合でもコンパイルエラーにならず、アプリを実行してその画面を開くまで、間違いに気づくことができません。
flutter_gen を使うと、”dart run build_runner build” などのコマンドで、これらのアセットへの参照をDartクラスとして自動生成してくれます。
そのため、以下のように使用することができるようになります。
Assets.images.myProfileIcon.image();
これによるメリットはいろいろありますが、Assetsクラスに存在しないアセットを呼び出すとコンパイル時にエラーになったり、IDEでの自動補完機能により利用可能な画像が候補として表示できるようになったりします。
なぜ”deprecated”なのか
公式に説明がありました。
https://docs.flutter.dev/release/breaking-changes/flutter-generate-i10n-source
「flutter_gen」は、flutterコマンドライン ツールによって作成される仮想(合成)パッケージで、開発者がそのパッケージをインポートして、「internationalization」(ローカライズ)などの生成されたシンボルや機能にアクセスできるようにします。パッケージはアプリの「pubspec.yaml」にリストされておらず、生成された「package_config.json」ファイルを書き換えることによって作成されるため、多くの問題が発生しています。
これは、flutter_gen のツール自体が非推奨になる(使えなくなる)ということではなく、flutter_gen が、主ローカライゼーション(l10n)のために動作していた古い仕組みである、「合成パッケージ (synthetic package)」が非推奨となったということでした。
非推奨の “Synthetic package”
“Synthetic package”とは、プロジェクト内に物理的なファイルが存在しないにも関わらず、Flutterのビルドツールが、そこにパッケージがあるかのように振る舞う仮想的なパッケージでした。
この仕組みは、”pubspec.yaml”ファイルに”flutter: generate: true”と設定した場合、開発者が明示的にコード生成コマンド (build_runner) を実行していなくても、Flutterツールが内部で仮想的に ”package:flutter_gen” というパッケージが存在するかのように振る舞う仕組みです。
この仕組みは、「ローカライゼーション(l10n)」で必要なものでした。
非推奨の理由としては、以下のようなものが挙げられます。
IDE(VS Codeなど)で認識されない
IDEはプロジェクト内の “lib/” フォルダや “pubspec.yaml” ファイルを見ますが、”flutter_gen” というパッケージは “pubspec.yaml” にも “lib/” の中にも存在していないため、IDEはそのパッケージを認識できない(エラーで赤線表示など)状態になります。
Flutterツールの動作
“flutter run” コマンドを実行すると、Flutterビルドツールにより、”.arb” ファイルからローカライゼーション用のDartコードを一時的な場所(”build” キャッシュフォルダなど)に自動生成します。その後、Dartコンパイラに対して「”package:flutter_gen/…” というインポート要求が来た際には、この一時的な場所にあるファイルを使うように”.dart_tool/package_config.json” という設定ファイルを動的に書き換えます。
問題点
IDEではエラーになるのにFlutterビルドツールでは成功するという、開発者が混乱する状況が生み出されることが問題となっており、これを避けるために非推奨となりました。
解決策
現在推奨されている方法は、「仮想」ではなく「物理的」にファイルを生成することです。
- 明示的にコマンドを実行
開発者は “flutter gen-l10n”や “dart run build_runner build”といったコマンドを手動実行する必要があります。 - 物理ファイルの生成
コマンド実行により、プロジェクト内で設定した “lib/generated/” フォルダなどに、実際の “.dart” ファイルが物理的に生成されます。
IDEは “lib/generated/” フォルダに実体のあるファイルを検出できるため、”import”文を正しく認識し、エラー表示がされなくなります。