Keep working offline

An app used where the connection comes and goes, such as a kiosk or a phone on the move, can keep the data it has loaded on the device. Pages keep showing it while offline, and changes made offline are saved when the connection returns.

Turn it on

It is an install setting, off unless you turn it on, and can differ per Firebase project:

npm run arc:configure -- --offline-cache=multi-tab
ValueMeans
offThe default. Firestore keeps nothing on the device, as before.
single-tabThe cache is kept for one browser tab at a time. A second tab of the same site works without it.
multi-tabEvery tab of the site shares the cache. Choose this unless you know the app runs in one tab only.

The value is written to arccms.config.json (key offlineCache) and to src/environments/arc-install.ts. Build and deploy the website for it to take effect. Firestore starts with the cache in the browser only, on the install's own database, named or not.

If the browser refuses the cache (some private windows have no storage for it), Firestore starts without it and the page works as before, online only. The browser console says so once.

What works offline, and what does not

Works offlineNeeds a connection
  • Pages that already loaded their data keep showing it, and reading it again comes from the device.
  • Writes (add, set, update, delete) are queued and sent in order when the connection returns. The page shows the change at once.
  • Live listeners keep working on what is stored, and catch up on reconnect.
  • Cloud Functions callables, such as sign-in by phone or PIN, payments and search.
  • Transactions, and writes that must read the server first.
  • Signing in for the first time on a device, or as someone new. A person already signed in stays signed in.
  • Data never loaded on this device.
  • File uploads to Storage.

The cache holds data, not the app's code. A screen whose code was never loaded on the device cannot open offline. With the installable app on, the code of every screen opened before is kept; to have every screen outside the admin area stored when the app installs, set routeCode: 'app' (see Open screens offline and after a deploy).

Signed-in pages open from the cache

Before a signed-in page opens, its guard needs the person's users record. With the cache on, a later visit takes it from the device, so the page opens without waiting for the server, online or not. The server's copy follows in the background and keeps the record up to date. Only a first sign-in on the device, or one after the cache was wiped, waits for the server once. With the cache off, every visit waits for the server, as before.

The device's copy only lets a page open. Two answers wait for the server's word instead: no record (the person counts as signed out) and an inactive account (signed out and sent to /signup). Offline, the device's answer counts after 10 seconds. An account blocked since the last visit can therefore open a page from the cache until the server's copy arrives; the security rules refuse its reads and writes all the same. See What the guards wait for.

Shared devices

Reads from the cache are not checked by your security rules. The rules run on the server, and offline there is no server. Whatever one person loaded on a device can come back to the next person's queries on that device while offline. On a device several people use, either accept that (staff who share the same data anyway), or wipe the cache when the person changes.

To wipe it, call clearOfflineCache() from src/app/core/config/arc-firebase.ts with the app's Firestore. It first waits up to 5 seconds for changes made offline to be sent, and refuses with OfflineWritesPendingError if they cannot be, so nothing is lost by accident. It then stops Firestore, deletes the stored data and reloads the page.

import { inject } from '@angular/core';
import { Firestore } from '@angular/fire/firestore';
import { clearOfflineCache, OfflineWritesPendingError } from '../app/core/config/arc-firebase'; // from src/custom/

export class SwitchUserService {
    private firestore = inject(Firestore);

    async handOver(): Promise<void> {
        try {
            await clearOfflineCache(this.firestore);
        } catch (error) {
            if (error instanceof OfflineWritesPendingError) {
                // Ask the person to connect first, or, if the device is being retired:
                // await clearOfflineCache(this.firestore, { discardPendingWrites: true });
            }
        }
    }
}

Arc CMS does not wipe the cache by itself when someone signs out, because signing out offline would then lose their unsent changes. The choice belongs to the app.

Check it

  1. Set the value and run npm run arc:configure, then npm run dev.

  2. Sign in and open a page that lists data. In Chrome's DevTools, Network, choose Offline.

  3. Open the same page again: the data is still there. Change something: the page shows it.

  4. Go back online. The change reaches Firestore (check it in the Firebase console).