Flutter Web で Firestore を使う

Flutter WebでFirestore動かせるのかなーと思ったのでやってみました。

## 事前準備
[flutter webのアプリをfirebase hostingで公開する](https://qiita.com/hiko1129/items/b55835968820d6e37d27)のときも書いたけど、flutter webを動かせるところまでは下記等を参考に

[flutter_web](https://github.com/flutter/flutter_web)
[flutter webでexampleを動かすまで(flutterインストール済みを想定)](https://qiita.com/hiko1129/items/efc20792016a22a7c88a)
[Flutter Webを動かしたときにつまづいたこと](https://qiita.com/Nkzn/items/402a29fe9bb517ce78aa)

flutter webが動かせる状態で、[tools-support-for-flutter-web-development](https://github.com/flutter/flutter_web#tools-support-for-flutter-web-development)を参考に新規プロジェクトを作成

## FirebaseのWeb版の設定を行う
[dart packageのfirebase](https://pub.dev/packages/firebase)のドキュメントに記載されているとおりに下記のように設定を行いました。

### pubspec.yamlを更新
pubspec.yamlのdependenciesにfirebaseを追加。

```yaml
dependencies:
  firebase: ^5.0.0
```

### web/index.htmlを更新
web/index.htmlにfirebaseのscriptタグを追加。

```html
  <script src="https://www.gstatic.com/firebasejs/5.5.2/firebase-app.js"></script>
  <script src="https://www.gstatic.com/firebasejs/5.5.2/firebase-firestore.js"></script>
```

## main.dartにfirestoreの記述等を追加

flutterのプロジェクト作成時の雛形にfirestoreの諸々の（とりあえず動く）コードを追加（initializeAppの内容は変更が必要です）。

```dart
import 'package:firebase/firebase.dart';
import 'package:firebase/firestore.dart' as fs;
import 'package:flutter_web/material.dart';

void main() {
  initializeApp(
    apiKey: "YourApiKey",
    authDomain: "YourAuthDomain",
    databaseURL: "YourDatabaseUrl",
    projectId: "YourProjectId",
    storageBucket: "YourStorageBucket",
  );

  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final fs.Firestore store = firestore();
  final List<Map<String, dynamic>> messages = List();

  fetchMessages() async {
    var messagesRef = await store.collection('messages').get();

    messagesRef.forEach(
      (doc) {
        messages.add(doc.data());
      },
    );

    setState(() {});
  }

  @override
  void initState() {
    super.initState();
    fetchMessages();
  }

  @override
  Widget build(BuildContext context) {
    // The Flutter framework has been optimized to make rerunning build methods
    // fast, so that you can just rebuild anything that needs updating rather
    // than having to individually change instances of widgets.
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () async {
          var m = Map<String, String>();
          m['content'] = 'hogehoge';
          await store.collection('messages').add(m);
          setState(() {
            messages.add(m);
          });
        },
        child: Icon(Icons.add),
      ),
      body: ListView(
        children: messages.map(
          (message) {
            return ListTile(title: Text(message['content']));
          },
        ).toList(),
      ),
    );
  }
}

```


悲しいことに下記コマンドだとエラーはきます。
＊ この件の[issue](https://github.com/flutter/flutter/issues/32347)

```console
$ webdev serve
```

なぜか下記のようにrelease modeだと動きます。
この問題が直るまでは遊びで使うのも厳しい感じがします。


```console
$ webdev serve -r
```

下のように無事表示されました。（floating action button何度か押したあとのものです。）

![スクリーンショット 2019-05-09 23.20.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117867/da457a94-8c5a-d857-92bf-18115610c7d9.png)

Flutter Webはまだテクニカルプレビューですが、URLが変わらない問題+~~配信のサイズが大きい問題~~を除けば、すぐに遊びに使うには十分な領域に達しそうだなと思いました。
全然コード書けねーってなったのでDartもFlutterもちゃんと勉強しようとも思いました。。。

## 追記
[このissue](https://github.com/flutter/flutter/issues/32524)によれば

```console
$ webdev serve
```
で動かすにはpubspec.yamlのdev_dependenciesのbuild_runnerとbuild_web_compilersを下記のように変更すれば良いようです。

```yaml
dev_dependencies:
  build_runner: any
  build_web_compilers: '>=1.0.0 <2.0.0'
```

上記のようにすることで`webdev serve -r`を使わなくとも動くようにはなるみたいです。

## 関連
前回は[flutter webのアプリをfirebase hostingで公開する](https://qiita.com/hiko1129/items/b55835968820d6e37d27)書いてました。

[[Flutter] 既存のFlutterのコードをFlutter Webで動かしてみた](https://qiita.com/hiko1129/items/7cb497fd219039f9f4f8)ってやつも書きました(Firebaseは関係ないやつです)。