Generated by Spark: Optimize bundle size further by lazy-loading heavy components like Monaco Editor

This commit is contained in:
2026-01-17 09:44:43 +00:00
committed by GitHub
parent 4ab59a509f
commit 6fa92030d2
10 changed files with 450 additions and 30 deletions

View File

@@ -30,7 +30,7 @@ import {
Queue,
} from '@phosphor-icons/react'
import { toast } from 'sonner'
import Editor from '@monaco-editor/react'
import { LazyInlineMonacoEditor } from '@/components/molecules/LazyInlineMonacoEditor'
interface LambdaDesignerProps {
lambdas: Lambda[]
@@ -452,7 +452,7 @@ export function LambdaDesigner({ lambdas, onLambdasChange }: LambdaDesignerProps
</div>
<TabsContent value="code" className="flex-1 m-0">
<Editor
<LazyInlineMonacoEditor
height="100%"
language={getEditorLanguage(selectedLambda.language)}
value={selectedLambda.code}

View File

@@ -34,7 +34,7 @@ import {
Link,
} from '@phosphor-icons/react'
import { toast } from 'sonner'
import Editor from '@monaco-editor/react'
import { LazyInlineMonacoEditor } from '@/components/molecules/LazyInlineMonacoEditor'
interface WorkflowDesignerProps {
workflows: Workflow[]
@@ -688,7 +688,7 @@ export function WorkflowDesigner({ workflows, onWorkflowsChange }: WorkflowDesig
<div>
<Label>Lambda Code</Label>
<div className="border border-border rounded-md overflow-hidden mt-2">
<Editor
<LazyInlineMonacoEditor
height="300px"
defaultLanguage="javascript"
value={selectedNode.config?.lambdaCode || '// Write your lambda code here\n'}
@@ -750,7 +750,7 @@ export function WorkflowDesigner({ workflows, onWorkflowsChange }: WorkflowDesig
<div>
<Label>Transform Script</Label>
<div className="border border-border rounded-md overflow-hidden mt-2">
<Editor
<LazyInlineMonacoEditor
height="300px"
defaultLanguage="javascript"
value={

View File

@@ -0,0 +1,56 @@
import { Suspense, lazy } from 'react'
const MonacoEditor = lazy(() =>
import('@monaco-editor/react').then(module => ({
default: module.default
}))
)
interface LazyInlineMonacoEditorProps {
height?: string
defaultLanguage?: string
language?: string
value?: string
onChange?: (value: string | undefined) => void
theme?: string
options?: any
}
function InlineMonacoEditorFallback() {
return (
<div className="flex items-center justify-center bg-muted/50 rounded-md" style={{ height: '300px' }}>
<div className="flex flex-col items-center gap-2">
<div className="w-6 h-6 border-2 border-primary border-t-transparent rounded-full animate-spin" />
<p className="text-xs text-muted-foreground">Loading editor...</p>
</div>
</div>
)
}
export function LazyInlineMonacoEditor({
height = '300px',
defaultLanguage,
language,
value,
onChange,
theme = 'vs-dark',
options = {}
}: LazyInlineMonacoEditorProps) {
return (
<Suspense fallback={<InlineMonacoEditorFallback />}>
<MonacoEditor
height={height}
defaultLanguage={defaultLanguage}
language={language}
value={value}
onChange={onChange}
theme={theme}
options={{
minimap: { enabled: false },
fontSize: 12,
...options
}}
/>
</Suspense>
)
}

View File

@@ -0,0 +1,54 @@
import { Suspense, lazy } from 'react'
import { ProjectFile } from '@/types/project'
const MonacoEditor = lazy(() =>
import('@monaco-editor/react').then(module => ({
default: module.default
}))
)
interface LazyMonacoEditorProps {
file: ProjectFile
onChange: (content: string) => void
}
function MonacoEditorFallback() {
return (
<div className="h-full w-full flex items-center justify-center bg-card">
<div className="flex flex-col items-center gap-3">
<div className="w-8 h-8 border-2 border-primary border-t-transparent rounded-full animate-spin" />
<p className="text-sm text-muted-foreground">Loading editor...</p>
</div>
</div>
)
}
export function LazyMonacoEditor({ file, onChange }: LazyMonacoEditorProps) {
return (
<Suspense fallback={<MonacoEditorFallback />}>
<MonacoEditor
height="100%"
language={file.language}
value={file.content}
onChange={(value) => onChange(value || '')}
theme="vs-dark"
options={{
minimap: { enabled: false },
fontSize: 14,
fontFamily: 'JetBrains Mono, monospace',
fontLigatures: true,
lineNumbers: 'on',
scrollBeyondLastLine: false,
automaticLayout: true,
}}
/>
</Suspense>
)
}
export function preloadMonacoEditor() {
console.log('[MONACO] 🎯 Preloading Monaco Editor')
import('@monaco-editor/react')
.then(() => console.log('[MONACO] ✅ Monaco Editor preloaded'))
.catch(err => console.warn('[MONACO] ⚠️ Monaco Editor preload failed:', err))
}

View File

@@ -1,5 +1,5 @@
import Editor from '@monaco-editor/react'
import { ProjectFile } from '@/types/project'
import { LazyMonacoEditor } from './LazyMonacoEditor'
interface MonacoEditorPanelProps {
file: ProjectFile
@@ -7,22 +7,5 @@ interface MonacoEditorPanelProps {
}
export function MonacoEditorPanel({ file, onChange }: MonacoEditorPanelProps) {
return (
<Editor
height="100%"
language={file.language}
value={file.content}
onChange={(value) => onChange(value || '')}
theme="vs-dark"
options={{
minimap: { enabled: false },
fontSize: 14,
fontFamily: 'JetBrains Mono, monospace',
fontLigatures: true,
lineNumbers: 'on',
scrollBeyondLastLine: false,
automaticLayout: true,
}}
/>
)
return <LazyMonacoEditor file={file} onChange={onChange} />
}

View File

@@ -6,6 +6,8 @@ export { EmptyEditorState } from './EmptyEditorState'
export { EmptyState } from './EmptyState'
export { FileTabs } from './FileTabs'
export { LabelWithBadge } from './LabelWithBadge'
export { LazyInlineMonacoEditor } from './LazyInlineMonacoEditor'
export { LazyMonacoEditor, preloadMonacoEditor } from './LazyMonacoEditor'
export { LoadingFallback } from './LoadingFallback'
export { LoadingState } from './LoadingState'
export { MonacoEditorPanel } from './MonacoEditorPanel'

View File

@@ -1,5 +1,6 @@
import { lazy } from 'react'
import { lazyWithRetry, lazyWithPreload } from '@/lib/lazy-loader'
import { preloadMonacoEditor } from '@/components/molecules'
export const ComponentRegistry = {
ProjectDashboard: lazyWithPreload(
@@ -8,7 +9,10 @@ export const ComponentRegistry = {
),
CodeEditor: lazyWithPreload(
() => import('@/components/CodeEditor').then(m => ({ default: m.CodeEditor })),
() => {
preloadMonacoEditor()
return import('@/components/CodeEditor').then(m => ({ default: m.CodeEditor }))
},
'CodeEditor'
),
@@ -33,12 +37,18 @@ export const ComponentRegistry = {
),
WorkflowDesigner: lazyWithPreload(
() => import('@/components/WorkflowDesigner').then(m => ({ default: m.WorkflowDesigner })),
() => {
preloadMonacoEditor()
return import('@/components/WorkflowDesigner').then(m => ({ default: m.WorkflowDesigner }))
},
'WorkflowDesigner'
),
LambdaDesigner: lazyWithPreload(
() => import('@/components/LambdaDesigner').then(m => ({ default: m.LambdaDesigner })),
() => {
preloadMonacoEditor()
return import('@/components/LambdaDesigner').then(m => ({ default: m.LambdaDesigner }))
},
'LambdaDesigner'
),