Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Truly dynamic imports with Turbopack, i.e. support for Monaco editor #72613

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
1 task done
leidegre opened this issue Nov 12, 2024 · 9 comments
Open
1 task done

Truly dynamic imports with Turbopack, i.e. support for Monaco editor #72613

leidegre opened this issue Nov 12, 2024 · 9 comments
Labels
Turbopack Related to Turbopack with Next.js.

Comments

@leidegre
Copy link

leidegre commented Nov 12, 2024

Verify canary release

  • I verified that the issue exists in the latest Next.js canary release

Provide environment information

Operating System:
  Platform: win32
  Arch: x64
  Version: Windows 11 Enterprise
  Available memory (MB): 65225
  Available CPU cores: 32
Binaries:
  Node: 20.11.1
  npm: 10.2.4
  Yarn: 1.22.19
  pnpm: N/A
Relevant Packages:
  next: 15.0.4-canary.6 // Latest available version is detected (15.0.4-canary.6).
  eslint-config-next: N/A
  react: 18.3.1
  react-dom: 18.3.1
  typescript: 5.4.5
Next.js Config:
  output: export

Which example does this report relate to?

No response

What browser are you using? (if relevant)

No response

How are you deploying your application? (if relevant)

No response

Describe the Bug

Trying to get the Monaco editor to work with Turbopack.

./node_modules/monaco-editor/esm/vs/editor/common/services/editorSimpleWorker.js:323:17
Module not found
  321 |             else {
  322 |                 const url = FileAccess.asBrowserUri(`${moduleId}.js`).toString(true);
> 323 |                 import(`${url}`).then(onModuleCallback).catch(reject);
      |                 ^^^^^^^^^^^^^^^^
  324 |             }
  325 |         });
  326 |     }

Expected Behavior

I don't know if it's trying to import an empty string or what it is doing but it is failing when I do a dynamic import for the monaco editor api module. Like so,

const useMonaco = () => {
  const [monaco, setMonaco] = useState<typeof import("monaco-editor/esm/vs/editor/editor.api")>()

  useEffect(() => {
    import("monaco-editor/esm/vs/editor/editor.api").then(setMonaco)
  }, [])

  return monaco
}

It's probably failing because it cannot resolve this statically but it's not supposed to either, I don't know how debug, troubleshoot or investigate this myself further. All I want Turbopack to do is to leave this dynamic import alone. Furthermore, this is a library so I cannot modify the call site. I just want Turbopack to not complain about this, I know what I'm doing.

To Reproduce

Adapt this sample from Monaco for Turbopack

https://github.com/microsoft/monaco-editor/tree/main/samples/browser-esm-webpack-small

@leidegre leidegre added the examples Issue was opened via the examples template. label Nov 12, 2024
@leidegre
Copy link
Author

leidegre commented Nov 12, 2024

I believe the examples label has been added by mistake. I don't think I can remove it.

@timneutkens timneutkens added Turbopack Related to Turbopack with Next.js. and removed examples Issue was opened via the examples template. labels Nov 12, 2024
@Chenalejandro
Copy link

