Convert React applications into Lightning Web Components (LWC) for Salesforce deployment.
- React to LWC Conversion - Compile React apps into deployable LWC components
- Multi-LWC Code Splitting - Automatically splits large bundles across multiple LWC components to bypass Salesforce's 1MB file size limit
- UTF-8 Safe Encoding - Handles Unicode characters (i18n libraries) correctly with proper base64 encoding/decoding
- Shadow DOM Support - React renders inside Shadow DOM for proper LWC encapsulation
- CSS Compilation - Automatically bundles and injects CSS into the Shadow DOM
┌─────────────────────────────────────────────────────────────────┐
│ Salesforce Org │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Main LWC (heavyApp) │ │
│ │ - Imports chunk LWCs │ │
│ │ - Concatenates base64 chunks │ │
│ │ - Decodes UTF-8 and executes via new Function() │ │
│ │ - Renders React into Shadow DOM │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Chunk0 LWC │ │ Chunk1 LWC │ │ Chunk2 LWC │ ... │
│ │ (800KB max) │ │ (800KB max) │ │ (800KB max) │ │
│ │ base64 data │ │ base64 data │ │ base64 data │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ react LWC │ │ reactdom │ (Shared React/ReactDOM) │
│ │ │ │ LWC │ │
│ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────────────┘
Salesforce enforces a 1MB limit per JavaScript file in LWC components. Large React apps with many dependencies (MUI, Recharts, i18next, etc.) can easily exceed this limit.
Solution: The generator automatically:
- Compiles the React app with webpack
- Base64 encodes the bundle (UTF-8 safe)
- Splits the encoded string into ~800KB chunks
- Creates a separate LWC component for each chunk (
heavyAppChunk0,heavyAppChunk1, etc.) - The main LWC imports all chunks, concatenates them, decodes, and executes
// Generated main LWC imports chunks from separate components
import { chunk as chunk0 } from 'c/heavyAppChunk0';
import { chunk as chunk1 } from 'c/heavyAppChunk1';
import { chunk as chunk2 } from 'c/heavyAppChunk2';
// Concatenate and decode (UTF-8 safe)
const encodedCode = chunk0 + chunk1 + chunk2;
const binaryStr = atob(encodedCode);
const bytes = new Uint8Array(binaryStr.length);
for (let i = 0; i < binaryStr.length; i++) {
bytes[i] = binaryStr.charCodeAt(i);
}
const decodedCode = new TextDecoder('utf-8').decode(bytes);
// Execute
const scriptFunc = new Function('React', 'ReactDOM', decodedCode);
scriptFunc(React, ReactDOM);Libraries like i18next include Unicode characters (Persian numerals, CJK characters, etc.). The browser's atob() function only handles Latin1 characters correctly.
Solution: We use TextDecoder('utf-8') to properly decode the base64 bytes as UTF-8:
- Node.js:
Buffer.from(code).toString('base64')- handles UTF-8 - Browser:
atob()→Uint8Array→TextDecoder('utf-8')- decodes UTF-8
lwc-react-interop/
├── src/
│ ├── App.js # Main React entry point
│ └── components/ # React components
├── scripts/
│ ├── lwcWrapperGenerator.js # Core generator with chunking logic
│ ├── generate-single.js # CLI for single component generation
│ └── templates/ # LWC templates
├── dist/
│ └── lwc/
│ ├── heavyApp/ # Main wrapper LWC
│ ├── heavyAppChunk0/ # Chunk 0 LWC
│ ├── heavyAppChunk1/ # Chunk 1 LWC
│ ├── react/ # React library LWC
│ └── reactdom/ # ReactDOM library LWC
└── package.json
Start the local development server to preview your React app:
yarn startThis starts a webpack dev server at http://localhost:3000 with hot module replacement.
Generate a Lightning Web Component from your React app:
# Generate with custom component name
node scripts/generate-single.js --componentName heavyApp
# Or use the yarn script
yarn generate --componentName myApp# Deploy to default org
sf project deploy start --source-dir ./dist
# Deploy to specific org
sf project deploy start --source-dir ./dist --target-org myorg@example.com# 1. Generate the LWC
node scripts/generate-single.js --componentName heavyApp
# 2. Deploy to Salesforce
sf project deploy start --source-dir ./dist --target-org myorg
# Output shows chunk count:
# 📦 Splitting React bundle into 3 chunk(s) as separate LWC components
# 📦 Created chunk LWC: heavyAppChunk0
# 📦 Created chunk LWC: heavyAppChunk1
# 📦 Created chunk LWC: heavyAppChunk2
# ✅ Generated main wrapper and 3 chunk LWC component(s)The default chunk size is 800KB (to stay well under the 1MB limit). To modify:
// In scripts/lwcWrapperGenerator.js
const chunkSize = 800000; // bytesThe system handles large dependency bundles. Example tested dependencies:
@mui/material+@mui/icons-material(Material UI)recharts(Charts)i18next+react-i18next(Internationalization)lodash,moment,date-fns(Utilities)formik,react-hook-form,yup(Forms)framer-motion(Animations)@tanstack/react-table,@tanstack/react-query(Data)antd(Ant Design)chart.js(Charts)
- Salesforce Locker Service - Some browser APIs may be restricted
- 1MB per file - Handled automatically via chunking
- ~39MB total package size - MDAPI deployment limit
- Shadow DOM - React renders in Shadow DOM; some libraries may need adaptation
- Dynamic imports - Not supported; all code must be bundled upfront
If you see this error with new Function(), it's likely a UTF-8 encoding issue. Ensure the generator uses TextDecoder:
const binaryStr = atob(encodedCode);
const bytes = new Uint8Array(binaryStr.length);
for (let i = 0; i < binaryStr.length; i++) {
bytes[i] = binaryStr.charCodeAt(i);
}
const decodedCode = new TextDecoder('utf-8').decode(bytes);The bundle exceeds 1MB. The generator should automatically chunk, but verify:
- Each chunk file is under 1MB
- All chunk LWCs are being deployed
- Check
wc -c dist/lwc/*Chunk*/*.js
Check browser console for errors:
ReactAppComponent not found- Webpack didn't export correctlyContainer element not found- HTML template issue- React errors - Check component code
ISC