FlutterでWebアプリをリリースする際にやったこと


FlutterでWebアプリをリリースする際にやったことを簡単にまとめる。
Flutter webの有効化手順やFirebaseの導入などは割愛する。
モバイル向けにはすでにできてるアプリをWebアプリとして公開したいというニーズ向けの記事。
リリースしたWebアプリ↓

https://codes.enoiu.com/
https://clqa.enoiu.com/

webアプリを実行してもエラーが出る問題

Firebase Authenticationを利用しているため、ポート番号を登録しているものにする必要がある。
localhost:5000はデフォルトで登録されているので、以下のコマンドを実行すれば正常にwebアプリをデバッグできる。

flutter run -d chrome --web-hostname localhost --web-port 5000

フォント問題

日本語の漢字が中国語のフォントになる問題がある。
以下の記事でまとめた。

https://zenn.dev/enoiu/articles/596078e878145d

Dialogのエラー

モバイル端末では出なかったAlertDialogでのRenderboxなんたらみたいなエラーが出る場合がある。(たぶんAlertDialogのcontentのとこでColumnとかScrollviewみたいなのを指定しているとき。)
contentのとこをSizedBoxで囲んで、widthを指定すると解消した。

パッケージのweb対応確認

パッケージによっては、webに対応していないものや、webだと動作が異なるものがある。
例えば、file_pickerはwebだと動作が異なる。
file_pickerをwebでも動作する方法については以下のスクラップ↓

https://zenn.dev/enoiu/scraps/eef936965c77ab
また、AdMobやアプリ評価関連のパッケージは使えない。
Webで使わないようにするには、kIsWebを使用するとよい。

実装例↓

if (!kIsWeb) {
  final InAppReview inAppReview = InAppReview.instance;
  if (await inAppReview.isAvailable()) {
    Future.delayed(const Duration(seconds: 1), () {
      inAppReview.requestReview();
    });
  }
}

また、final BannerAd _bannerAd;とか定義しただけでもPlatformエラーが出るので、lateをつけて対応した。(lateをつけることで、その変数が使用されるまで読み出されない。kIsWebによって変数を使用させなければ、webでは読み出されずエラーが出なくなる)
ただ、この方法がいいかどうかはわからない。とりあえず動いたのでよしとする。

tooltip追加

モバイルでの使用時にはあまり気にならないが、Web版の場合、PCで使うとマウスオーバーという操作があるため、tooltipを設定したほうがよい。

IconButton(
  icon: const Icon(Icons.sort),
  tooltip: '並び替え', //追加
  onPressed: () {}
)

tooltipが定義されていないWidgetで使うには、Tooltip widgetを使う。

Tooltip(
  message: '閉じる',
  child: OutlinedButton(
    onPressed: () {},
    child: const Icon(Icons.clear),
    style: OutlinedButton.styleFrom(
      shape: const CircleBorder(),
    )
  ))

AppBarの左上のメニューアイコンや戻るアイコンなどにはデフォルトでtooltipが指定されている(日本語にも対応している←多言語化で表示された)が、任意のtooltipを指定するには、以下のようにleadingを設定する。

