Electron+TypeScript应用因模块配置报错崩溃问题排查
问题根因
你遇到的Cannot use import statement outside a module类模块报错,本质是三个配置冲突:
- 单tsconfig配置无法同时适配Electron双进程:Electron主进程运行在Node.js环境,渲染进程默认是浏览器沙箱环境,两者支持的模块系统不一致,共用一套编译配置必然顾此失彼,要么主进程不认ESM语法,要么渲染进程不认CommonJS的require。
- 现有配置自相矛盾:你当前
tsconfig.json里开启了"noEmit": true,但build脚本是执行tsc输出编译产物到dist目录,这个配置会让tsc不生成任何js文件,直接导致启动时找不到对应执行文件。 - 模块声明不匹配:package.json里写了
"type": "module",强制Node.js把所有.js后缀文件当作ES Module处理,但如果tsconfig输出的是CommonJS格式(带require语法),Node运行时会直接抛语法错;如果输出ES Module格式,渲染进程里用普通<script>标签引入时没有声明module类型,浏览器同样会抛导入语法错误。
修复步骤
1. 拆分主进程、渲染进程的TS配置
删掉根目录原来的单tsconfig.json,新建两个配置文件分别对应两个进程,从根源上避免模块规范冲突:
- 主进程配置
tsconfig.main.json,专门编译主进程入口(通常是src/main.ts或src/main/index.ts):
{ "compilerOptions": { "target": "ES2020", "lib": ["ES2020"], "module": "CommonJS", "moduleResolution": "Node", "esModuleInterop": true, "strict": true, "skipLibCheck": true, "outDir": "./dist", "forceConsistentCasingInFileNames": true, "useUnknownInCatchVariables": false }, "include": ["src/main/**/*", "src/main.ts"] }
- 渲染进程配置
tsconfig.renderer.json,编译前端页面运行的代码,输出浏览器原生支持的ESM格式:
{ "compilerOptions": { "target": "ES2020", "lib": ["DOM", "DOM.Iterable", "ES2020"], "module": "ESNext", "moduleResolution": "Node", "esModuleInterop": true, "allowSyntheticDefaultImports": true, "strict": true, "skipLibCheck": true, "outDir": "./dist/renderer", "jsx": "react-jsx", "isolatedModules": true, "resolveJsonModule": true, "useUnknownInCatchVariables": false }, "include": ["src/renderer/**/*", "src/renderer.ts"] }
2. 调整package.json配置
直接删除package.json里的"type": "module"字段,Electron主进程用CommonJS规范兼容性最好,不用折腾ESM在Node下的路径后缀、默认导入等边角问题。
同时修改scripts脚本,分别编译两个进程的代码;另外卸载已经废弃的@types/electron依赖,Electron 18版本已经内置完整TS类型,旧类型包会和内置类型冲突报莫名错误:
{ "scripts": { "build:main": "tsc -p tsconfig.main.json", "build:renderer": "tsc -p tsconfig.renderer.json", "build": "npm run build:main && npm run build:renderer", "watch": "npm run build:main -- -w & npm run build:renderer -- -w", "lint": "eslint -c .eslintrc --ext .ts ./src", "start": "npm run build && electron --no-sandbox ./dist/main.js" } }
执行卸载依赖命令:
npm uninstall @types/electron
3. 修正渲染进程脚本引入方式
如果没有用打包工具处理渲染进程代码,HTML里引入渲染进程JS时必须加type="module"标识,否则浏览器会把ESM的import语法识别为非法语法:
<!-- 错误写法 --> <!-- <script src="./renderer/index.js"></script> --> <!-- 正确写法 --> <script type="module" src="./renderer/index.js"></script>
4. (可选省心方案)用打包工具处理渲染进程
如果不想手动适配浏览器ESM兼容、裸模块导入问题,可以直接给渲染进程接入Vite/Webpack做打包,把渲染进程代码打包成单文件IIFE格式,完全不用考虑模块兼容问题,主进程保持CommonJS编译即可,这也是目前Electron项目的通用实践。
避坑提醒
- 不要在渲染进程代码里直接引入Node原生模块或Electron主进程专属API,除非主动开启了高安全风险的nodeIntegration,跨进程通信统一走IPC。
- 如果后续再碰到require相关报错,先定位报错的JS文件运行环境:主进程里的require是合法语法,渲染进程里出现require要么是编译配置错误把ESM输出成了CommonJS,要么是脚本标签没加module类型声明。
内容的提问来源于stack exchange,提问作者rev
相关产品推荐
相关产品推荐

