Uncaught SyntaxError: I don't have an export named 'default'?

Hello,

I am new to npms and javascript. Such, I am having a lot of issues with it.

Currently, I’m trying to integrate CodeMirror 6 (including the merge addon and lang-markdown) into my NiceGUI (frontend python-based framework) application, following the node module integration example in the documentation link. However, the page fails to render, and I consistently get the following error in the browser’s developer console:

Uncaught SyntaxError: The requested module ‘/_nicegui/2.12.1/components/2bc0ddd3fb955118d45797c0bcfed968/codemirrorbundle.js’ does not provide an export named ‘default’ (at (index):56:16)

I’ve tried simplifying my code to a minimal example, but the error persists. I suspect there might be an issue with how webpack is bundling everything, especially my links that just won’t work.

Currently, I am on NICEGUI v2.0.0, python 3.12.7, node v22.13.1, and npm v11.0.0

This is how my directory looks like:
nicegui-codemirror-minimal/
├── dist/
│ └── codemirror-bundle.js
├── node_modules/
│ └── …
├── codemirror_editor.js
├── codemirror_editor.py
├── main.py
├── package.json
├── package-lock.json
└── webpack.config.js

this is my package.json:

{
  "scripts": {
    "build": "webpack --config webpack.config.js"
  },
  "dependencies": {
    "@codemirror/commands": "^6.4.0",
    "@codemirror/lang-markdown": "^6.2.4",
    "@codemirror/merge": "^6.0.1",
    "@codemirror/state": "^6.4.1",
    "@codemirror/view": "^6.25.4",
    "codemirror": "^6.0.1"
  },
  "devDependencies": {
    "@babel/core": "^7.24.5",
    "@babel/preset-env": "^7.24.5",
    "babel-loader": "^9.1.3",
    "webpack": "^5.91.0",
    "webpack-cli": "^5.1.4"
  }
}

this is my webpack.config.js:

const path = require("path");

module.exports = {
  entry: "./codemirror_editor.js",
  mode: "development",
  output: {
    path: path.resolve(__dirname, "dist"),
    filename: "codemirrorbundle.js",
    library: "CodeMirrorEditor",
    libraryTarget: "window",
    globalObject: 'this',
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader",
          options: {
            presets: ["@babel/preset-env"],
          },
        },
      },
    ],
  },
};

this is my codemirror_editor.js:

let mergeViewInstance;

export default async function createCodeMirrorEditor(element, props) {
  const initialValueA = props.value_a || "";
  const initialValueB = props.value_b || "";

  // Dynamically import CodeMirror modules
  const { MergeView } = await import("@codemirror/merge");
  const { EditorView } = await import("@codemirror/view");
  const { basicSetup } = await import("codemirror"); 
  const { EditorState } = await import("@codemirror/state");
  const { markdown } = await import("@codemirror/lang-markdown");
  const { keymap, defaultKeymap } = await import("@codemirror/view"); 
  const { defaultKeymap: commandsDefaultKeymap } = await import("@codemirror/commands"); 

  mergeViewInstance = new MergeView({
    a: {
      doc: initialValueA,
      extensions: [
        basicSetup, 
        markdown(), 
        EditorView.editable.of(true), 
        keymap.of(defaultKeymap), 
        EditorView.updateListener.of((update) => {
          if (update.docChanged) {
            sendUpdate('a', update.state.doc.toString());
          }
        }),
      ],
    },
    b: {
      doc: initialValueB,
      extensions: [
        basicSetup, 
        markdown(), 
        EditorView.editable.of(true), 
        keymap.of(defaultKeymap), 
        EditorView.updateListener.of((update) => {
          if (update.docChanged) {
            sendUpdate('b', update.state.doc.toString());
          }
        }),
      ],
    },
    parent: element,
    root: document,
  });

  function sendUpdate(side, value) {
    element.dispatchEvent(new CustomEvent('update-value', { detail: { side, value } }));
  }

  function setValue(side, value) {
    const editor = side === 'a' ? mergeViewInstance.a : mergeViewInstance.b;
    const transaction = editor.state.update({
      changes: { from: 0, to: editor.state.doc.length, insert: value }
    });
    editor.dispatch(transaction);
  }

  return {
    setValue: setValue,
    destroy: () => { mergeViewInstance.destroy(); }
  };
}

this is my codemirror_editor.py:

from nicegui import ui
from typing import Callable, Optional

class CodeMirrorEditor(ui.element, component='dist/codemirrorbundle.js', dependencies=['dist/codemirrorbundle.js']):

    def __init__(self,
                 value_a: str = "",
                 value_b: str = "",
                 on_change_a: Optional[Callable] = None,
                 on_change_b: Optional[Callable] = None
                 ) -> None:
        super().__init__()
        self._props['value_a'] = value_a
        self._props['value_b'] = value_b
        self.on_change_a = on_change_a
        self.on_change_b = on_change_b
        self.on('update-value', self.handle_change)

    def handle_change(self, event):
        side = event.args['side']
        value = event.args['value']
        if side == 'a':
            self._props['value_a'] = value
            if self.on_change_a:
                self.on_change_a(value)
        elif side == 'b':
            self._props['value_b'] = value
            if self.on_change_b:
                self.on_change_b(value)
        self.update()

    def set_value(self, side: str, value: str):
        if side not in ('a', 'b'):
            raise ValueError("side must be 'a' or 'b'")
        self.run_method('setValue', side, value)

    @property
    def value_a(self) -> str:
        return self._props['value_a']

    @value_a.setter
    def value_a(self, value: str) -> None:
        self._props['value_a'] = value
        self.set_value('a', value)
        self.update()

    @property
    def value_b(self) -> str:
        return self._props['value_b']

    @value_b.setter
    def value_b(self, value: str) -> None:
        self._props['value_b'] = value
        self.set_value('b', value)
        self.update()

this is my main.py:

from nicegui import ui
from codemirror_editor import CodeMirrorEditor

@ui.page('/')
async def page():
    editor = CodeMirrorEditor(value_a="# Initial A", value_b="Initial B")

ui.run()

Also, I’ve tried bundling with rollup instead, and the same issue persists.