appBar: AppBar(
  title: Text('Title'),
  leading: Builder(
    builder: (BuildContext context) {
      return IconButton(
        icon: const Icon(Icons.menu),
	onPressed: () {
	  Scaffold.of(context).openDrawer();
	},
	tooltip: '目次',
      );
    },
  ),
  //省略

ちなみに、PopupMenuButtonにもデフォルトでtooltipが指定されていた(日本語だと「メニューを表示」というtooltip)。

アプリアイコン設定

アプリアイコンは、flutter_launcher_iconsパッケージを使用して設定すると思うが、これはwebには対応していない。
webでのアプリアイコンと一口にいっても、タブに表示されるfavicon、ホーム画面やデスクトップのショートカットとして表示されるアイコン、androidやiosでホーム画面に追加した際に表示されるアイコンなど様々ある。
現時点で、flutterのパッケージでこれらを設定できるものはないようなので、六法アプリでは以下のstackoverflowの回答を参考にして進めた。

https://stackoverflow.com/questions/56745525/how-to-configure-icon-for-my-flutter-web-application
しかし、もっと簡単にできる以下記事の方法をCLQAアプリでは採用した。
webフォルダ内にあるpngファイルを自分のアイコンのものに置き換えればいける。
https://qiita.com/hidea/items/4c003c6941a9b795c318
webフォルダ内にあるpngファイルは、
  • favicon.png
  • Icon-192.png
  • Icon-512.png
  • Icon-maskable-192.png
  • Icon-maskable-512.png

の5つだった(たぶんFlutterのバージョンによって異なる)。
上の3つは、flutter_launcher_iconsで使ったものをサイズ変更して置き換えた。
サイズは、デフォルトで用意されていたものと同じにした。
下2つのmaskableはAndroidでいうアダプティブアイコンみたいなものらしい。
以下の記事を参考に作成した。

https://web.dev/i18n/ja/maskable-icon/

title, description, iOS meta tag設定

webフォルダのindex.html内にある<title>タグと<meta name="description" content="">を変更する。
このtitleとdescriptionは、検索エンジンで表示されるもの。
titleはアプリ読み込み時のタブにも表示される(読み込み後は後述のmanifest.jsonで指定したtitleが表示される)ので、ちゃんと指定しておく。
同じくindex.html内にある<!-- iOS meta tags & icons -->のところも変更しておく。

  <!-- iOS meta tags & icons -->
  <meta name="apple-mobile-web-app-capable" content="yes">
  <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
  <meta name="apple-mobile-web-app-title" content="CLQA">
  <link rel="apple-touch-icon" href="icons/Icon-192.png">

apple-mobile-web-app-capableは、ホーム画面に追加したアイコンから起動するとアドレスバーとかが非表示になって、ネイティブアプリっぽい見た目になる機能。
apple-mobile-web-app-status-bar-styleは、ステータスバーのスタイルを指定する。
詳細は、以下の記事。

https://medium.com/appscope/changing-the-ios-status-bar-of-your-progressive-web-app-9fc8fbe8e6ab

manifest.json設定

webフォルダ内のmanifest.jsonを設定する。
このmanifest.jsonの設定によって、webアプリとしてどのように振る舞うか(ネイティブアプリっぽい感じにするとか)を決めることができる。
ネイティブアプリっぽい感じのWebアプリをPWAというらしい。つまり、PWAの設定をmanifest.jsonでできるということだと思う。
デフォルトでは、以下のようになっていた。(iconsの部分は省略)。

{
    "name": "clqa",
    "short_name": "clqa",
    "start_url": ".",
    "display": "standalone",
    "background_color": "#0175C2",
    "theme_color": "#0175C2",
    "description": "A new Flutter project.",
    "orientation": "portrait-primary",
    "prefer_related_applications": false,
    "icons": [
    //省略
    ]
}

それぞれのキーの説明は以下のサイトを確認。

https://developer.mozilla.org/ja/docs/Web/Manifest
簡単にふれると、
  • nameはタブやホーム画面追加したときに表示される名前。
  • nameが長い場合は、short_nameが表示される。
  • start_urlはウェブアプリの開始URLを指定する。そのままでおk。
  • displayはwebアプリの表示モードを指定する。standaloneは単独のアプリっぽい感じになる。
  • background_colorは、アプリ読み込み時に表示される色(=スプラッシュ画面の色)。
  • theme_colorは、ステータスバーやアドレスバー(Android版Chromeだとわかりやすい)の色。
  • descriptionは、index.htmlのdescriptionで同じでいいと思う
  • orientationは、画面の向き。縦固定したいならportraitにする。
  • prefer_related_applicationsは、PlaystoreやAppstoreのネイティブアプリを勧めるならtrueにする(related_applicationsの指定が必要)。

という感じ。
六法アプリでは、以下のようにしている。

{
    "name": "web六法",
    "short_name": "六法",
    "start_url": ".",
    "display": "standalone",
    "background_color": "#795548",
    "theme_color": "#795548",
    "description": "webで閲覧できるブラウザ六法アプリです。e-Govが提供している法令APIを使用しています。",
    "orientation": "portrait-primary",
    "related_applications": [
        {
            "platform": "play",
            "url": "https://play.google.com/store/apps/details?id=com.enoiu.codes",
            "id": "com.enoiu.codes"
        }, 
        {
            "platform": "itunes",
            "url": "https://itunes.apple.com/app/六法-条番号検索をダブルタップで/id1595987434"
        }
    ],
    "prefer_related_applications": true,
    icons: //省略
}

OGP設定

SNSでシェアした際やブログカードで表示されるタイトルや画像、説明を設定する。
まず、OGPを使うという宣言のために、index.html内にある<head>を編集する。

- <head>
+ <head prefix="og: https://ogp.me/ns#">

次に、<head></head>内に追加する。

<meta property="og:title" content="CLQA for PC">
<meta property="og:type" content="website">
<meta property="og:url" content="https://clqa.enoiu.com/">
<meta property="og:image" content="https://clqa.enoiu.com/Icon-512.png">
<meta property="og:image:type" content="image/png">
<meta property="og:image:width" content="512">
<meta property="og:image:height" content="512">
<meta property="og:image:alt" content="CLQA logo">
<meta property="og:description" content="Card List Q&A: Make Your Flashcards Lists for PC">
<meta name="twitter:card" content="summary">
<meta name="twitter:site" content="@enoiu2020">

imageを指定するURLは、iconsフォルダ内を指定する(https://clqa.enoiu.com/icons/Icon-512.png)と画像が表示されなかったため、favicon.pngがある階層と同じところに画像を追加し、URLを指定した。
以下のサイトを参考にした。

https://ogp.me/
https://digitalidentity.co.jp/blog/seo/ogp-share-setting.html
これで一通りの設定はとりあえず完了。

サーバー・ドメイン準備

公開するためのサーバー・ドメインを準備する。
私は、ホームページ(enoiu.com)のサブドメイン(clqa.enoiu.com、codes.enoiu.com)を作ってそこに公開している。
サブドメインを利用しているのは、サブドメインだと追加のドメイン代がいらず、また、ホームページがAdsense審査に通っており、サブドメインだとすぐにAdsense広告を貼れるから(Adsense広告を入れる方法については後述)。
新規にサーバーを契約した場合、サーバーが使えるようになるまでに少し時間がかかるので、早めにやっておく。
また、SSL設定(https化)もしておいたほうがいいと思う。

サーバーにアップロード

サーバー・ドメインの準備・設定が完了したら、webアプリをビルドしてサーバーにアップロードする。
ビルドするには、以下のコマンドを実行する。

flutter build web

すると、プロジェクト内のbuildフォルダにwebフォルダが生成されるので、そのwebフォルダの中身をすべてサーバーにアップロードすればOK。
サーバーにアップロードするには、FTPソフトを使う。
WindowsではFFFTP、MacではFileZillaを使うのが主流だと思う。
FTPソフトの使い方、サーバーアップロード方法は割愛。

※Googleログインが使えなかった問題について

https://zenn.dev/enoiu/scraps/bd9c45cef844d8

Adsense導入

すでにAdsenseアカウントがある前提で進める。
Google Adsenseページの左側にある「サイト」から追加したいドメインを押して、詳細を表示を選択。
サブドメインを追加をクリックして、サブドメインを追加。

追加したら、左側にある「広告」を押して、コードを取得をクリック。
表示されたコードをindex.htmlの<head></head>内に追加。
これで、自動広告(アンカー広告)がオンになっていれば、アンカー広告が表示される。

ただ、このアンカー広告は、閉じることができるが、閉じるつまみのところが操作の邪魔をする可能性がある(特にモバイル端末ではAppBarの左上のボタンと干渉する)。
そのため、アンカー広告が邪魔になるなら、自動広告をオフにして、広告ユニットを自分で追加する必要がある。
自動広告をオフにするには、コードを取得したページのドメインのところにある一番右の編集ボタンをクリック。
広告設定の一番下にあるページ除外のところの「管理」をクリック。
除外設定を追加をクリックし、除外したいドメインを入力、このセクションのすべてのページを選択し追加する。

広告ユニットを追加する方法については以下の記事が参考になる。

https://yuyu-log.com/flutter-web-adsense/

CLQAアプリでは、PCでの利用を前提としているので、とりあえずアンカー広告でいくことにした。
PCだと、アンカー広告のつまみは下部にあるので、以下のpaddingを追加した。

padding: const EdgeInsets.only(bottom: 25)

SEO対策について

SEOについてよくわかっていないが、Flutterでのwebアプリは一つのページで構成されており、bodyタグ内に内容があるわけではないので、SEO的にはダメダメらしい。

https://www.quora.com/How-is-the-Flutter-web-good-with-SEO
SEO対策のパッケージも一応あるっぽい。
https://pub.dev/packages/seo_renderer
https://medium.com/mindful-engineering/flutter-web-seo-friendly-317528c29cc6
今のところ、webアプリ紹介ページみたいなのを別途作って、そのページのSEO対策をするのがよさそう。
https://codes.enoiu.com/
https://clqa.enoiu.com/