Monaco Editor for React - use the monaco-editor in any React application without needing to use webpack (or rollup/parcel/etc) configuration files / plugins
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Utilities for configuring Monaco Editor loading behavior, CDN sources, and initialization options. The loader is re-exported from the @monaco-editor/loader package.
Monaco Editor loader providing configuration and initialization control.
/**
* Monaco Editor loader instance for configuration and initialization
*/
declare const loader: MonacoLoader;
interface MonacoLoader {
/** Initialize Monaco Editor and return promise */
init(): Promise<Monaco>;
/** Configure loader options */
config(options: LoaderConfig): void;
/** Get current Monaco instance if already loaded */
__getMonacoInstance(): Monaco | null;
}Basic Usage:
import { loader } from "@monaco-editor/react";
// Initialize Monaco manually
async function initializeMonaco() {
try {
const monaco = await loader.init();
console.log("Monaco loaded:", monaco);
return monaco;
} catch (error) {
console.error("Failed to load Monaco:", error);
}
}
// Check if Monaco is already loaded
function checkMonacoStatus() {
const monaco = loader.__getMonacoInstance();
return monaco ? "Monaco is loaded" : "Monaco not loaded yet";
}Configure Monaco Editor loading source, paths, and initialization options.
/**
* Configure Monaco Editor loader settings
* @param options - Loader configuration options
*/
declare function config(options: LoaderConfig): void;
interface LoaderConfig {
/** Monaco Editor file paths configuration */
paths?: {
/** Base path for Monaco Editor files */
vs?: string;
};
/** Internationalization configuration */
"vs/nls"?: {
/** Available language translations */
availableLanguages?: Record<string, string>;
};
/** Pre-loaded Monaco instance */
monaco?: Monaco;
}Configuration Examples:
import { loader } from "@monaco-editor/react";
// Use custom CDN
function setupCustomCDN() {
loader.config({
paths: {
vs: 'https://cdn.jsdelivr.net/npm/monaco-editor@0.45.0/min/vs'
}
});
}
// Use local files (for offline scenarios)
function setupLocalFiles() {
loader.config({
paths: {
vs: '/static/monaco-editor/min/vs'
}
});
}
// Configure internationalization
function setupInternationalization() {
loader.config({
"vs/nls": {
availableLanguages: {
"*": "de" // Use German language pack
}
}
});
}
// Use pre-loaded Monaco instance
function usePreloadedMonaco(monacoInstance) {
loader.config({
monaco: monacoInstance
});
}import React, { useState, useCallback } from "react";
import { loader } from "@monaco-editor/react";
import Editor from "@monaco-editor/react";
function LazyMonacoEditor() {
const [isConfigured, setIsConfigured] = useState(false);
const configureAndLoad = useCallback(async () => {
if (isConfigured) return;
// Configure before loading
loader.config({
paths: {
vs: 'https://cdn.jsdelivr.net/npm/monaco-editor@0.45.0/min/vs'
}
});
try {
const monaco = await loader.init();
// Post-load configuration
monaco.editor.defineTheme('customTheme', {
base: 'vs-dark',
inherit: true,
rules: [],
colors: {
'editor.background': '#2d2d2d',
}
});
setIsConfigured(true);
} catch (error) {
console.error('Monaco loading failed:', error);
}
}, [isConfigured]);
return (
<div>
{!isConfigured ? (
<div>
<button onClick={configureAndLoad}>Load Monaco Editor</button>
</div>
) : (
<Editor
height="400px"
language="javascript"
defaultValue="// Monaco loaded with custom config"
theme="customTheme"
/>
)}
</div>
);
}import { loader } from "@monaco-editor/react";
function configureMonacoForEnvironment() {
const isProduction = process.env.NODE_ENV === 'production';
const isDevelopment = process.env.NODE_ENV === 'development';
if (isProduction) {
// Use CDN in production
loader.config({
paths: {
vs: 'https://cdn.jsdelivr.net/npm/monaco-editor@0.45.0/min/vs'
}
});
} else if (isDevelopment) {
// Use local files in development for faster loading
loader.config({
paths: {
vs: '/node_modules/monaco-editor/min/vs'
}
});
}
// Configure based on user preferences
const userLanguage = navigator.language.split('-')[0];
if (userLanguage !== 'en') {
loader.config({
"vs/nls": {
availableLanguages: {
"*": userLanguage
}
}
});
}
}import { loader } from "@monaco-editor/react";
async function robustMonacoInitialization() {
const fallbackCDNs = [
'https://cdn.jsdelivr.net/npm/monaco-editor@0.45.0/min/vs',
'https://unpkg.com/monaco-editor@0.45.0/min/vs',
'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.45.0/min/vs'
];
for (let i = 0; i < fallbackCDNs.length; i++) {
try {
loader.config({
paths: { vs: fallbackCDNs[i] }
});
const monaco = await loader.init();
console.log(`Monaco loaded from CDN ${i + 1}`);
return monaco;
} catch (error) {
console.warn(`CDN ${i + 1} failed:`, error);
if (i === fallbackCDNs.length - 1) {
throw new Error('All Monaco CDN sources failed');
}
}
}
}import { loader } from "@monaco-editor/react";
// Preload Monaco on app initialization
export async function preloadMonaco() {
try {
loader.config({
paths: {
vs: 'https://cdn.jsdelivr.net/npm/monaco-editor@0.45.0/min/vs'
}
});
const monaco = await loader.init();
// Pre-configure frequently used features
monaco.languages.typescript.javascriptDefaults.setEagerModelSync(true);
monaco.languages.typescript.typescriptDefaults.setEagerModelSync(true);
return monaco;
} catch (error) {
console.error('Monaco preload failed:', error);
}
}
// Call during app initialization
// preloadMonaco();import React, { useState, useEffect } from "react";
import { loader } from "@monaco-editor/react";
function ConditionalMonacoLoader({ shouldLoad, children }) {
const [monacoReady, setMonacoReady] = useState(false);
const [loading, setLoading] = useState(false);
useEffect(() => {
if (!shouldLoad || monacoReady || loading) return;
setLoading(true);
loader.config({
paths: {
vs: 'https://cdn.jsdelivr.net/npm/monaco-editor@0.45.0/min/vs'
}
});
loader.init()
.then(() => {
setMonacoReady(true);
setLoading(false);
})
.catch((error) => {
console.error('Monaco loading failed:', error);
setLoading(false);
});
}, [shouldLoad, monacoReady, loading]);
if (!shouldLoad) {
return <div>Monaco not needed yet</div>;
}
if (loading) {
return <div>Loading Monaco Editor...</div>;
}
if (!monacoReady) {
return <div>Ready to load Monaco</div>;
}
return children;
}// webpack.config.js - Example for custom Monaco setup
const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin');
module.exports = {
plugins: [
new MonacoWebpackPlugin({
// Available languages
languages: ['javascript', 'typescript', 'css', 'html', 'json'],
// Available features
features: ['coreCommands', 'find', 'folding', 'bracketMatching']
})
]
};
// Then configure loader to use local build
import { loader } from "@monaco-editor/react";
loader.config({
paths: {
vs: '/static/vs' // Path to webpack output
}
});// next.config.js
module.exports = {
webpack: (config) => {
config.module.rules.push({
test: /\.worker\.js$/,
use: { loader: 'worker-loader' }
});
return config;
}
};
// Configure for Next.js
import { loader } from "@monaco-editor/react";
if (typeof window !== 'undefined') {
loader.config({
paths: {
vs: 'https://cdn.jsdelivr.net/npm/monaco-editor@0.45.0/min/vs'
}
});
}// vite.config.js
export default {
optimizeDeps: {
include: ['monaco-editor']
},
build: {
rollupOptions: {
external: ['monaco-editor']
}
}
};
// Configure for Vite
import { loader } from "@monaco-editor/react";
loader.config({
paths: {
vs: '/node_modules/monaco-editor/min/vs'
}
});