If you are using pnpm, you can patch the monaco-editor.
For example, here is my integration of monaco-editor with next.js: https://github.com/Chenalejandro/next.js/tree/add-monaco-editor-example/examples/monaco-editor. To work around turbopack,

  1. run pnpm patch [email protected] (or adjust to the version you are using)
  2. open the directory returned by the previous command
  3. open the file esm/vs/base/common/worker/simpleWorker.js and add the following four lines:
         if (isESM) {
             const url = FileAccess.asBrowserUri(`${moduleId}.js`).toString(true);
+            if (process.env.NODE_ENV === "development") {
+                throw new Error(`No RequestHandler!`);
+                return;
+            }
             return import(`${url}`).then((module) => {
  1. open the file esm/vs/editor/common/services/editorSimpleWorker.js and add the following four lines:
             else {
                 const url = FileAccess.asBrowserUri(`${moduleId}.js`).toString(true);
+                if (process.env.NODE_ENV === "development") {
+                    reject();
+                    return;
+                }
                 import(`${url}`).then(onModuleCallback).catch(reject);
             }
  1. run pnpm patch-commit YOUR_MONACO_EDITOR_PATH, where YOUR_MONACO_EDITOR_PATH is the path returned by step 1

The only issue is that the editor will not have syntax highlighting when running next.js in dev mode.

The turbopack team said that they will be migrating the most popular webpack plugins to turbopack once they reach stable, so lets hope that monaco-editor-webpack-plugin will get the same treatment.

@leidegre
Copy link
Author

leidegre commented Nov 20, 2024

They don't have to add support for plugins, they just need to relax the rewriting rule for truly dynamic imports. It should not be failing for something that can be resolved at runtime (maybe emit a warning but not hard stop error), it's on me to provide the adequate workaround. It's just a matter of mapping entry points to chunks. That's all there's to this. I've done this before but here I find Turbopack missing a critical feature. It's just overly zealous about rewriting some imports.

@brycefranzen
Copy link

If you are using pnpm, you can patch the monaco-editor. For example, here is my integration of monaco-editor with next.js: https://github.com/Chenalejandro/next.js/tree/add-monaco-editor-example/examples/monaco-editor. To work around turbopack,

  1. run pnpm patch [email protected] (or adjust to the version you are using)
  2. open the directory returned by the previous command
  3. open the file esm/vs/base/common/worker/simpleWorker.js and add the following four lines:
         if (isESM) {
             const url = FileAccess.asBrowserUri(`${moduleId}.js`).toString(true);
+            if (process.env.NODE_ENV === "development") {
+                throw new Error(`No RequestHandler!`);
+                return;
+            }
             return import(`${url}`).then((module) => {
  1. open the file esm/vs/editor/common/services/editorSimpleWorker.js and add the following four lines:
             else {
                 const url = FileAccess.asBrowserUri(`${moduleId}.js`).toString(true);
+                if (process.env.NODE_ENV === "development") {
+                    reject();
+                    return;
+                }
                 import(`${url}`).then(onModuleCallback).catch(reject);
             }
  1. run pnpm patch-commit YOUR_MONACO_EDITOR_PATH, where YOUR_MONACO_EDITOR_PATH is the path returned by step 1

The only issue is that the editor will not have syntax highlighting when running next.js in dev mode.

The turbopack team said that they will be migrating the most popular webpack plugins to turbopack once they reach stable, so lets hope that monaco-editor-webpack-plugin will get the same treatment.

I opted to do this instead:
if(process.env.TURBOPACK) instead of if(process.env.NODE_ENV === 'development')

This way, when I want to work with monaco editor, I can run without --turbo.
But when not working with --turbo, things won't crash and burn.

@Kiryous
Copy link

Kiryous commented Mar 18, 2025

Hey! Having the same issue. Any updates or workarounds other than patching monaco-editor?

@hosein-mola

This comment has been minimized.

@timneutkens
Copy link
Member

Could you share a full reproduction repository?

I.e. @monaco-editor/react works with Turbopack:

"use client";

import Editor from "@monaco-editor/react";

export default function IDE() {
  const handleSubmit = async () => {};

  return (
    <div className="flex justify-center items-start pt-10 h-screen">
      <div className="w-full max-w-4xl p-4 border">
        <form action="#" onSubmit={handleSubmit}>
          <div className="">
            <label htmlFor="comment" className="sr-only">
              Add your code
            </label>
            <Editor
              height="50vh"
              defaultLanguage="javascript"
              defaultValue='Deno.serve(req => new Response("Hello!"));'
            />
          </div>
          <div className="flex justify-between pt-2">
            <div className="flex items-center space-x-5"></div>
            <div className="flex-shrink-0">
              <button
                type="submit"
                className="inline-flex items-center rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white hover:bg-indigo-500"
              >
                Run
              </button>
            </div>
          </div>
        </form>
      </div>
    </div>
  );
}

@GreenBabyBorn
Copy link

@timneutkens https://github.com/GreenBabyBorn/monaco-nextjs-turbopack

@leidegre
Copy link
Author

leidegre commented May 3, 2025

I don't know that it does. The problem really is with the way Next takes control over the rewriting of imports without leaving you with any option to bail. @monaco-editor/react is facilitated by @monaco-editor/loader which in turn has one or two things to say about getting going, see here.

All I want, is to be able to use Monaco directly without libraries and workarounds. For that to be possible I need to be able to tell Next to not touch the import that does the bootstrapping for Monaco. I'm perfectly happy with vendoring the libraries. In my particular situation, a CDN is also out of the question.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Turbopack Related to Turbopack with Next.js.
Projects
None yet
Development

No branches or pull requests

7 participants