【Electron】app.getAppPath() 在 开发阶段 返回的是项目根目录

【Electron】app.getAppPath() 在 开发阶段 返回的是项目根目录

问题根源 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'))

五、验证步骤

  1. 开发时

“ npm run dev “

控制台网络面板应出现

“ file:///Users/you/project/node_modules/swagger-ui-dist/swagger-ui.css 200 “

  1. 打包后

“ 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 内仍想引用

必须
protocol.registerFileProtocol('swagger', …) 映射成 swagger://swagger-ui.css,否则 Chromium 一律 404


30 秒复盘

  1. 用 app.isPackaged 区分「开发」/node_modules vs「生产」/Resources。
  2. 拼绝对路径后转 file://(Windows 加三个斜杠)。
  3. 开发时指向 node_modules,打包后指向 extraResources,两边 200 成功。

按上面改完,开发、生产路径自动对齐,swagger-ui.css / bundle.js 不再 404,页面即可正常渲染!


ERR_FILE_NOT_FOUND 说明 浏览器根本找不到这两个文件,90 % 是由于:

  1. 你把 swagger-ui-dist 打进了 asar 包,而 file:// 协议下 Chromium 禁止读取 asar 内的静态资源
  2. 或者路径拼错 / 文件名大小写不一致。

下面给一套「asar 外 + 绝对路径」的 3 分钟修复方案,保证 file:// 能正常加载。


一、让 electron-builder 把资源放到 app 外(推荐)

  1. 安装依赖(只当普通资源,不打包)
npm i -D swagger-ui-dist
  1. electron-builder.yml 新增一条 extraResources
extraResources:
  - from: node_modules/swagger-ui-dist
    to: swagger-ui-dist
  1. 构建后会得到目录结构
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 内加载

必须改用 自定义协议
protocol.registerFileProtocol)把 asar 映射成 https://swagger/xxx,否则 Chromium 一律拒绝


30 秒复盘

  1. electron-builder.yml 里 extraResources 把 swagger-ui-dist 放到 app 外。
  2. 代码里用 file://${app.getAppPath()}/../swagger-ui-dist/xxx 拼绝对 URL。
  3. Windows 把反斜杠转 / 并加 file:///。

按上面改完,两个静态文件 200 成功,页面即能正常渲染,祝调试顺利!

© 版权声明

相关文章

暂无评论

none
暂无评论...