Lorem Ipsum Dummy Text Generator の Flutter DevTools Extension を作りました

作成日: 2025-01-22 /

Panache という Lorem Ipsum Dummy Text Generator の Flutter DevTools Extension を作ったので、それまでのいきさつを書く。

panache | Flutter package

panache | Flutter package

https://pub.dev

panache | Flutter package

開発するきっかけ

去年の FlutterKaigi 2024Flutter DevTools Extension を作るセッションを参加した。まず作れるんだと感心したので、何か自分で作ってみたいと感じたのが大きかった。セッションでは、Riverpod で保持されているローディング状態をトグルするものだったので、セッションを聞いた当初は自分もアプリと連携するものを作りたいと考えた。しかし、ライブラリとして公開するため、アプリの特性や使用ライブラリに依存しないのと、最初は難易度を下げたいと考えたので、連携を必要としないものを作ることを目標した。

初めて OSS ライブラリを公開したのもあり、今回は DevTools Extension を一般公開するまでのことをまとめた。

DevTools Extensions を開発するにあたって

種類を決める

Flutter DevTools Extension を開発するにあたって、Extension には Standalone ExtensionCompanion Exntension の 2 種類がある。Standalone Extension は Extension だけ配布されたものとなり、反対に Companion Extension は Extension が既存のパッケージの一部として配布されるものになる。具体的には、Companion Extension ではログを取る処理とそれを Extension に表示する機能を両方提供している。その処理をアプリ側で呼び出し、ログを Extension 側で見るといったものとなる。

今回は Extension のみを提供するなので、Standalone Extension を開発するものとする。

ディレクトリ・ファイル構成

どちらの Extension を作るかを選んだあとは、ディレクトリ構成を決めていく。

まずは devtools_extensions の README.md の Step 1: Setup your package hierarchyStep 2: Configure your extension を熟読することをおすすめする。

lib ディレクトリに Devtools Extensions を構成するコードを置くことは普段 Flutter で開発していれば馴染みがあるが、今回大事なのは extension ディレクトリであり、ここに配布用の Extension 関連のコードやアセット、設定ファイルなどをまとめる。配布用にビルドしたアセットたちを extension/devtools ディレクトリに置き、設定ファイルは config.yaml として保存する。

directory_strcuture.txt
my_new_tool
  extension/
    devtools/
      build/
        ...  # pre-compiled output of the Flutter web app under lib/
      config.yaml
  lib/  # source code for your extension Flutter web app
    src/
      ...
extension/devtoosl/config.yaml
name: some_pkg
issueTracker: <link_to_your_issue_tracker.com>
version: 0.0.1
materialIconCodePoint: '0xe0b1'
requiresConnection: true  # optional field - defaults to true

panache のディレクトリ構成config.yaml は最終的にこうした。

panache_directory_strcuture.txt
panache
  extension/
    devtools/
      build/
        ...  # lib コードをビルドし、
      config.yaml
  lib/  # ここに devtools extension を構成するコードを置く。
    src/
      ...
panache/extension/devtools/config.yaml
name: panache
issueTracker: https://github.com/offich/panache/issues
version: 0.0.2
materialIconCodePoint: '0xe651'
requiresConnection: false

ローカルでの開発

DevTools Extension は Flutter Web で作られるので、下のコマンドを実行して、プロジェクト作成する。基本的には README.md の Step 3 に従う。

devtools_extension_create.sh
flutter create --template app --platforms web panache
flutter pub add devtools_extensions devtools_app_shared

DevToolsExtension ウィジェットでラップすれば、最初のセットアップは完了。

main.dart
import 'package:devtools_extensions/devtools_extensions.dart';
import 'package:flutter/material.dart';

import 'package:panache/panache.dart';

void main() {
  runApp(DevToolsExtension(child: const Panache()));
}

最後は DevTools Extension を起動して、表示される。

run.sh
flutter run -d chrome --dart-define=use_simulated_environment=true

開発するものについて

概要を説明したあとは作るもの自体の説明をするが、タイトルにある通り、ダミーテキストを簡単に生成する Extension を作ることをゴールにした。

ちなみに完成したものはこちら ↓

