From 744755937a1d063e128d18680fe18bcea673fa77 Mon Sep 17 00:00:00 2001 From: David Souther Date: Mon, 8 Jul 2024 18:20:18 -0400 Subject: [PATCH 1/6] Better handle lazy loading monaco --- web/src/shell/Monaco.tsx | 40 ++++++++++++++++---------------- web/src/shell/editor.tsx | 49 ++++++++++++++++------------------------ 2 files changed, 38 insertions(+), 51 deletions(-) diff --git a/web/src/shell/Monaco.tsx b/web/src/shell/Monaco.tsx index a1b4e6d0f..bbacb9435 100644 --- a/web/src/shell/Monaco.tsx +++ b/web/src/shell/Monaco.tsx @@ -1,8 +1,5 @@ -import MonacoEditor, { useMonaco, type OnMount } from "@monaco-editor/react"; -import { - CompilationError, - Span, -} from "@nand2tetris/simulator/languages/base.js"; +import MonacoEditor, { type OnMount } from "@monaco-editor/react"; +import { CompilationError, Span } from "@nand2tetris/simulator/languages/base"; import * as monacoT from "monaco-editor/esm/vs/editor/editor.api"; import { useCallback, useContext, useEffect, useRef, useState } from "react"; import { AppContext } from "../App.context"; @@ -95,7 +92,7 @@ export const Monaco = ({ lineNumberTransform?: (n: number) => string; }) => { const { theme } = useContext(AppContext); - const monaco = useMonaco(); + const monaco = useRef(); const [height, setHeight] = useState(0); const editor = useRef(); @@ -133,7 +130,7 @@ export const Monaco = ({ newHighlight = highlight.current; } decorations.current = makeDecorations( - monaco, + monaco.current || null, editor.current, // I'm not sure why this makes things work, but it is load bearing. // Removing the empty span will cause the initial first-statement @@ -170,7 +167,8 @@ export const Monaco = ({ // Set options when mounting const onMount: OnMount = useCallback( - (ed) => { + (ed, mon) => { + monaco.current = mon; editor.current = ed; editor.current?.updateOptions({ fontFamily: `"JetBrains Mono", source-code-pro, Menlo, Monaco, @@ -227,19 +225,19 @@ export const Monaco = ({ // Add error markers on parse failure useEffect(() => { - if (editor.current === undefined) return; - if (monaco === null) return; + if (!editor.current) return; + if (!monaco.current) return; const model = editor.current.getModel(); if (model === null) return; if (error === undefined || error.span === undefined) { - monaco.editor.setModelMarkers(model, language, []); + monaco.current.editor.setModelMarkers(model, language, []); return; } const startPos = model.getPositionAt(error.span.start); const endPos = model.getPositionAt(error.span.end); - monaco.editor.setModelMarkers(model, language, [ + monaco.current.editor.setModelMarkers(model, language, [ { message: error.message, startColumn: startPos.column, @@ -257,14 +255,14 @@ export const Monaco = ({ }; return ( - <> - - + ); }; + +export default Monaco; diff --git a/web/src/shell/editor.tsx b/web/src/shell/editor.tsx index d91c81291..b179c68d2 100644 --- a/web/src/shell/editor.tsx +++ b/web/src/shell/editor.tsx @@ -1,6 +1,6 @@ import { Trans } from "@lingui/macro"; import { type Grammar } from "ohm-js"; -import { CSSProperties, useContext, useEffect, useState } from "react"; +import { CSSProperties, lazy, Suspense, useContext, useState } from "react"; import { AppContext } from "../App.context"; import { @@ -9,11 +9,8 @@ import { } from "@nand2tetris/simulator/languages/base.js"; import "./editor.scss"; -import type { Monaco as MonacoT } from "./Monaco"; -let Monaco: typeof MonacoT = ( - ..._params: Parameters -): JSX.Element => <>; +const Monaco = lazy(() => import("./Monaco")); export const ErrorPanel = ({ error }: { error?: CompilationError }) => { return error ? ( @@ -97,37 +94,29 @@ export const Editor = ({ lineNumberTransform?: (n: number) => string; }) => { const { monaco } = useContext(AppContext); - const [monacoLoaded, setMonacoLoaded] = useState(false); - useEffect(() => { - const loadMonaco = async () => { - if (monaco.canUse && monaco.wants && !monacoLoaded) { - Monaco = (await import("./Monaco")).Monaco; - setMonacoLoaded(true); - } - }; - loadMonaco(); - }, [monaco, monacoLoaded, setMonacoLoaded]); return (
- {monaco.canUse && monaco.wants && monacoLoaded ? ( - + {monaco.canUse && monaco.wants ? ( + + + ) : ( <>