UNPKG

@wordpress/sync

Version:
55 lines (40 loc) 3.17 kB
# Status of the sync experiment in Gutenberg The sync package is part of an ongoing research effort to lay the groundwork of Real-Time Collaboration in Gutenberg. Relevant docs: - https://make.wordpress.org/core/2023/07/13/real-time-collaboration-architecture/ - https://github.com/WordPress/gutenberg/issues/52593 - https://docs.yjs.dev/ ## Enable the experiment The experiment can be enabled in the "Guteberg > Experiments" page. When it is enabled (search for `gutenberg-sync-collaboration` in the codebase), the client receives two new pieces of data: - `window.__experimentalEnableSync`: boolean. Used by the `core-data` package to determine whether to bootstrap and use the sync provider offered by the `sync` package. - `window.__experimentalCollaborativeEditingSecret`: string. A secret used by the `sync` package to create a secure connection among peers. ## The data flow The current experiment updates `core-data` to leverage the YJS library for synchronization and merging changes. Each core-data entity record represents a YJS document and updates to the `--edit` record are broadcasted among peers. These are the specific checkpoints: 1. REGISTER. - See `getSyncProvider().register( ... )` in `registerSyncConfigs`. - Not all entity types are sync-enabled at the moment, look at those that declare a `syncConfig` and `syncObjectType` in `rootEntitiesConfig`. 2. BOOTSTRAP. - See `getSyncProvider().bootstrap( ... )` in `getEntityRecord`. - The `bootstrap` function fetches the entity and sets up the callback that will dispatch the relevant Redux action when document changes are broadcasted from other peers. 3. UPDATE. - See `getSyncProvider().update( ... )` in `editEntityRecord`. - Each change done by a peer to the `--edit` entity record (local changes, not persisted ones) is broadcasted to the others. - The data that is shared is the whole block list. This is the data flow when the peer A makes a local change: - Peer A makes a local change. - Peer A triggers a `getSyncProvider().update( ... )` request (see `editEntityRecord`). - All peers (including A) receive the broadcasted change and execute the callback (see `updateHandler` in `createSyncProvider.bootstrap`). - All peers (including A) trigger a `EDIT_ENTITY_RECORD` redux action. ## What works and what doesn't - Undo/redo does not work. - Changes can be persisted and the publish/update button should react accordingly for all peers. - Offline. - Changes are stored in the browser's local storage (indexedDB) for each user/peer. Users can navigate away from the document and they'll see the changes when they come back. - Offline changes can be deleted via visiting the browser's database in all peers, then reload the document. - Documents can get out of sync. For example: - Two peers open the same document. - One of them (A) leaves the document. Then, the remaining user (B) makes changes. - When A comes back to the document, the changes B made are not visible to A. - Entities - Not all entities are synced. For example, global styles are not. Look at the `base` entity config for an example (it declares `syncConfig` and `syncObjectType` properties).