firebase / flutterfire

🔥 A collection of Firebase plugins for Flutter apps.
https://firebase.google.com/docs/flutter/setup
BSD 3-Clause "New" or "Revised" License
8.71k stars 3.97k forks source link

🐛 [cloud_firestore] Disable offline persistence on web #6672

Closed ConcenTech closed 3 years ago

ConcenTech commented 3 years ago

In my web app, I only want to listen to streams of data from the online database.

In the documentation there is the following information on offline persistence:

This functionality is enabled by default, however it can be disabled if needed. The settings must be set before any Firestore interaction is performed:

// Web.
await FirebaseFirestore.instance.enablePersistence();

// All other platforms.
FirebaseFirestore.instance.settings =
    Settings(persistenceEnabled: false);

This reads as though offline persistence is disabled by default on web and can only be enabled?

Currently if listen to a stream, go offline and add a document to the collection I'm listening to, the new document appears in the stream. Is this expected behaviour, as offline persistence hasn't been enabled.

I expected the write to fail, so I can then handle this case.

markusaksli-nc commented 3 years ago

Hi @ConcenTech Could you please provide your flutter doctor -v and flutter pub deps -- --style=compact? What versions of the CDN are you importing in index.html? Thank you

ConcenTech commented 3 years ago

Hi, Please find the requested information below.

Thanks

flutter pub deps -- --style=compact
Flutter Doctor -v [√] Flutter (Channel stable, 2.2.3, on Microsoft Windows [Version 10.0.22000.71], locale en-GB) • Flutter version 2.2.3 at C:\src\flutter • Framework revision f4abaa0735 (3 weeks ago), 2021-07-01 12:46:11 -0700 • Engine revision 241c87ad80 • Dart version 2.13.4 [√] Android toolchain - develop for Android devices (Android SDK version 30.0.2) • Android SDK at C:\Users\kgcar\AppData\Local\Android\sdk • Platform android-30, build-tools 30.0.2 • Java binary at: C:\Program Files\Android\Android Studio\jre\bin\java • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b01) • All Android licenses accepted. [√] Chrome - develop for the web • Chrome at C:\Program Files\Google\Chrome\Application\chrome.exe [√] Android Studio (version 4.1.0) • Android Studio at C:\Program Files\Android\Android Studio • Flutter plugin can be installed from: https://plugins.jetbrains.com/plugin/9212-flutter • Dart plugin can be installed from: https://plugins.jetbrains.com/plugin/6351-dart • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b01) [√] VS Code (version 1.58.2) • VS Code at C:\Users\kgcar\AppData\Local\Programs\Microsoft VS Code • Flutter extension version 3.24.0 [√] Connected device (2 available) • Chrome (web) • chrome • web-javascript • Google Chrome 91.0.4472.164 • Edge (web) • edge • web-javascript • Microsoft Edge 91.0.864.71 • No issues found!
  <script src="https://www.gstatic.com/firebasejs/8.6.1/firebase-app.js"></script>
  <script src="https://www.gstatic.com/firebasejs/8.6.1/firebase-firestore.js"></script>
  <script src="https://www.gstatic.com/firebasejs/8.6.1/firebase-auth.js"></script>
  <script src="https://www.gstatic.com/firebasejs/8.6.1/firebase-functions.js"></script>
markusaksli-nc commented 3 years ago

I was able to reproduce the behavior but not sure if this is intended or not.

cloud_firestore: ^2.4.0
  <script src="https://www.gstatic.com/firebasejs/8.6.1/firebase-app.js"></script>
  <script src="https://www.gstatic.com/firebasejs/8.6.1/firebase-firestore.js"></script
