Démarrage rapide
Tester la collaboration dans deux navigateurs, puis intégrer la composition minimale Client, Transport, Endpoint, Service et Adapter dans votre application.
Cette page propose deux parcours. Exécutez d’abord l’exemple officiel et vérifiez tout le circuit collaboratif dans deux navigateurs. Lisez ensuite la composition minimale Server et Web et copiez-la dans votre application Univer.
Avant de commencer, respectez les exigences d’environnement et de version. Tous les paquets @univerjs/* et @univerjs-pro/* doivent être verrouillés sur le même ensemble de versions compatibles.
Premier parcours : exécuter l’exemple officiel
Préparer le premier lancement
Le dépôt exige Node.js 24+ et déclare pnpm 10.32.1. Vérifiez node --version et pnpm --version, puis conservez le lockfile. Exécutez les commandes pnpm example:* à la racine du dépôt. Elles compilent le navigateur et le serveur, vérifient les types puis démarrent le serveur ; elles ne proposent pas de rechargement à chaud. Après une modification, arrêtez puis relancez la commande.
Si vous disposez d’une licence client, définissez UNIVER_LICENSE dans le shell avant la compilation. vite.config.ts l’intègre au bundle navigateur. La définir uniquement au démarrage du serveur déjà compilé ne la met pas à jour. Voir la configuration de licence.
git clone https://github.com/dream-num/univer-collaboration-examples.gitcd univer-collaboration-examplespnpm install --frozen-lockfilepnpm example:quick-startOuvrez :
http://127.0.0.1:3010/?unit=quick-start-sheetVérifier la collaboration en temps réel
- Ouvrez l’URL complète dans une fenêtre de navigateur.
- Ouvrez-la dans un autre profil ou une fenêtre privée.
- Modifiez une cellule dans l’une des feuilles.
- Vérifiez que la modification apparaît dans l’autre navigateur.
Utilisez deux contextes indépendants pour que le serveur crée deux Sessions en ligne. Observer une modification sur la même page ne suffit pas à vérifier le circuit Room, ACK et diffusion.
Ce que prouve la réussite
Univer Collaboration Client → Node Transport → UniverCollabEndpoint → UniverCollabService → MemoryDatabaseAdapterLa synchronisation entre navigateurs signifie qu’ils ont chargé une Unit par HTTP, ouvert des Sessions WebSocket avec un Session Ticket à usage unique et rejoint la même Room. Le Service a effectué l’OT, confirmé une nouvelle révision, l’a enregistrée via l’Adapter et l’Endpoint l’a diffusée aux autres membres.
Deuxième parcours : intégrer dans votre application
Le code suivant montre la composition minimale du Server et du Web. Le démarrage rapide officiel fournit la structure complète de l’application :
Si vous avez déjà une application Web Univer, conservez son Runtime, ses préréglages et son UI ; ajoutez seulement la configuration du client Collaboration et le serveur ci-dessous. Pour un projet vide, copiez index.html, vite.config.ts et les styles du répertoire comme structure de l’application.
Partir des fichiers exécutables
Copiez examples/quick-start en conservant package.json, index.html, vite.config.ts, web/styles.css, web/main.ts et server/main.ts. Lancez build et start depuis ce répertoire : Express lit dist/web relativement au répertoire courant. Conservez l’injection de licence Vite et une hauteur non nulle pour #app. Le code ci-dessous explique l’assemblage ; ces fichiers constituent le projet exécutable complet.
La page et /universer-api partagent la même origine. Avec un frontend séparé, relayez HTTP et WebSocket Upgrade ou modifiez ensemble les cinq URL du client. unit doit correspondre à l’ID créé par le serveur. Le paramètre URL ne crée pas de document. L’exemple lit unit et charge explicitement avec loadSheetAsync() ; dans votre application, définissez l’utilisateur courant avant de charger, comme décrit dans Intégration collaborative.
1. Installer un ensemble cohérent de paquets
Le serveur nécessite Transport, Endpoint, Service et un Database Adapter. Le navigateur nécessite le client Collaboration. Installez les paquets, puis fixez tous les paquets Univer à la même version exacte :
pnpm add \ @univerjs-pro/collaboration \ @univerjs-pro/collaboration-client \ @univerjs-pro/collaboration-client-ui \ @univerjs-pro/collaboration-database-memory \ @univerjs-pro/collaboration-endpoint \ @univerjs-pro/collaboration-service \ @univerjs-pro/collaboration-transport-node \ @univerjs-pro/license \ @univerjs/core \ @univerjs/preset-sheets-core \ @univerjs/presets \ @univerjs/protocol \ express react react-dom rxjsLe manifeste de l’exemple officiel exécutable fait référence pour la composition actuelle et les versions exactes.
2. Créer Service, Endpoint et Unit initiale
UniverCollabService est le cœur collaboratif faisant autorité. L’Endpoint traduit le protocole navigateur vers le Service, tandis que le Memory Adapter conserve temporairement instantanés, jeux de modifications et révisions :
import type { IWorkbookData } from "@univerjs/core";import { createServer } from "node:http";import express from "express";import { LocaleType } from "@univerjs/core";import { MemoryDatabaseAdapter } from "@univerjs-pro/collaboration-database-memory";import { UniverCollabEndpoint } from "@univerjs-pro/collaboration-endpoint";import { UniverCollabService } from "@univerjs-pro/collaboration-service";import { createNodeTransport } from "@univerjs-pro/collaboration-transport-node";import { ErrorCode, UniverType } from "@univerjs/protocol";const UNIT_ID = "quick-start-sheet";const unitData: IWorkbookData = { id: UNIT_ID, rev: 1, name: "Quick Start Sheet", appVersion: "", locale: LocaleType.EN_US, sheetOrder: ["sheet-1"], sheets: { "sheet-1": { id: "sheet-1", name: "Sheet 1", rowCount: 100, columnCount: 26, cellData: {}, }, }, styles: {}, resources: [],};const database = new MemoryDatabaseAdapter();const service = new UniverCollabService({ dbAdapter: database });const endpoint = new UniverCollabEndpoint(service);const transport = createNodeTransport();transport.use(async (context, next) => { context.userID = "demo-user"; await next();});transport.register(endpoint);await service.createUnitFromData( { type: UniverType.UNIVER_SHEET, data: unitData }, { userID: "demo-user" },);Le demo-user fixe illustre la transmission de l’identité de confiance depuis Transport vers Endpoint et Service. En production, validez votre cookie, jeton Bearer ou session dans transport.use() avant de définir un userID métier stable.
3. Monter les points d’entrée d’autorisation, HTTP et WebSocket
Le client Collaboration actuel interroge un protocole d’autorisation. Le démarrage rapide renvoie toujours allowed: true pour cette route et rattache le Transport au serveur HTTP de l’application :
const app = express();app.post("/universer-api/authz/-/object/-/batch_allowed", express.json(), (request, response) => { const body = request.body as { requests: Array<{ unitID: string; objectID: string; actions: unknown[] }>; }; response.json({ error: { code: ErrorCode.OK, message: "" }, objectActions: body.requests.map((item) => ({ unitID: item.unitID, objectID: item.objectID, actions: item.actions.map((action) => ({ action, allowed: true })), })), });});app.use(express.static("dist/web"));const server = createServer(app);transport.attach(server);server.listen(3010, "127.0.0.1");Tout autoriser est une simplification pédagogique, pas une frontière de sécurité. Une application réelle doit protéger lectures HTTP, JOIN temps réel, envoi des jeux de modifications et opérations du cycle de vie des Units. Consultez Identité et autorisation pour la couverture complète.
4. Enregistrer le client Collaboration dans le Runtime navigateur
Conservez Web SDK et les préréglages habituels, puis ajoutez les plugins collaboratifs et les URL de protocole :
import { LocaleType, LogLevel } from "@univerjs/core";import { UniverCollaborationPlugin } from "@univerjs-pro/collaboration";import { UniverCollaborationClientPlugin } from "@univerjs-pro/collaboration-client";import CollaborationClientEnUS from "@univerjs-pro/collaboration-client/locale/en-US";import { BrowserCollaborationSocketService, UniverCollaborationClientUIPlugin,} from "@univerjs-pro/collaboration-client-ui";import CollaborationClientUIEnUS from "@univerjs-pro/collaboration-client-ui/locale/en-US";import { UniverLicensePlugin } from "@univerjs-pro/license";import { UniverSheetsCorePreset } from "@univerjs/preset-sheets-core";import UniverPresetSheetsCoreEnUS from "@univerjs/preset-sheets-core/locales/en-US";import { createUniver, defaultTheme, mergeLocales } from "@univerjs/presets";import "@univerjs-pro/collaboration-client/facade";import "@univerjs/preset-sheets-core/lib/index.css";import "@univerjs-pro/collaboration-client-ui/lib/index.css";const httpProtocol = location.protocol === "https:" ? "https" : "http";const wsProtocol = location.protocol === "https:" ? "wss" : "ws";const baseURL = `${httpProtocol}://${location.host}/universer-api`;const unitId = new URLSearchParams(location.search).get("unit");if (!unitId) throw new Error("Open the URL printed by the server; it names the Sheet with ?unit=.");const { univerAPI } = createUniver({ locale: LocaleType.EN_US, locales: { [LocaleType.EN_US]: mergeLocales( UniverPresetSheetsCoreEnUS, CollaborationClientEnUS, CollaborationClientUIEnUS, ), }, theme: defaultTheme, logLevel: LogLevel.WARN, collaboration: true, presets: [UniverSheetsCorePreset({ container: "app" })], plugins: [ [UniverLicensePlugin, { license: import.meta.env.UNIVER_LICENSE || undefined }], UniverCollaborationPlugin, [ UniverCollaborationClientPlugin, { socketService: BrowserCollaborationSocketService, sendChangesetTimeout: 200, authzUrl: `${baseURL}/authz`, snapshotServerUrl: `${baseURL}/snapshot`, collabSubmitChangesetUrl: `${baseURL}/comb`, collabWebSocketUrl: `${wsProtocol}://${location.host}/universer-api/comb/connect`, wsSessionTicketUrl: `${baseURL}/user/session-ticket`, }, ], UniverCollaborationClientUIPlugin, ],});const workbook = await univerAPI.getCollaboration().loadSheetAsync(unitId);if (!workbook) throw new Error("Document could not be loaded");La page nécessite un élément id="app" et choisit l’Unit par paramètres de requête :
/?unit=quick-start-sheet5. Remplacer la configuration pédagogique
| Configuration pédagogique | Remplacement |
|---|---|
demo-user fixe | Middleware d’authentification et ID utilisateur stable |
| Contrôles autorisant toujours | ACL serveur couvrant lecture, JOIN, envoi et cycle de vie |
| Unit fixe | API de création et enregistrement produit appelant createUnitFromData() |
| Memory Adapter | SQLite ou Adapter persistant personnalisé validé par tests de contrat |
Complétez ensuite Adaptateurs de base de données et Identité et autorisation. Ajoutez History, Thread Comment, Worktree ou Exchange selon vos besoins. L’index des exemples présente toutes les compositions exécutables.
Dépanner le premier lancement
| Symptôme | Vérification |
|---|---|
| Échec d’installation ou de compilation | Node.js 24+, pnpm déclaré, versions Univer alignées |
| Port 3010 occupé | Arrêter l’exemple précédent ou utiliser PORT=3011 dans les deux URL |
| Page vide ou ressources absentes | Compilation terminée, démarrage depuis le répertoire de l’exemple, hauteur de #app |
| Modifications non synchronisées | Même URL complète, requêtes snapshot et session-ticket réussies, WebSocket /universer-api/comb/connect connecté |
| Données perdues au redémarrage | Quick Start utilise la mémoire ; passer à SQLite |
Que pensez-vous de ce guide ?