Skip to content

feat: support React 19 in ESM build#271

Merged
kwinto merged 1 commit intomainfrom
feature/esm-react19-support
Apr 27, 2026
Merged

feat: support React 19 in ESM build#271
kwinto merged 1 commit intomainfrom
feature/esm-react19-support

Conversation

@kwinto
Copy link
Copy Markdown
Collaborator

@kwinto kwinto commented Apr 15, 2026

Summary

  • Update @cognigy/chat-components to 0.70.0 (externalizes react/jsx-runtime to prevent React 19 crashes)
  • Add react-dom/client, react/jsx-runtime, and react/jsx-dev-runtime to ESM build externals in webpack.es.js

Problem

The ESM build (webchat.esm.js) bundled React 18's jsx-runtime and react-dom/client inline. When React 19 consumers loaded the ESM bundle, it crashed because:

  1. The inlined jsx-runtime accesses React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner — removed in React 19
  2. The inlined react-dom/client wrapper reads createRoot from the external react-dom root export, but React 19 only exposes it on react-dom/client

Solution

Externalize all React subpath imports in the ESM build so consumers provide their own:

config.externals = {
    react: "react",
    "react-dom": "react-dom",
    "react-dom/client": "react-dom/client",         // NEW
    "react/jsx-runtime": "react/jsx-runtime",       // NEW
    "react/jsx-dev-runtime": "react/jsx-dev-runtime", // NEW
};

The UMD build (webchat.js) is unaffected — it continues to bundle everything inline for standalone usage.

Consumer impact

  • Standard bundlers (Vite, webpack, Rollup): no changes needed — subpath imports resolve automatically from existing react/react-dom dependencies
  • Module Federation: add react/jsx-runtime and react-dom/client to the shared config
  • Minimum React version: unchanged (React 18+)

Quick test

After building (npm run build:esm), save this file as dist/test.html and serve:

python3 -m http.server 8787 -d dist
# open http://localhost:8787/test.html
dist/test.html — single-file React 19 ESM test
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8" />
  <title>Webchat ESM + React 19 Test</title>
  <script type="importmap">
  {
    "imports": {
      "react": "https://esm.sh/react@19?dev",
      "react-dom": "https://esm.sh/react-dom@19?dev",
      "react-dom/client": "https://esm.sh/react-dom@19/client?dev",
      "react/jsx-runtime": "https://esm.sh/react@19/jsx-runtime?dev"
    }
  }
  </script>
</head>
<body>
  <h2>Webchat ESM + React 19 Test</h2>
  <p>Check the console. The webchat bubble should appear in the bottom-right corner.</p>
  <pre id="log" style="background:#f5f5f5;padding:12px;border-radius:4px;font-size:13px;"></pre>

  <script type="module">
    const log = (msg) => {
      document.getElementById('log').textContent += msg + '\n';
      console.log(msg);
    };

    try {
      const React = await import('react');
      log(`✅ React ${React.version} loaded`);

      const webchat = await import('./webchat.esm.js');
      log(`✅ Webchat ESM loaded — exports: ${Object.keys(webchat)}`);

      await webchat.initWebchat(
        'https://endpoint-trial.cognigy.ai/f9e76db1fd1cd4e048e30c5e3d1a26de68c843e0afb60c8b7ca498cd05e94e06'
      );
      log('✅ initWebchat resolved — widget should be visible');
    } catch (err) {
      log(`❌ ${err}`);
      console.error(err);
    }
  </script>
</body>
</html>

To test with React 18 instead, change all @19@18 in the import map.

Test plan

  • UMD build succeeds, works with React 18
  • ESM build succeeds, works with React 18
  • ESM build works with React 19 (no ReactCurrentOwner crash, no createRoot error)
  • webchat.esm.js has 0 references to __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED
  • webchat.esm.js imports react/jsx-runtime and react-dom/client as externals

Update @cognigy/chat-components to 0.70.0 which externalizes
react/jsx-runtime to prevent React 19 crashes (ReactCurrentOwner
removed in React 19).

Add react-dom/client, react/jsx-runtime, and react/jsx-dev-runtime
to the ESM build externals so consumers provide their own React
subpath modules. This enables React 19 consumers (e.g. Interaction
Panel MFE via Module Federation) to load the ESM bundle without
crashes from bundled React 18 internals.

UMD build (webchat.js) is unaffected — it continues to bundle
everything inline.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings April 15, 2026 11:10
@kwinto kwinto temporarily deployed to pr-preview-271 April 15, 2026 11:10 — with GitHub Actions Inactive
@graymalkin77
Copy link
Copy Markdown

graymalkin77 commented Apr 15, 2026

Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues
Licenses 0 0 0 0 0 issues
Code Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds React 19 compatibility for the ESM bundle (dist/webchat.esm.js) by ensuring React runtime subpath imports are not bundled, aligning the embed build output with how consumers provide React.

Changes:

  • Externalize react-dom/client, react/jsx-runtime, and react/jsx-dev-runtime in webpack.es.js (in addition to react / react-dom).
  • Bump @cognigy/chat-components to 0.70.0.
  • Update package-lock.json to reflect the dependency bump.

Reviewed changes

Copilot reviewed 2 out of 3 changed files in this pull request and generated 1 comment.

File Description
webpack.es.js Adds React subpath externals so the ESM build doesn’t inline React 18 runtime modules that break under React 19.
package.json Updates @cognigy/chat-components to a React-19-safe version and tidies devDependency ordering.
package-lock.json Locks @cognigy/chat-components@0.70.0 and its updated transitive dependency graph.

Comment thread package.json
@kwinto kwinto requested a review from sushmi21 April 23, 2026 07:35
@kwinto kwinto merged commit 8e60052 into main Apr 27, 2026
12 of 13 checks passed
github-actions Bot added a commit that referenced this pull request Apr 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants