Import Web SDK via CDN
Run the complete example first, then copy it into your page. It includes the dependencies, styles, language packs and Facade registrations needed for an editable spreadsheet with formulas.
Try an editable spreadsheet
- Open the example, or download the HTML below and save it as
index.html. - Open it in a modern browser with internet access. No build tool or server is needed. The interface and sample data use English.
- The Notebook total is 36. Change its quantity from 3 to 4: the total becomes 48. You can also edit cells and undo your changes.
Complete HTML example
This example uses React 18.3.1 UMD. Its global React object does not expose jsx and jsxs, which the Univer UMD bundles expect. The two-line bridge below supplies these entry points through the public React.createElement API. With package-manager integration, the build tool resolves react/jsx-runtime; do not copy this UMD bridge into that setup.
Resources load in dependency order from jsDelivr. If a request fails, the example retries the same version on unpkg before continuing. If both providers fail, it stops and shows the resource that could not load.
<!doctype html><html lang="en-US"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Univer Sheets CDN example</title> <style> html, body, #root, #app { padding: 0; margin: 0; height: 100%; } </style> </head> <body> <div id="app"><p role="status" style="padding: 24px; font-family: system-ui">Loading Univer…</p></div> <script> const cdnBases = ['https://cdn.jsdelivr.net/npm/', 'https://unpkg.com/'] const app = document.getElementById('app') async function loadResource(path, tag = 'script') { for (const base of cdnBases) { const element = document.createElement(tag) const url = base + path element.crossOrigin = 'anonymous' if (tag === 'link') { element.rel = 'stylesheet' element.href = url } else { element.src = url } try { await new Promise((resolve, reject) => { element.onload = () => resolve() element.onerror = () => reject(new Error(url)) document.head.appendChild(element) }) return } catch { element.remove() } } throw new Error(`Could not load ${path} from ${cdnBases.join(' or ')}`) } const styles = [ '@univerjs/design@1.4.0/lib/index.css', '@univerjs/ui@1.4.0/lib/index.css', '@univerjs/docs-ui@1.4.0/lib/index.css', '@univerjs/sheets-ui@1.4.0/lib/index.css', '@univerjs/sheets-formula-ui@1.4.0/lib/index.css', '@univerjs/sheets-numfmt-ui@1.4.0/lib/index.css', ] const reactScripts = [ 'react@18.3.1/umd/react.production.min.js', 'react-dom@18.3.1/umd/react-dom.production.min.js', ] const sdkScripts = [ 'rxjs@7.8.2/dist/bundles/rxjs.umd.min.js', '@wendellhu/redi@1.1.3/dist/umd/index.js', '@wendellhu/redi@1.1.3/dist/umd/react-bindings/index.js', '@univerjs/themes@1.4.0/lib/umd/index.js', '@univerjs/protocol@1.4.0/lib/umd/index.js', '@univerjs/core@1.4.0/lib/umd/index.js', '@univerjs/network@1.4.0/lib/umd/index.js', '@univerjs/rpc@1.4.0/lib/umd/index.js', '@univerjs/design@1.4.0/lib/umd/index.js', '@univerjs/engine-render@1.4.0/lib/umd/index.js', '@univerjs/engine-formula@1.4.0/lib/umd/index.js', '@univerjs/drawing@1.4.0/lib/umd/index.js', '@univerjs/telemetry@1.4.0/lib/umd/index.js', '@univerjs/ui@1.4.0/lib/umd/index.js', '@univerjs/docs@1.4.0/lib/umd/index.js', '@univerjs/docs-ui@1.4.0/lib/umd/index.js', '@univerjs/sheets@1.4.0/lib/umd/index.js', '@univerjs/sheets-ui@1.4.0/lib/umd/index.js', '@univerjs/sheets-formula@1.4.0/lib/umd/index.js', '@univerjs/sheets-formula-ui@1.4.0/lib/umd/index.js', '@univerjs/sheets-numfmt@1.4.0/lib/umd/index.js', '@univerjs/sheets-numfmt-ui@1.4.0/lib/umd/index.js', '@univerjs/core@1.4.0/lib/umd/facade.js', '@univerjs/engine-formula@1.4.0/lib/umd/facade.js', '@univerjs/ui@1.4.0/lib/umd/facade.js', '@univerjs/docs@1.4.0/lib/umd/facade.js', '@univerjs/docs-ui@1.4.0/lib/umd/facade.js', '@univerjs/sheets@1.4.0/lib/umd/facade.js', '@univerjs/sheets-ui@1.4.0/lib/umd/facade.js', '@univerjs/sheets-formula@1.4.0/lib/umd/facade.js', '@univerjs/sheets-numfmt@1.4.0/lib/umd/facade.js', '@univerjs/design@1.4.0/lib/umd/locale/en-US.js', '@univerjs/ui@1.4.0/lib/umd/locale/en-US.js', '@univerjs/sheets@1.4.0/lib/umd/locale/en-US.js', '@univerjs/sheets-ui@1.4.0/lib/umd/locale/en-US.js', '@univerjs/docs-ui@1.4.0/lib/umd/locale/en-US.js', '@univerjs/sheets-formula-ui@1.4.0/lib/umd/locale/en-US.js', '@univerjs/sheets-numfmt-ui@1.4.0/lib/umd/locale/en-US.js', ] // Fetch ahead in parallel; main() still executes scripts in dependency order. for (const [as, paths] of [ ['style', styles], ['script', [...reactScripts, ...sdkScripts]], ]) { for (const path of paths) { const preload = document.createElement('link') preload.rel = 'preload' preload.as = as preload.crossOrigin = 'anonymous' preload.href = cdnBases[0] + path preload.onerror = () => { preload.onerror = null preload.href = cdnBases[1] + path } document.head.appendChild(preload) } } async function main() { for (const path of styles) await loadResource(path, 'link') for (const path of reactScripts) await loadResource(path) // Bridge the React 18 UMD global to the JSX runtime expected by Univer UMD bundles. React.jsx = (type, props, key) => React.createElement(type, key === undefined ? props : { ...props, key }) React.jsxs = React.jsx for (const path of sdkScripts) await loadResource(path) app.textContent = '' const { Univer, LocaleType, mergeLocales, UniverInstanceType } = UniverCore const { FUniver } = UniverCoreFacade const { UniverRenderEnginePlugin } = UniverEngineRender const { UniverFormulaEnginePlugin } = UniverEngineFormula const { UniverUIPlugin } = UniverUi const { UniverSheetsPlugin } = UniverSheets const { UniverSheetsUIPlugin } = UniverSheetsUi const { UniverDocsPlugin } = UniverDocs const { UniverDocsUIPlugin } = UniverDocsUi const { UniverSheetsFormulaPlugin } = UniverSheetsFormula const { UniverSheetsFormulaUIPlugin } = UniverSheetsFormulaUi const { UniverSheetsNumfmtPlugin } = UniverSheetsNumfmt const { UniverSheetsNumfmtUIPlugin } = UniverSheetsNumfmtUi const univer = new Univer({ locale: LocaleType.EN_US, locales: { [LocaleType.EN_US]: mergeLocales( UniverDesignEnUS, UniverUiEnUS, UniverSheetsEnUS, UniverSheetsUiEnUS, UniverDocsUiEnUS, UniverSheetsFormulaUiEnUS, UniverSheetsNumfmtUiEnUS, ), }, }) univer.registerPlugin(UniverRenderEnginePlugin) univer.registerPlugin(UniverFormulaEnginePlugin) univer.registerPlugin(UniverUIPlugin, { container: 'app', }) univer.registerPlugin(UniverDocsPlugin) univer.registerPlugin(UniverDocsUIPlugin) univer.registerPlugin(UniverSheetsPlugin) univer.registerPlugin(UniverSheetsUIPlugin) univer.registerPlugin(UniverSheetsFormulaPlugin) univer.registerPlugin(UniverSheetsFormulaUIPlugin) univer.registerPlugin(UniverSheetsNumfmtPlugin) univer.registerPlugin(UniverSheetsNumfmtUIPlugin) univer.createUnit(UniverInstanceType.UNIVER_SHEET, {}) const univerAPI = FUniver.newAPI(univer) window.univerAPI = univerAPI univerAPI .getActiveWorkbook() .getActiveSheet() .getRange('A1:D3') .setValues([ ['Item', 'Quantity', 'Unit price', 'Total'], ['Notebook', 3, 12, '=B2*C2'], ['Pen', 5, 2, '=B3*C3'], ]) } main().catch((error) => { console.error(error) app.setAttribute('role', 'alert') app.style.cssText = 'padding: 24px; box-sizing: border-box; white-space: pre-wrap; overflow-wrap: anywhere; font: 14px/1.5 system-ui' app.textContent = 'The example could not load. Check your connection and refresh the page.' + '\n' + error.message }) </script> </body></html>Namespace conventions
UMD scripts expose module exports as global objects. Use these names when accessing plugins and Facade APIs in initialization code:
| Package or entry | Global name |
|---|---|
@univerjs/core | UniverCore |
@univerjs/docs-ui | UniverDocsUi |
@univerjs/core/facade | UniverCoreFacade |
@univerjs/docs-ui/locale/en-US | UniverDocsUiEnUS |
Keep versions aligned
This example pins all Univer packages to 1.4.0, React and ReactDOM to 18.3.1, and RxJS to 7.8.2. When upgrading, update every Univer URL together, including Facade, CSS and locale files. Avoid loading a second copy of these libraries alongside an existing application bundle.
Troubleshooting
| Symptom | What to check |
|---|---|
ITelemetryService | Load @univerjs/telemetry before @univerjs/sheets-ui, which depends on it. Keep the complete dependency list. |
FDocument | Load @univerjs/docs/facade before @univerjs/docs-ui/facade; Sheets also uses the Docs text engine. |
[redi], t is not a function | Start with the complete example and use one copy of each dependency at matching versions. Check failed requests in the browser Network panel. |
| Blank editor | Give the container an explicit height. If a CDN is blocked by your network or CSP, use locally hosted dependencies or package-manager integration. |
For an existing React or Vue application, prefer package-manager integration. It manages dependencies and avoids maintaining a long script list.
How is this guide?