メモ2ブログ

メモtoウェブログ。旧ブログはこちら。 http://sakebook.blogspot.jp/

パッケージが統合されたFlutter for Webへのアップグレード

Flutter for Webのパッケージがflutterに統合されました。それに伴い既存のFlutter for Webのプロジェクトでアップグレードが必要になったのでその記録です。

Upgrading

まだstableには来てないのでdevに向けて、webを有効にします。

$ flutter channel dev
$ flutter upgrade
$ flutter config --enable-web

channelの変更は、次のバージョンがstableに来たら不要になると思います

$ flutter --version
Flutter 1.10.6 • channel dev • https://github.com/flutter/flutter.git
Framework • revision cc3ca9a916 (5 days ago) • 2019-09-25 10:57:58 -0400
Engine • revision 63949eb0fd
Tools • Dart 2.6.0 (build 2.6.0-dev.0.0 69b5681546)

既存プロジェクトですでに作成済みの web/main.dart を削除します。

次に、プロジェクトをFlutter SDK向けに変更していきます。

AndroidiOSディレクトリを作成します

$ flutter create .

pubspec.yamlを置き換えて、flutter_webの部分をflutterに置き換えます。

web/assets/ に置いていた FontManifest.json の内容を移行します。

MaterialIconsは

flutter:
  uses-material-design: true

となり、

fontを利用していた場合は fonts フォルダをプロジェクトルートに作り、そこにフォントファイルを置きます。その後、font名の指定とfontのpathを書きます。

flutter:
  ...
  fonts:
    - family: KosugiMaru
      fonts:
        - asset: fonts/KosugiMaru-Regular.ttf

画像などの素材は、 assets フォルダをプロジェクトルートに作り、そこに移動させます。その後フォルダを指定します。

flutter:
  ...
  assets:
    - assets/

これで web/assets フォルダは空になったと思うので、削除します。

実行は次のコマンドです。Windowが立ち上がります。

$ flutter run -d chrome

ドキュメント的には以上なのですが、自分の環境では更に次のような手順が必要でした。

追加手順

rootBundleのimport

rootBundle を使っている場合、含まれるパッケージが変わっているので flutter/service からimportします。

import 'package:flutter/services.dart' show rootBundle;

assetsのパス

rootBundleでassetsにアクセスしている場合、pathが次のように変わります。

  • some.json

だったものが

  • assets/some.json

になります。assetsに指定しているフォルダからpathを指定する必要があります。

BinaryMessengerへのアクセス

runApp より早いタイミングで rootBundle を利用している場合、chromeのconsoleにエラーが出ます。

Uncaught (in promise) Error: ServicesBinding.defaultBinaryMessenger was accessed before the binding was initialized.
If you're running an application and need to access the binary messenger before `runApp()` has been called (for example, during plugin initialization), then you need to explicitly call the `WidgetsFlutterBinding.ensureInitialized()` first.
If you're running a test, you can call the `TestWidgetsFlutterBinding.ensureInitialized()` as the first line in your test's `main()` method to initialize the binding.

rootBundleがbinaryMessengerを利用しているため、怒られます。回避するためにはエラー文の通り、

WidgetsFlutterBinding.ensureInitialized()rootBundleより先に呼び出します。

dart:htmlのimportエラー

自分はIntelliJで開発しているのですが、Target of URI doesn’t exist: ‘dart:html’. のエラーが出ました。ですが、ターミナルからビルドする分には問題ありませんでした。

現状Dart SDKが提供しているもので、利用できるものとそうでないものがあるみたいです。

github.com

Release Buildのアウトプット先

今までは build/だったのですが、build/web/ に変わりました。Deployする際には注意が必要です。

リリースビルドのコマンドは次です。デフォルトでreleaseのconfigurationになっています。

$ flutter build web

まとめ

パッケージ統合以前のFlutter for Webのプロジェクトでも、アップグレードガイドがあるので移行自体はさっとできます。

ただし、いくつか注意点があるのでハマりすぎないように気をつけてください。

自分の環境において、マイグレーションのドキュメントに書いてないことで気をつける必要があったことは次の5点です。

  • rootBundleのimportが変わる
  • assetsのパスが変わる
  • assetsに早いタイミングでアクセスしている場合はWidgetsFlutterBinding.ensureInitialized() が必要になる
  • Dart SDKのいくつかのパッケージはWebでの利用に制限がある
  • アウトプットのpathが異なる

参考

Upgrading from package:flutter_web to the Flutter SDK · flutter/flutter Wiki · GitHub

Flutter: Unhandled Exception: ServicesBinding.defaultBinaryMessenger was accessed before the binding was initialized - Stack Overflow

Properly enable dart:html imports · Issue #35588 · flutter/flutter · GitHub

Building a web application with Flutter - Flutter

技術書典7にFitbit本の続編を出した

先日開催された技術書典7にサークル参加しました。サークル参加としては2回目で、技術書典5以来なので1年ぶりの参加でした。

前回の参加記事はこちら

sakebook.hatenablog.com

事前準備(執筆編)

1年ぶりで、結構色々忘れていました。

次の記事を参考に環境を構築しました。去年と大きく異なっていたのは、Re:VIEWのメジャーバージョンが2から3に変わっていました。

mochikoastech.hatenablog.com

続編という位置づけで考えていたのですが、旧刊を購入していないと話がわからないのでは敷居が高すぎると思ったので、一部内容は重複してしまうのですが、それぞれ独立して読めるような構成にしました

