Electron 中启用 ESM 需主进程设 "type": "module" 并用 .mjs 入口,渲染进程加 type="module",preload 脚本必须为 .mjs 扩展名,且不可混用 require 与 import。

Electron 中默认支持 ESModule(ESM),但需要正确配置 package.json 和启动方式,否则会报 ERR_REQUIRE_ESM 或 Cannot use import statement outside a module 错误。
确保主进程启用 ESM
Electron 主进程(main.js)默认运行在 CommonJS 环境下。若要用 ESM,需满足两个条件:
-
package.json 中设置
"type": "module"—— 这会让 Node.js 将所有.js文件按 ESM 解析(注意:此时require()不可用,必须用import) -
Electron 启动入口改为
.mjs扩展名(如main.mjs),或保留.js但配合"type": "module"(推荐前者,更明确且兼容性更好)
示例 package.json:
{
"name": "my-electron-app",
"type": "module",
"main": "main.mjs",
"scripts": {
"start": "electron ."
}
}
渲染进程加载 ESM 脚本
渲染进程(HTML 页面)中使用 ESM 更直接:
立即学习“Java免费学习笔记(深入)”;
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
- 在
<script>标签中添加type="module"属性即可启用 ESM 环境 - 支持顶层
await、动态import()、相对/绝对路径导入(注意:不支持 bare specifiers 如import { xxx } from 'lodash',除非用构建工具或插件处理)
示例 HTML:
<script type="module">
import { app } from './preload.mjs';
import { someUtil } from './utils/helper.js';
console.log(someUtil());
</script>
预加载脚本(preload)必须用 ESM 显式声明
Electron 的 preload 脚本默认是 CommonJS,若想用 ESM:
- 文件扩展名必须为
.mjs(如preload.mjs) - 不能依赖
"type": "module",因为 Electron 对 preload 的解析与主进程不同——它只看扩展名 - 在
webPreferences.preload中指定完整路径(推荐用path.join(__dirname, 'preload.mjs'))
示例主进程加载逻辑(main.mjs):
import { app, BrowserWindow } from 'electron';
import path from 'path';
function createWindow() {
const win = new BrowserWindow({
webPreferences: {
preload: path.join(__dirname, 'preload.mjs'),
contextIsolation: true,
nodeIntegration: false
}
});
win.loadFile('index.html');
}
app.whenReady().then(createWindow);
注意事项与常见坑
ESM 在 Electron 中不是“开箱即用”,尤其跨版本行为有差异(v20+ 更严格):
-
不能混用
require和import在同一文件中 —— ESM 是静态解析,CommonJS 是动态执行 - 第三方模块若只有 CommonJS 版本(如老版
sqlite3),需通过createRequire包装后使用 -
Node.js 内置模块(如
fs,path)在 ESM 中需显式导入:import fs from 'fs';(注意:需开启nodeIntegration: true或通过 preload 暴露) -
路径别名(如
@/components)不被原生 ESM 支持 —— 需借助打包器(Vite/Electron Forge)或自定义解析逻辑

















