Skip to content

Conversation

@teboho
Copy link
Contributor

@teboho teboho commented Jan 20, 2026

#4439

Monaco Editor Local Bundling

Overview

This document describes the configuration changes made to bundle Monaco Editor locally instead of loading it from a CDN. This significantly improves load times for the code editor component.

Changes Made

1. Monaco Setup File (src/components/codeEditor/client-side/monacoSetup.ts)

Created a new setup file that:

  • Configures Monaco Editor to use locally bundled files
  • Sets up web workers for TypeScript, JavaScript, JSON, CSS, and HTML language support
  • Uses Next.js's built-in worker bundling via new URL() and import.meta.url

2. Code Editor Client Side (src/components/codeEditor/client-side/codeEditorClientSide.tsx)

Updated the file to:

  • Import Monaco from the new setup file instead of from CDN
  • Configure the @monaco-editor/react loader to use the local Monaco instance

Before:

loader.config({ paths: { vs: 'https://cdn.jsdelivr.net/npm/monaco-editor@0.50.0/min/vs' } });

After:

import monaco from './monacoSetup';
loader.config({ monaco });

3. Next.js Configuration (next.config.js)

Added webpack configuration to:

  • Handle TTF font files used by Monaco Editor
  • Support proper bundling of Monaco assets

Benefits

  1. Faster Load Times: Monaco files are bundled with the application and served from the same domain, eliminating CDN latency
  2. Better Caching: Monaco assets follow the same caching strategy as other application assets
  3. Offline Support: The editor works without internet connection once the app is loaded
  4. No CDN Dependencies: Removes reliance on external CDN availability
  5. Consistent Performance: Load times are predictable and not affected by CDN performance

Technical Details

Worker Configuration

Monaco Editor uses Web Workers for language services (TypeScript IntelliSense, syntax checking, etc.). The setup file configures these workers to be bundled using Next.js's built-in worker support:

new Worker(
  new URL('monaco-editor/esm/vs/language/typescript/ts.worker', import.meta.url),
  { type: 'module' }
)

Next.js automatically:

  1. Bundles the worker code
  2. Creates separate chunk files for each worker
  3. Handles the proper URL resolution at build time

Bundle Impact

Monaco Editor adds approximately 3-4MB to the bundle size when minified. However:

  • Workers are code-split into separate chunks
  • Only used workers are loaded
  • Compression (gzip/brotli) reduces the actual transfer size significantly
  • The improved load time from local serving offsets the larger bundle size

Performance Comparison

Before (CDN)

  • Initial load: Network request to cdn.jsdelivr.net
  • Latency: Variable (50-500ms depending on location)
  • Cache: CDN cache (may be stale or slow)
  • Total time: ~2-5 seconds for full editor load

After (Local Bundle)

  • Initial load: Bundled with application
  • Latency: Local server response
  • Cache: Application cache (consistent)
  • Total time: ~500ms-1.5 seconds for full editor load

Maintenance

Updating Monaco Editor

To update Monaco Editor version:

  1. Update the package version in package.json:

    npm install monaco-editor@latest @monaco-editor/react@latest
  2. No code changes required - the local bundling configuration will automatically use the new version

Troubleshooting

If the editor fails to load:

  1. Check browser console for worker loading errors
  2. Verify Monaco Editor is properly installed: npm list monaco-editor
  3. Clear Next.js cache: rm -rf .next
  4. Rebuild the application: npm run build-next

Development vs Production

The configuration works identically in both development and production modes. Next.js handles the worker bundling appropriately for each environment.

Rollback

To revert to CDN loading, change codeEditorClientSide.tsx:

// Remove this line:
import monaco from './monacoSetup';

// Change this:
loader.config({ monaco });

// Back to:
loader.config({ paths: { vs: 'https://cdn.jsdelivr.net/npm/monaco-editor@0.50.0/min/vs' } });