どうやって決めたかというと、セッションの登壇者が web 開発で使われている Google Chrome Extension を参考にするとよいとアドバイスを残していたのを思い出した。なので、早速 Google Chrome Extension のおすすめ一覧やランキングを眺めていると、Lorem Ipsum のダミーテキスト生成の Extension がちらほらあるのに気づいた。はじめて開発するのも相まって、アプリへの依存度もないことから難易度も上がらないだろうと予測を立て、開発することに決めた。

左のサイドバーで、段落、文章、単語数を自由に決めて、ランダムに生成されたテキストが右側に表示されるというものになる。

左のサイドバーでは、それぞれの数は最初 input で入力してもらうことを想定していたが、数字ではなく文字列が変に入力されていないか、もしく入力された数が最大最小の範囲に留まっているかを確認するバリデーションを実装するのは少し骨が折れるので、スライダーを採用した。スライダーについては、Flutter から提供されただ範囲の中でも、その中であらかじめ計算された値にしか更新できず、不便に感じたので、今回は妥協して下のスライダーを使うことにした。

syncfusion_flutter_sliders | Flutter package

syncfusion_flutter_sliders | Flutter package

https://pub.dev

syncfusion_flutter_sliders | Flutter package

右のスペースは FadeTransitionSliderTransition を利用して、テキストが生成されるたびに、下からフェードインされるようにした。複数のアニメーションを組み合わせるときは、このようにラップする。

animation.dart
SlideTransition(
  position: offsetAnimation.value!,
  child: FadeTransition(
    opacity: opacityAnimation.value!,
    child: SelectableText(text, style: PanacheTextStyle.medium),
  ),
);

知見となったことしては、テキストが生成されたら同じアニメーションを開始するにはどうしたらいいかを調べたところ、AnimationController#forwardfrom0.0 に渡せばいいとのこと。最初は reverse してとも考えたので、勉強になった。

forward.dart
  useEffect(() {
    animationController.forward(from: 0.0);

    return;
  }, [text]);

命名について

少し余談になるが、パッケージの名前は panache という名前にした。命名の理由は多くあるが、なにかお酒やカクテルの名前にしたかったのが一番になる。

細かい理由に分解していくと、1 つは「Lorem Ipsum Dummy Text Generator」というシンプルな名前を使用するのを避けたかった。長いし、この記事のように紹介するときに、他のダミーテキストパッケージに紛れて pub dev のサイト内の検索でヒットしないことを避けたかった。

あとは過去の現場で、プロジェクトの名前を使用技術や所属している部署やチームなど関わりがあるものを由来にしないという命名規則にインスパイアされたのもある。名前を流動的に変化があるものにし、プロジェクトの名前が他サービスから参照されていると、名前の変更時に多くの追従作業が発生してしまう。そのため、具体的には何も関係性がない、果物の名前を採用していた。

この命名規則を自分のプロジェクトへ当てはめたときに、最初から変化の機会が多くあるものを由来する予定はなかったが、好きなカクテルから決めるのは割と好感を持てた。なので、自分が開発するライブラリたちにはすべてカクテルの名前を振ることにした。(強いていうなら、一番わかりやすい「Lorem Ipsum DevTools Extensions」という名前が候補にあったが、万が一 DevTools Extensions から別の名前になった場合を考慮して、やはりカクテルの名前を使用することに。)

panache(パナシェ) はフランス生まれのカクテルで、フランス語でまざりあったという意味がある。もともとはビールとレモネードを同量(1 対 1)で割ったカクテルのこと。ただし、現在ではビールとレモネードの組み合わせだけでなく、ビールと透明な炭酸飲料を混ぜ合わせたもの全般を幅広く「パナシェ」と呼ぶみたい。生成されるダミーテキストはローマ語のランダムな言葉たちなので、まさに混ざり合ったものが最終的なアウトプットになるという意味も含んでの panache にした。

一般公開するまで

Extension が完成したあとは、一般公開するまでのことをまとめる。

pub dev にアカウント登録

まずは pub dev にパブリッシャーを登録する必要がある。公式には、個人の Google アカウントより、検証済みパブリッシャーとしてパッケージを公開することが推奨されている。ただ注意しないといけないのが、何か自分のドメインを用意していないとパブリッシャー登録できない。自分はたまたまこのブログを運用し、Google Search Console でドメイン登録しているので、幸いなことに条件を満たしていた。最後リリースする前の大事な作業になるので、注意が必要になる。

GitHub Actions からアップロード