今回は表紙をお願いすることにしました。

お願いするにあたって、何が決まっていれば嬉しいのかがわからなかったので、こんな感じだと嬉しいなってのをboothからピックアップして雰囲気を伝えました。

あとは表示サイズと仮タイトルを伝えて、ここはこういうふうにしたほうがFitbitをつけてるのが映えるよーってのをやり取りして決めていきました。

印刷は前回と同じく日光企画さんにお願いしました。Fitbit Versa 2の発売日が技術書展7の明後日なので、なるべく最新の情報を詰めたくて前日まで粘ってたのですが、結局開発者向けの新しい情報は公開されませんでした。

前日印刷でも、午前10時までにデータを入稿すれば間に合いはしますが、印刷代が倍くらいに膨れるので最後の手段と思ったほうが良さそうです。

自分の場合だとA5サイズ64ページで50冊印刷して50,240円でした。

事前準備(ブース編)

前回の振り返りを見て、背の高いPOPスタンドを置いておくと目立つというのと、卓上に布があったほうが圧倒的に見栄えが良いことがわかっていたので、準備しました。

シンプルなあの布POPスタンドを用意しました。

今回は本の価格を1000円にしました。残っていた旧刊も売れればいいなと思い持っていきました。旧刊は500円なので、数枚程度500円玉を用意し、万札にも耐えられるように1000円札を用意しました。

あとはPOPスタンドに吊るす紙をA4で印刷し、電子版も対応していたのでQRコードを印刷した紙を用意しました。

当日

若干遅刻してしまいました。サークル入場も遅れていたので結果的に自分はほとんど待つことなく入場できましたが、準備が間に合わないんじゃないかとヒヤヒヤしました。

本は技術書典のバックアップ印刷所さんに依頼しておけばブースまで持ってきてもらえます。当日着いたらすでに届いていました。

実際の部数は65冊ありました。

遅れたこともあり、立ち読み本の扱いがよくわからなかったのですが横のサークルの方に教えてもらい、無事提出できました。準備はサッとできました。

実は今回も売り子を見つけられず一人での参加となりました。辛かったですがお手洗いなどは横のサークルの方が気を利かせてくれて助かりました。

技術書典5でFitbit本を購入し、今回も購入してくださった方がいてめちゃめちゃ嬉しかったです。

後払いで20部、現金で19部の合計39部売れました。印刷代やサークル参加費を考えると赤字です。旧刊は完売したのでそこは良かったです。余った部数が多かったのでboothにあずけて帰りました。boothでも、月に安定して売上が立たなければ保管料金がかかるみたいなので注意です

今回販売した新刊のboothリンクです。Versa 2買った人や購入検討中の人は買って損のない内容になってます。

sakebook.booth.pm

終わってみて

一人参加は相変わらず辛いですが、ちょっとこなれた感じがあります。ウェアラブルバイスに関するサークルがうちと横のサークルしかなく、横の方はその辺りを話題にだしたりしていたのですが、自分はあまりそういう接客ができていなかったです。交流という意味でも接客という意味でもその辺りはもう少しやりようはあったなーと思いました。

立ち読みはしてくれたのですが、そこから購入に至らなかった人がわりといました。本の質の問題なのか、目次から読み取りにくかったのか、思ってたのと違ったのか、その辺りがわからないのが辛いところです。

掛けた時間と帰ってくるお金は相変わらず見合わないですが、サークル参加自体は敷居が低くなってきているので、気になってる方はやってみると良いと思います。自分の好きなことを好き勝手書いていいんですよ!

参考

技術書典7

BOOTH - 創作物の総合マーケット

株式会社 日光企画

DartでCloud Functions for Firebaseを動かす

最近FlutterでDartを触っているので、Dartでなにかできればなと思いました。

ちょっとした処理をしたくなって、Cloud Functions for Firebaseが使えればなと思い調べたところ、DartJavascriptにトランスパイルしてCloud Functionsで利用できるようにするPluginがあったのでその紹介をします。

firebase_functions_interop

pub.dev

READMEが充実しているのでその通りにやればだいたいできます。

build_runnerでビルドして、生成された.jsファイルをpackage.jsonが見るようにします。

デバッグ

serve コマンドでローカルに立ち上げることができます。

$ firebase serve --only functions

ハマったところ

通信はnode_httpで行う

http.getを行おうとすると実行時に次のようなエラーが発生します。

ReferenceError: XMLHttpRequest is not defined

firebase_functions_interopnode_httpで通信を行なっているので、それに合わせます。

Cloud Functions for Firebaseの無料版ではOutbound networkに制限がある

Cloud Functions for Firebase内でSlackなどとOutbound networkを行うと次のようなエラーログが吐かれます

Billing account not configured. External network is not accessible and quotas are severely limited. Configure billing account to remove these restrictions

無料版だとOutbound networkingがGoogle services onlyという制限があります。

firebase.google.com

解決するにはFlameプランかBlazeプランにする必要があります。

作ったもの

SlackのOutgoing WebHooksを使って、トリガーとなる言葉とユーザグループを指定するとランダムにユーザを選択するものを作りました。

github.com

まとめ

DartでもCloud Functions for Firebaseを動かすことはできますが、適宜制約があるのでハマらないように気をつけましょう。

参考

firebase_functions_interop / Dart Package

node-interop/build_node_compilers at master · pulyaevskiy/node-interop / GitHub

Cloud Functions for Firebase - Billing account not configured / Stack Overflow