Related Files

  • /src/components/codeEditor/client-side/monacoSetup.ts - Monaco worker configuration
  • /src/components/codeEditor/client-side/codeEditorClientSide.tsx - Main editor component
  • /next.config.js - Webpack configuration for Monaco assets
  • /package.json - Monaco editor dependencies

References

Summary by CodeRabbit

  • Chores
    • Code Editor now loads its editor engine from locally bundled resources instead of an external CDN, improving reliability, offline availability, and consistent performance across deployments.

✏️ Tip: You can customize this high-level summary in your review settings.

@teboho teboho requested a review from IvanIlyichev January 20, 2026 13:39
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 20, 2026

Walkthrough

Replaces CDN-based Monaco initialization with a local bundled setup. Adds monacoSetup.ts to configure MonacoEnvironment.getWorker for various languages and exports the configured monaco instance. codeEditorClientSide.tsx now imports this setup and calls loader.config({ monaco }) instead of using the CDN.

Changes

Cohort / File(s) Summary
Monaco local setup
shesha-reactjs/src/components/codeEditor/client-side/monacoSetup.ts
New module that imports monaco-editor, assigns MonacoEnvironment.getWorker to return local ESM worker scripts (TS/JS, JSON, CSS, HTML, default) via import.meta.url, and exports the configured monaco instance.
Client-side editor integration
shesha-reactjs/src/components/codeEditor/client-side/codeEditorClientSide.tsx
Replaces CDN loader usage by importing the new monacoSetup and configuring the loader with loader.config({ monaco }), ensuring Monaco is sourced from the bundled package.

Sequence Diagram(s)

sequenceDiagram
  participant App as Client Component
  participant Loader as Monaco Loader (requirejs)
  participant Monaco as monacoSetup (monaco instance)
  participant Worker as Local Worker Script

  App->>Loader: import / initialize loader
  App->>Monaco: import monacoSetup
  Loader->>Monaco: loader.config({ monaco })
  App->>Monaco: create Editor instance
  Monaco->>Monaco: MonacoEnvironment.getWorker(kind, label)
  Monaco->>Worker: instantiate worker via import.meta.url -> local ESM worker
  Worker-->>Monaco: worker ready
  Monaco-->>App: editor ready
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I hopped from CDN to local ground,
Bundled workers spinning round and round.
TypeScript, JSON, HTML hum—
Local Monaco, work begun.
Small rabbit cheers for code well found! 🎉

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and accurately describes the main change: switching from CDN-based Monaco loading to local bundling for more predictable code editor loading behavior.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@shesha-reactjs/src/components/codeEditor/client-side/monacoSetup.ts`:
- Around line 11-53: Define a proper global type for MonacoEnvironment and
assign it to globalThis without using an any cast: add a TypeScript global
declaration that declares MonacoEnvironment with the correct getWorker signature
(e.g., getWorker(moduleId: string, label: string): Worker) so the file can set
globalThis.MonacoEnvironment = { getWorker(...) { ... } } directly; update
monacoSetup.ts to reference globalThis.MonacoEnvironment and remove the (self as
any) cast while keeping the existing worker-return logic in the getWorker
implementation.

…up.ts


Strict typing as suggested by code rabbit

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Copy link
Contributor

@IvanIlyichev IvanIlyichev left a comment

Choose a reason for hiding this comment

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

Hi @teboho. Local bundling requires reconfiguration of rollupjs build. Proposed changes can't be used as is because build of applicaitons that uses @shesha-io/reactjs fails with error ReferenceError: window is not defined. You can test it using shesha-functional-tests\adminportal

@teboho
Copy link
Contributor Author

teboho commented Jan 21, 2026

Hi @teboho. Local bundling requires reconfiguration of rollupjs build. Proposed changes can't be used as is because build of applicaitons that uses @shesha-io/reactjs fails with error ReferenceError: window is not defined. You can test it using shesha-functional-tests\adminportal

Hi @IvanIlyichev I will make changes.

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.

2 participants