flutter doctor -v ``` [√] Flutter (Channel master, 2.4.0-5.0.pre.166, on Microsoft Windows [Version 10.0.19041.1110], locale et-EE) • Flutter version 2.4.0-5.0.pre.166 at C:\Development\flutter_master • Upstream repository https://github.com/flutter/flutter.git • Framework revision 2dc11a85ff (11 hours ago), 2021-07-22 17:56:03 -0700 • Engine revision fbbb3b3f7b • Dart version 2.14.0 (build 2.14.0-343.0.dev) [√] Android toolchain - develop for Android devices (Android SDK version 30.0.2) • Android SDK at C:\Users\marku\AppData\Local\Android\sdk • Platform android-30, build-tools 30.0.2 • Java binary at: C:\Users\marku\AppData\Local\JetBrains\Toolbox\apps\AndroidStudio\ch-0\202.7486908\jre\bin\java • Java version OpenJDK Runtime Environment (build 11.0.8+10-b944.6842174) • All Android licenses accepted. [√] Chrome - develop for the web • Chrome at C:\Program Files\Google\Chrome\Application\chrome.exe [√] Visual Studio - develop for Windows (Visual Studio Community 2019 16.7.7) • Visual Studio at C:\Program Files (x86)\Microsoft Visual Studio\2019\Community • Visual Studio Community 2019 version 16.7.30621.155 • Windows 10 SDK version 10.0.18362.0 [√] Android Studio (version 4.2) • Android Studio at C:\Users\marku\AppData\Local\JetBrains\Toolbox\apps\AndroidStudio\ch-0\202.7486908 • Flutter plugin version 58.0.1 • Dart plugin version 202.8531 • Java version OpenJDK Runtime Environment (build 11.0.8+10-b944.6842174) [√] IntelliJ IDEA Ultimate Edition (version 2021.1) • IntelliJ at C:\Users\marku\AppData\Local\JetBrains\Toolbox\apps\IDEA-U\ch-0\211.7628.21 • Flutter plugin can be installed from: https://plugins.jetbrains.com/plugin/9212-flutter • Dart plugin can be installed from: https://plugins.jetbrains.com/plugin/6351-dart [√] Connected device (4 available) • SM G950F (mobile) • ce12171c51cc001c03 • android-arm64 • Android 9 (API 28) • Windows (desktop) • windows • windows-x64 • Microsoft Windows [Version 10.0.19041.1110] • Chrome (web) • chrome • web-javascript • Google Chrome 91.0.4472.164 • Edge (web) • edge • web-javascript • Microsoft Edge 91.0.864.67 • No issues found! ```
Minimal reproducible code sample ```dart import 'package:flutter/material.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:cloud_firestore/cloud_firestore.dart'; const USE_FIRESTORE_EMULATOR = false; const COLLECTION = "basic-example"; Future main() async { WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp(); if (USE_FIRESTORE_EMULATOR) { FirebaseFirestore.instance.useFirestoreEmulator('localhost', 8080); } //await FirebaseFirestore.instance.enablePersistence(); runApp(FirestoreExampleApp()); } class FirestoreExampleApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Firestore Example App', theme: ThemeData.dark(), home: Scaffold( body: Center(child: Body()), appBar: AppBar( title: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ const Text('Firestore Example: Basic'), StreamBuilder( stream: FirebaseFirestore.instance.snapshotsInSync(), builder: (context, _) { return Text( 'Latest Snapshot: ${DateTime.now()}', style: Theme.of(context).textTheme.caption, ); }, ) ], ), ), ), ); } } class Body extends StatefulWidget { const Body({Key? key}) : super(key: key); @override _BodyState createState() => _BodyState(); } class _BodyState extends State { var _colRef = FirebaseFirestore.instance.collection("$COLLECTION"); var _collectionStream = FirebaseFirestore.instance.collection('$COLLECTION').snapshots(); @override Widget build(BuildContext context) { return Column( children: [ StreamBuilder( stream: _collectionStream, builder: (context, AsyncSnapshot snapshot) { if (snapshot.hasError) { return Text('${snapshot.error}'); } if (!snapshot.hasData) { return CircularProgressIndicator(); } final data = snapshot.requireData; String docs = ''; for (int i = 0; i < data.size; i++) { docs += data.docs[i].id; if (i != data.size - 1) docs += ', '; } return ListTile( title: const Text('Test collection:'), subtitle: Text(docs), leading: IconButton( icon: Icon(Icons.add), tooltip: "Add document", onPressed: () async { await _colRef.doc("${data.size}") .set({"dummy": "document"}); }, ), trailing: IconButton( icon: Icon(Icons.remove), tooltip: "Remove document", onPressed: data.size == 0 ? null : () async { await data.docs[data.size - 1].reference.delete(); }, ), onTap: () async { var col = await _colRef.get(); var docs = '$COLLECTION:\n'; for (var value in col.docs) { docs += value.id + value.data().toString() + "\n"; } var message = '${docs}isFromCache: ${col.metadata.isFromCache}'; print(message); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(message), ), ); }, enableFeedback: true, ); }, ), ], ); } } ```
russellwheatley commented 3 years ago

Hey @ConcenTech, this is working as intended.

On web, the default is to disable persistence. The documents are still in-memory, and once the browser tab is refreshed/closed, the data will be lost (i.e. not persisted).

If you enable persistence, you will still have that data should you refresh/close the browser.

Below is a script you can run if you wish to see how firebase web handles it. Toggle the enablePersistence() to see docs persisted/not persisted once you close/refresh the browser.

Hope this helps.

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

  var firebaseConfig = {
    // TODO - insert your own config here
  };
  firebase.initializeApp(firebaseConfig);
  var firestore = firebase.firestore();

  (async function init() {
    // TODO - Toggle enable persistence to see the difference
    // await firestore.enablePersistence();

    await firestore.disableNetwork();
    console.log('disabled network');
  })()

  const collection = 'flutter-tests';

  firestore.collection(collection).onSnapshot((snap) => {
    console.log('docs: ', snap.docs.length);
  });

  async function add() {
    await firebase.firestore().collection(collection).add({ doc: 'here' });
  }

</script>
<button onclick="add()">add</button>
</html>