You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Webpack打包CodeMirror模块出现default导出不存在语法错误求助

模块导出错误排查与解决

问题

控制台报错:

Uncaught SyntaxError: The requested module './dist/codemirrorbundle.js' does not provide an export named 'default' (at (index):22:16)

环境

  • Python 3.12.7
  • Node v22.13.1
  • npm v11.0.0

项目目录结构

nicegui-codemirror-minimal/
├── dist/
│   └── codemirrorbundle.js
│   └── ...
├── node_modules/
│   └── ...
├── codemirror_editor.js
├── index.html
├── package.json
├── package-lock.json
└── webpack.config.js

相关代码文件

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"
  }
}

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: {
        name: 'CodeMirrorMerge',
        type: 'umd',
        export: 'default'
    },
    globalObject: 'this',
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader",
          options: {
            presets: ["@babel/preset-env"],
          },
        },
      },
    ],
  },
};

codemirror_editor.js

let mergeViewInstance;

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

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


  const createExtensions = (side) => [
    basicSetup,
    markdown(),
    EditorView.editable.of(true),
    keymap.of(commandsDefaultKeymap),
    updateListener.of((update) => {
      if (update.docChanged) {
        sendUpdate(side, update.state.doc.toString());
      }
    }),
  ];

  mergeViewInstance = new MergeView({
    a: {
      doc: initialValueA,
      extensions: createExtensions('a'),
    },
    b: {
      doc: initialValueB,
      extensions: createExtensions('b'),
    },
    parent: element,

  });

  function sendUpdate(side, value) {
    console.log(`Update: Side ${side}, Value: ${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(); }
  };
}

export default { createCodeMirrorEditor };

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>CodeMirror Merge Example</title>
    <style>
        .cm-editor {
            border: 1px solid #ddd;
            height: 300px; /* Or whatever height you want */
        }
        .cm-merge-view {
          display: flex;
          flex-direction: row;
        }
    </style>
</head>
<body>
    <div id="codemirror-container"></div>

    <script type="module">
        import CodeMirrorMerge from './dist/codemirrorbundle.js';

        document.addEventListener('DOMContentLoaded', () => {
            const container = document.getElementById('codemirror-container');
            if (!container) {
              console.error("Container element not found!");
              return;
            }

            CodeMirrorMerge.createCodeMirrorEditor(container, {
                value_a: "# Initial Value A",
                value_b: "Initial Value B",
            })
            .then(editor => {
                window.editor = editor; // For easy access in the browser console (good practice)
                console.log("CodeMirror MergeView initialized!");
            })
            .catch(error => {
                console.error("Error initializing CodeMirror:", error);
            });
        });
    </script>
</body>
</html>

解决方案

原因分析

Webpack配置中设置了library.export: 'default',但编译后的UMD模块在ES模块环境下的导出结构和预期不符,导致无法识别default导出。

修复方案(二选一即可)

方案1:修改Webpack配置,适配ES模块导出

调整output.library配置,添加umdNamedDefine: true,并确保导出结构正确:

output: {
  path: path.resolve(__dirname, "dist"),
  filename: "codemirrorbundle.js",
  library: {
      name: 'CodeMirrorMerge',
      type: 'umd',
      export: 'default'
  },
  globalObject: 'this',
  umdNamedDefine: true, // 新增这一行
},

然后重新执行npm run build。

方案2:修改HTML中的导入方式

如果不想改Webpack配置,直接调整模块导入语句,使用命名导入或者解构默认导出:

// 替换原来的import语句
import * as CodeMirrorMerge from './dist/codemirrorbundle.js';
// 或者
import { default as CodeMirrorMerge } from './dist/codemirrorbundle.js';

额外优化建议

  • 可以将codemirror_editor.js中的动态导入改为静态导入,减少运行时异步加载的复杂度:
import { MergeView } from "@codemirror/merge";
import { EditorView, keymap, updateListener } from "@codemirror/view";
import { basicSetup } from "codemirror";
import { EditorState } from "@codemirror/state";
import { markdown } from "@codemirror/lang-markdown";
import { defaultKeymap as commandsDefaultKeymap } from "@codemirror/commands";

这样Webpack可以更好地进行代码优化,也避免异步导入可能带来的时序问题。

内容的提问来源于stack exchange,提问作者ayejays

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 00:55:13