配布するものが完成したなら、最後に pub dev への公開を自動化する。自動化の手段は GitHub Actions からか Google Cloud Service account からかを選択できる。

今回は GitHub Actions を選択し、それに必要な設定を Admin ページで入力していく。設定していくものは、Publishing packages using GitHub Actions を参考にすると良い。

設定が終わったら、workflow を用意するが、DevTool Extension をリリーするときはドキュメントに書いてあるものより少し手を加えないといけないので、注意が必要になる。ドキュメントでは、workflow が dart-lang/setup-dart@v1 の一行のみだが、それはシンプルな dart のスクリプトだけで構成されたパッケージの場合のものとなる。

しかし、DevTool Extension をアップロードするので、Flutter 自体をインストールしないといけない。その workflow だけで使用しているパッケージたちをインストールするのか、認証やアップロードしてくれるのかと悩んだ。調査すると、どうやら dart-lang/setup-dart@v1 の中に内包されているみたいだった。それだけだと Flutter 自体をインストールできないので、workflow の中で Flutter を使えるようにする Action も一緒に使うことで解決させる。

最終的な workflow の中身はこちら。

.github/workflows/publish.yml
name: Publish

jobs:
  publish:
    steps:
      # checkout
      # ...

      - uses: dart-lang/setup-dart@v1
        with:
          sdk: 3.6.0

      - uses: kuhnroyal/flutter-fvm-config-action@v3
        id: fvm-config-action

      - uses: subosito/[email protected]
        with:
          channel: ${{ steps.fvm-config-action.outputs.FLUTTER_CHANNEL }}
          flutter-version: ${{ steps.fvm-config-action.outputs.FLUTTER_VERSION }}

      - name: install dependencies
        run: flutter pub get

      - name: Validate
        run: dart run devtools_extensions validate --package=.

      - name: Build and Copy
        run: dart run devtools_extensions build_and_copy --source=. --dest=./extension/devtools

      - name: Publish
        run: dart pub publish --force

pub dev の Score を気にしよう

いろいろな pub パッケージのページを見てきたが、その score タブは中身を見たことをなかった。今回初めてみたが、この得点が満点に近いものだと安全性や信頼を得られ、多くの開発者からダウンロードしてもらえると考えると、最初リリースするときから満点にしたい。

panache の例だと、Follow Dart files conventionsProvide Documentation が不十分なので、今後対応する。

これからやること

ユニットテスト

リリースすることでリソースがいっぱいでありテストを書けなかったので、知見が溜まり次第、ここのセクションに書いていく。Golden Image Test を移動して、リグレッションテストも書いていきたい。

実際の Devtools Extension でフォーカスが移動しない

現在知見を探しているのだが、DevTools Extension がボタンなどの UI パーツでタブキーでの移動ができないのに困っている。DevTools Extension は Flutter web app で開発するものなので、せっかくならアクセシビリティを考慮しようと考えた。ボタンやスライダーの生成する文章や段落数をキーボードだけで操作できるようにした。(このあたりは別の記事で知見をまとめたい)

しかし、実際の Flutter プロジェクトで確認したところ、開発時には初期表示後でタブキーのキーイベントにフックして移動していたフォーカスが全く反応しなくなっていた。ブラウザでボタンの要素に向けてフォーカスさせたいが、それも難しく、これから詳しく調べていきたい。

感想

初めて Flutter DevTools Extension を開発し、なんだかんだ初めての OSS ライブラリを公開できたので、個人的には満足度が高いものとなった。pub dev へ公開された 3 日後には 150 越えダウンロード数があり、個人的には嬉しさを感じた。数相場がどれぐらいかなのかはわからないが、どれぐらいダウンロードされているかを見られるのはテンションがあがった。よかったら、ダウンロードして、Like もクリックしてもらえると非常に幸いだ。なるべく難易度を下げることでリリースするまでのゴールを達成したので、次は何かアプリ側と連携する DevTools Extension を開発してみたい。

参考にしたサイト

GitHub - lllttt06/flutter_devtools_extension_sample

GitHub - lllttt06/flutter_devtools_extension_sample

https://github.com

GitHub - lllttt06/flutter_devtools_extension_sample

[Flutter] Devtools Extensions で独自の Devtool を開発する

[Flutter] Devtools Extensions で独自の Devtool を開発する

https://zenn.dev

[Flutter] Devtools Extensions で独自の Devtool を開発する