dotCMS / dotCMS/core

[SDK] Improve tree shaking and runtime performance across React, client, UVE, types, and analytics

Open
#37,571 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

dotCMS : SDK javascript OKR : Application Performance Team : Scout
Dominant language
Java
Stars
970
Forks
486
Avg merge
3d 33m
Merged PRs (30d)
170

Description

Description

A consumer-performance audit found related packaging and runtime costs across the browser SDKs. This issue consolidates the work outside the dedicated Vue and Experiments issues.

React packaging and optional editor code

@dotcms/react preserves modules but does not publish sideEffects metadata. Isolated bundle probes showed that importing only useEditableDotCMSPage or DotCMSLayoutBody still retains unrelated modules, including the TinyMCE React wrapper, editable text, block-renderer code, and layout CSS.

Measured isolated imports:

  • useEditableDotCMSPage: approximately 10.4 KB gzip.
  • DotCMSLayoutBody: approximately 11.6 KB gzip.
  • Both unexpectedly retained TinyMCE integration.

DotCMSEditableText should lazy-load @tinymce/tinymce-react when UVE edit mode actually needs the editor. The package should publish accurate side-effect metadata, likely preserving CSS explicitly.

Per-contentlet React runtime work

Every rendered React contentlet currently:

  • Registers its own dotcms:analytics:ready window listener through useIsAnalyticsActive.
  • Runs getBoundingClientRect() in a layout effect and triggers another state update, including in production mode.
  • Resolves duplicate dev-mode state; containers do similar work.

Dev mode and analytics state should be resolved once at DotCMSPageProvider and shared through context, following the centralized design already used by the Vue and Angular SDKs. Content measurement should run only when edit/development behavior requires it.

Component maps and example guidance

Static component maps make every mapped component reachable from a client entry. The Next.js example currently demonstrates this eager pattern. Documentation and examples should use explicit dynamic imports and include a regression fixture proving that unused mapped components are not part of the initial route graph.

Client SDK composition

@dotcms/client is a flat approximately 100 KB ESM entry with one public factory. Constructing a client imports and instantiates page, navigation, content/query builders, and AI APIs even when a consumer uses only one area.

Add focused subpath entrypoints and/or lazy API construction so page fetching does not pull AI and content-query machinery. Treat sideEffects: false as packaging hygiene, not as the solution for a single fully reachable module.

UVE, types, analytics, and export maps
  • Add verified side-effect metadata to tree-shakeable packages such as UVE, types, and analytics.
  • Correct generated conditional exports so standard ESM import resolves to *.esm.js rather than a *.cjs.mjs bridge.
  • Give @dotcms/analytics a framework-neutral entrypoint; both current root and ./react exports resolve to React code.
  • Keep framework-specific analytics/Next.js router integration behind an explicit subpath.

Acceptance Criteria

SDK packaging and runtime
  • @dotcms/react, UVE, types, client, and analytics publish accurate side-effect metadata; CSS or true side effects are explicitly retained.
  • A minimal React hook/layout import does not include TinyMCE, editable text, block-editor renderers, or unrelated layout modules.
  • TinyMCE React integration is loaded only when editable text enters UVE edit mode.
  • React uses one analytics-ready listener and one dev-mode value per layout tree, not one per contentlet/container.
  • Production mode avoids per-contentlet synchronous layout measurements used only for editor placeholders.
  • @dotcms/client exposes a supported way to consume page/navigation/content/AI functionality independently or lazily.
  • Importing page-only client functionality does not retain AI search and unrelated query-builder code.
  • Standard ESM export conditions resolve directly to ESM artifacts; CommonJS remains available through require where supported.
  • @dotcms/analytics exposes a framework-neutral entrypoint and keeps React/Next-specific code behind an explicit subpath.
Example applications and documentation
  • Update all affected React-based examples—not only SDK source—to demonstrate the optimized consumption pattern: examples/nextjs, examples/nextjs-experiments, and examples/astro.
  • Replace eager content-type component maps in those examples with framework-appropriate explicit dynamic imports so unused mapped components are not part of the initial page bundle.
  • Defer optional UI and SDK features in the examples, including AI search dialogs/client code, until the feature is actually opened or needed.
  • Update the corresponding README/code snippets and repository guidance so consumers do not copy the previous eager mapping/import pattern.
  • Keep examples/vuejs changes scoped to #37569, while ensuring any shared documentation remains consistent across frameworks.
  • All changed examples build successfully against the locally produced SDK artifacts rather than silently validating the previously published latest packages.
  • Live rendering, client-side navigation, SSR/prerendering, UVE edit mode, inline editing, block-editor rendering, analytics, and component fallbacks continue to work in the affected examples.
Required validation
  • Capture a reproducible before/after bundle report for each affected example, recording initial-route raw, minified, and gzip JavaScript totals and the modules/chunks responsible for the difference.
  • Add a deterministic fixture that maps at least one identifiable unused component; its marker/module must be absent from the initial route's JavaScript and network requests.
  • For Next.js examples, inspect the production client-reference/build manifests and initial route chunks—not development-mode module loading—to prove unused mapped components and TinyMCE are excluded.
  • For the Astro React example, inspect the production client output and browser network requests to prove the same behavior.
  • Verify in a browser/E2E test that a dynamically mapped component is fetched and rendered when its matching content type appears, rather than merely disappearing from the initial bundle.
  • Verify live mode makes no TinyMCE integration or TinyMCE script request; entering UVE edit mode and rendering editable text must load the editor and preserve inline editing.
  • Render multiple contentlets in a runtime test and assert there is one analytics-ready listener per layout tree, not one per contentlet, and that production mode does not call the editor-only getBoundingClientRect() path.
  • Bundle a page-only @dotcms/client fixture and assert its metafile does not contain AI search or unrelated content-query builders.
  • Resolve/import the published package under standard ESM conditions and assert that it selects the ESM artifact rather than a CJS bridge.
  • Bundle a framework-neutral analytics fixture and assert it does not include React or Next.js.
  • CI includes per-export bundle-metafile assertions and explicit size budgets so these regressions fail automatically.
  • Existing SDK unit tests and production builds for the affected examples remain green.

Priority

High

Additional Context

Relevant paths include:

  • core-web/libs/sdk/react
  • core-web/libs/sdk/client
  • core-web/libs/sdk/uve
  • core-web/libs/sdk/types
  • core-web/libs/sdk/analytics
  • examples/nextjs
  • examples/nextjs-experiments
  • examples/astro

The client sideEffects flag alone will not materially reduce its bundle while every API remains reachable from createDotCMSClient; the package needs a structural split or lazy construction.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reviewing the affected entrypoints and package metadata under core-web/libs/sdk/react, client, uve, types, and analytics, then compare the example consumption patterns in examples/nextjs, examples/nextjs-experiments, and examples/astro. Use the required bundle reports, fixtures, production manifests, browser tests, and existing SDK tests to validate each acceptance criterion. Done means the affected packages and examples build successfully while unused code is excluded and runtime behavior remains intact.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, next.js, react
Domain
api, build-system, documentation, frontend, performance, testing
Issue type
Refactor
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.