
问题根源 app.getAppPath() 在 开发阶段 返回的是项目根目录(含 package.json), 而在 打包后 返回的是
YourApp.app/Contents/Resources/app.asar 所在目录; 直接拼 ../swagger-ui-dist 会随环境漂移,导致开发时指向「项目上一层」、生产时指向「asar 旁」——两边都 404。 正确做法是:「开发时」用 node_modules 原路径,「生产时」用 extraResources 目录,通过 app.isPackaged 一键切换。
一、目录规划(保持不变)
项目根
├─ node_modules/swagger-ui-dist ← dev 用
└─ dist/mac/xxx.app/Contents/
├─ Resources/app.asar
└─ Resources/swagger-ui-dist ← build 用(extraResources)
二、统一路径工具(
src/main/swagger-static.ts)
import path from 'path';
import { app } from 'electron';
export function swaggerAssets() {
if (app.isPackaged) {
// 生产:extraResources 放在 Resources 目录
const dir = path.join(app.getAppPath(), '..', 'swagger-ui-dist');
return {
dir,
css: `file://${path.join(dir, 'swagger-ui.css')}`,
bundle: `file://${path.join(dir, 'swagger-ui-bundle.js')}`
};
} else {
// 开发:直接用 node_modules
const dir = path.join(__dirname, '../../node_modules/swagger-ui-dist');
return {
dir,
css: `file://${path.join(dir, 'swagger-ui.css')}`,
bundle: `file://${path.join(dir, 'swagger-ui-bundle.js')}`
};
}
}
三、生成 HTML(复用上面的工具)
import { swaggerAssets } from './swagger-static';
const { css, bundle } = swaggerAssets();
const html = `
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<link rel="stylesheet" href="${css}"/>
</head>
<body>
<div id="swagger-ui"></div>
<script src="${bundle}"></script>
<script>
SwaggerUIBundle({ spec: ${JSON.stringify(swaggerJson)}, dom_id: '#swagger-ui' });
</script>
</body>
</html>`;
四、Windows 兼容(三段式 file:///)
function fileUrl(p: string) {
const url = path.resolve(p).replace(/\/g, '/');
return `file:///${url}`;
}
// 使用
css: fileUrl(path.join(dir, 'swagger-ui.css')),
bundle: fileUrl(path.join(dir, 'swagger-ui-bundle.js'))
五、验证步骤
- 开发时
“ npm run dev “
控制台网络面板应出现
“ file:///Users/you/project/node_modules/swagger-ui-dist/swagger-ui.css 200 “
- 打包后
“ npm run build:mac “
安装完打开 App,网络面板
“ file:///Applications/YourApp.app/Contents/Resources/swagger-ui-dist/swagger-ui.css 200 “
六、常见补充
|
现象 |
解决 |
|
dev 时 __dirname 指向 out/main |
用 path.join(__dirname, '../../node_modules/…') 向上两级即可 |
|
不想写 if/else |
用 app.isPackaged 是官方推荐,最简洁;也可把资源放 public 文件夹,让 Vite 复制到 out/ |
|
asar 内仍想引用 |
必须 |
30 秒复盘
- 用 app.isPackaged 区分「开发」/node_modules vs「生产」/Resources。
- 拼绝对路径后转 file://(Windows 加三个斜杠)。
- 开发时指向 node_modules,打包后指向 extraResources,两边 200 成功。
按上面改完,开发、生产路径自动对齐,swagger-ui.css / bundle.js 不再 404,页面即可正常渲染!
ERR_FILE_NOT_FOUND 说明 浏览器根本找不到这两个文件,90 % 是由于:
- 你把 swagger-ui-dist 打进了 asar 包,而 file:// 协议下 Chromium 禁止读取 asar 内的静态资源;
- 或者路径拼错 / 文件名大小写不一致。
下面给一套「asar 外 + 绝对路径」的 3 分钟修复方案,保证 file:// 能正常加载。
一、让 electron-builder 把资源放到 app 外(推荐)
- 安装依赖(只当普通资源,不打包)
npm i -D swagger-ui-dist
- electron-builder.yml 新增一条 extraResources
extraResources:
- from: node_modules/swagger-ui-dist
to: swagger-ui-dist
- 构建后会得到目录结构
dist/mac/YourApp.app/Contents/Resources/swagger-ui-dist/
├─ swagger-ui.css
├─ swagger-ui-bundle.js
└─ ...
Windows 在 resourcesswagger-ui-dist;Linux 同理。
二、在代码里生成绝对 file:// URL
import path from 'path';
import { app } from 'electron';
const SWAGGER_DIR = path.join(app.getAppPath(), '..', 'swagger-ui-dist'); // asar 外
const SWAGGER_CSS = `file://${path.join(SWAGGER_DIR, 'swagger-ui.css')}`;
const SWAGGER_BUNDLE = `file://${path.join(SWAGGER_DIR, 'swagger-ui-bundle.js')}`;
三、生成 HTML(用上面的绝对 URL)
const html = `
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<link rel="stylesheet" href="${SWAGGER_CSS}"/>
</head>
<body>
<div id="swagger-ui"></div>
<script src="${SWAGGER_BUNDLE}"></script>
<script>
SwaggerUIBundle({ spec: ${JSON.stringify(swaggerJson)}, dom_id: '#swagger-ui' });
</script>
</body>
</html>`;
四、Windows 兼容写法(三段式 file:///)
function fileUrl(p: string) {
const url = path.resolve(p).replace(/\/g, '/');
return `file:///${url}`;
}
const SWAGGER_CSS = fileUrl(path.join(SWAGGER_DIR, 'swagger-ui.css'));
const SWAGGER_BUNDLE = fileUrl(path.join(SWAGGER_DIR, 'swagger-ui-bundle.js'));
五、再跑一遍 → 网络面板应显示 200
file:///Users/.../YourApp.app/Contents/Resources/swagger-ui-dist/swagger-ui.css 200
file:///Users/.../YourApp.app/Contents/Resources/swagger-ui-dist/swagger-ui-bundle.js 200
控制台不再报 ERR_FILE_NOT_FOUND,document.querySelector('.swagger-ui') 也能正常拿到节点。
六、常见额外坑
|
现象 |
解决 |
|
路径对了仍 404 |
确认 大小写(Linux 严格) |
|
作为 extraResources 后 dev 模式找不到 |
dev 时手动把 swagger-ui-dist 拷到 out/ 或判断 app.isPackaged 走不同路径 |
|
想保持 asar 内加载 |
必须改用 自定义协议( |
30 秒复盘
- electron-builder.yml 里 extraResources 把 swagger-ui-dist 放到 app 外。
- 代码里用 file://${app.getAppPath()}/../swagger-ui-dist/xxx 拼绝对 URL。
- Windows 把反斜杠转 / 并加 file:///。
按上面改完,两个静态文件 200 成功,页面即能正常渲染,祝调试顺利!


