Skip to content

Feature suggestion: withTabSync #291

@ketchel

Description

@ketchel

Initial discussion about this feature can be found here: #289.

Adding the withTabSync extension to a store would synchronize the state between browser tabs and windows. The suggested implementation is inspired by use-broadcast-ts

Behavior

  • When the state changes in one tab, it posts a message using BroadcastChannel. When a tab receives a message, it updates it's own state.
  • When a new tab opens, it populates the store normally and sends the data to other tabs. This helps keep tabs converged after initialization.
  • Conflict resolution: last message arrival wins (updates are applied in the order received).

Implementation

This feature could follow a similar pattern to withStorageSync.

File structure

src/lib/tab-sync/
  broadcast-channel.service.ts
  with-tab-sync.ts
  tests/

broadcast-channel.service.ts

Manages the BroadcastChannel, providing a wrapper for postMessage and closing the BroadcastChannel when the beforeunload event fires.

with-tab-sync.ts

Similar to with-storage-sync.ts but uses BroadcastChannelService instead of LocalStorageService. Provides the following config:

export type SyncConfig<State> = {
  /**
   * The name of the BroadcastChannel. Must be unique per origin.
   */
  name: string;
  /**
   * Flag indicating whether tabs should sync automatically.
   *
   * `true` by default
   */
  autoSync?: boolean;
  /**
   * Function to select that portion of the state which should be synced with other tabs
   *
   * Returns the whole state object by default
   */
  select?: (state: State) => unknown;
};

Constraints / Support

  • BroadcastChannel is same-origin only so it can only be used within a single app.
  • BroadcastChannel is not supported on old browsers https://caniuse.com/?search=broadcastchannel. If BroadcastChannel is not available, this extension is a no-op and logs a warning.
  • If executed in a non-browser environment (e.g. SSR), this extension is a no-op and logs a warning.

Possible Improvements

  • We could only send properties that are patched instead of the whole state. This would potentially improve performance and lessen the chances of conflicts.
  • Add an initSync config option that specifies whether a new tab's store should be populated normally and broadcast to other tabs ('push') or from other tabs ('pull')

If the maintainers agree with the approach and it's okay with them I'd like to take a crack and implementing it :)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions