# app.json 配置
## 功能
`app.json` 是 `bt-app` 的桌面应用配置文件。它描述应用名称、窗口、入口、运行模式、图标、主脚本和打包资源。
`app.json` 是唯一配置来源。项目根目录不存在 `app.json` 但存在 `index.html` 时,`bt-app` 会自动写入默认 `app.json` 后再启动;`index.html` 中的 `
` 和自定义标签不会覆盖应用配置。
## 完整示例
```json
{
"app": {
"id": "org.example.diary",
"name": "Diary",
"title": "我的日记本",
"version": "1.0.0",
"description": "BT 桌面日记本示例",
"copyright": "Copyright 2026 BT",
"mode": "static",
"entry": "index.html",
"icon": "icon.ico",
"storage": "app",
"file_associations": [
{
"extensions": ["md", "markdown"],
"icon": "icons/markdown.ico",
"description": "Markdown 文档",
"context_menu": "以 Diary 打开"
}
],
"main": "main.bt"
},
"window": {
"width": 900,
"height": 700,
"resizable": true,
"fullscreen": false,
"hide_titlebar": false,
"transparent": false,
"always_on_top": false
},
"dev": {
"watch": true,
"delay": 500,
"devtools": true,
"console": true
},
"resources": [
"app.json",
"index.html",
"icon.ico",
"main.bt",
"assets/**"
],
"exclude": [
"assets/test/**",
"assets/*.bak"
]
}
```
## app 字段
| 字段 | 类型 | 必填 | 默认值 | 有效范围或可选值 | 说明 |
|---|---|---|---|---|---|
| `app.id` | string | 否 | 根据 `app.name` 生成 `org.btlang.` | 小写反向域名形式;至少两段;每段只能包含 ASCII 字母、数字、`_`、`-`,且首尾为字母或数字 | 跨版本保持稳定的应用标识。显式配置后用于 WebView profile、凭据和应用数据隔离,不应因显示名称或输出文件名变化而修改。 |
| `app.name` | string | 否 | `BTApp` | 单个文件名片段;不能包含路径或 Windows 文件名非法字符 | 应用内部名称,也是默认打包输出文件名。 |
| `app.title` | string | 否 | `BT 桌面应用` | 非空文本 | 窗口标题。用户看到的应用名称通常写在这里。 |
| `app.version` | string | 否 | `1.0.0` | 非空文本 | 应用版本,并写入 BTR 软件信息。 |
| `app.description` | string | 否 | 无 | 非空文本或省略 | 应用说明。Windows 打包时写入 exe 的 `FileDescription` 元信息。 |
| `app.copyright` | string | 否 | 无 | 非空文本或省略 | 版权说明。Windows 打包时写入 exe 的 `LegalCopyright` 元信息。 |
| `app.mode` | string | 否 | `static` | `static`、`server`、`remote` | 运行模式。 |
| `app.entry` | string | 否 | 按模式决定 | `static` 为项目内安全相对路径;`server`、`remote` 为 HTTP/HTTPS URL | 窗口入口。`static` 默认 `index.html`,`server` 默认 `http://127.0.0.1:18280`,`remote` 默认 `https://example.com`。 |
| `app.icon` | string | 否 | 内置图标 | 项目内安全相对 `.ico` 路径 | 用于运行窗口图标、BTR 工具条展示和 Windows 打包 exe 图标。 |
| `app.storage` | string | 否 | `app` | `app`、`private`、`global` | WebView 存储策略。`app` 按应用标识使用独立持久 profile;`private` 每次启动使用唯一临时 profile;`global` 使用旧版全局共享 profile。 |
| `app.file_associations` | object[] | 否 | `[]` | 见下表 | Windows 业务文件关联列表。只由打包后的 exe 应用注册;外部 BTR 不注册其中声明的关联。 |
| `app.main` | string/boolean/null | 否 | 自动尝试 `main.bt` | 安全相对 `.bt` 路径、`false`、空字符串、`true` 或 `null` | 前端 `bt.call()` 可调用的 BT 主脚本。字符串表示指定脚本;`false` 或空字符串表示不执行;其他默认形式自动查找 `main.bt`。 |
建议从项目创建时就显式写入 `app.id`。未写时仍按旧行为兼容:运行时根据当前 `app.name` 生成默认 ID,并继续沿用旧版按名称保存的数据位置;一旦显式设置稳定 ID,后续修改 `app.name` 或 `app.title` 不会更换应用 profile 与数据目录。
## app.file_associations 字段
每个关联对象可同时声明多个扩展名。打包应用启动后会把自身注册为这些扩展名的打开程序,并添加资源管理器右键菜单;文件路径会作为启动参数传入,可通过 `window.bt.app.args()` 读取。
| 字段 | 类型 | 必填 | 默认值 | 有效范围或可选值 | 含义 |
|---|---|---|---|---|---|
| `extensions` | string[] | 是 | 无 | 每项为 1 到 32 个 ASCII 字母或数字;可带前导 `.`,读取后会移除并转成小写;全配置内不能重复 | 需要关联的文件扩展名。 |
| `icon` | string | 否 | `app.icon` | 项目内相对路径,只支持 `.ico` 文件 | 文件类型专属图标。构建时嵌入 exe 的独立图标资源组,资源管理器中的关联文件使用该图标;右键菜单仍显示应用主图标。 |
| `description` | string | 否 | ` 文档` | 非空文本,不允许 NUL | Windows 中显示的文件类型说明。 |
| `context_menu` | string | 否 | `以 打开` | 非空文本,不允许 NUL | 文件资源管理器右键菜单文本。 |
```json
{
"app": {
"name": "M++",
"title": "M++",
"file_associations": [
{
"extensions": ["md"],
"icon": "markdown.ico",
"description": "Markdown 文档",
"context_menu": "以 M++ 打开"
}
]
}
}
```
`file_associations[].icon` 和 `app.icon` 作用不同:前者表示文件类型图标,后者表示 exe、窗口和任务栏中的应用图标。关联图标会直接嵌入单文件 exe,不需要额外写入 `resources`;省略时继续复用应用主图标,兼容旧配置。
Windows 关联写入 `HKEY_CURRENT_USER\\Software\\Classes`,不需要管理员权限,也不会修改其他用户。系统会尊重用户已经在 Windows 设置中明确选择的默认应用;这种情况下右键菜单和“打开方式”仍会出现,用户可在系统设置中把新应用设为默认。bt-app 不删除带签名保护的 `UserChoice`,也不会在每次启动时抢回用户后来选择的其他默认程序。
## window 字段
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
| `window.width` | number | 否 | `800` | 主窗口初始宽度,单位为逻辑像素。写 `0` 会回退到默认值。 |
| `window.height` | number | 否 | `500` | 主窗口初始高度,单位为逻辑像素。写 `0` 会回退到默认值。 |
| `window.resizable` | boolean | 否 | `true` | 是否允许用户调整窗口大小。 |
| `window.fullscreen` | boolean | 否 | `false` | 是否全屏启动。 |
| `window.hide_titlebar` | boolean | 否 | `false` | 是否隐藏系统标题栏。隐藏后需要页面自己提供拖动、关闭等交互;Windows 无标题栏窗口会关闭产生 1px 白边的系统阴影。 |
| `window.transparent` | boolean | 否 | `false` | 是否在创建时同时启用原生窗口和 WebView 透明背景。设为 `true` 时必须同时设置 `hide_titlebar: true`;修改后必须重启应用,热重载不会切换透明状态。 |
| `window.always_on_top` | boolean | 否 | `false` | 是否置顶窗口,适合悬浮工具、监控面板等场景。 |
主窗口启动时会先以无边框、无投影且隐藏的状态创建 WebView。非透明页面开始加载后会显示 bt-app 内置的无边框加载动画;首个页面完成加载后,bt-app 才应用 `hide_titlebar` 对应的最终边框和系统投影。透明窗口不会绘制矩形加载背景,而是保持隐藏到页面首帧完成。该时序由运行时统一处理,可避免 Windows 非客户区边线和 WebView 默认白底在页面首帧前闪现,项目页面不需要额外制作启动遮罩。
### 透明窗口
透明窗口适合悬浮工具、圆角面板、桌面挂件以及带 Alpha 通道的 PNG 界面。它不是运行期 API,而是窗口创建期配置:
```json
{
"window": {
"width": 320,
"height": 180,
"resizable": false,
"fullscreen": false,
"hide_titlebar": true,
"transparent": true,
"always_on_top": true
}
}
```
页面根节点必须保持透明,只让实际界面容器绘制背景和圆角:
```css
html,
body {
margin: 0;
width: 100%;
height: 100%;
background: transparent;
}
.app-shell {
width: 100%;
height: 100%;
border-radius: 24px;
background: rgba(24, 28, 42, 0.92);
}
```
`transparent: true` 会关闭矩形原生阴影,阴影需要由 HTML/CSS 绘制并在窗口尺寸内预留透明边距。PNG 和 HTML 元素可以使用半透明像素;完全透明的圆角区域仍属于原生矩形窗口的命中范围,不会自动点击穿透到下层应用。
## dev 字段
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
| `dev.watch` | boolean | 否 | `true` | 开发目录运行时是否监听资源变化并自动刷新页面。打包后的 Bundle 运行不生效。 |
| `dev.delay` | number | 否 | `500` | 文件变化后的防抖时间,单位为毫秒。连续保存多个文件只刷新一次。 |
| `dev.devtools` | boolean | 否 | `false` | 是否允许打开 WebView 开发者工具。开启后可按 `F12` 或 `Ctrl+Shift+I` 打开,也可调用 `window.bt.window.open_devtools()`。建议只在开发阶段开启;文件变化热重载不会自动弹出开发者工具。 |
| `dev.console` | boolean | 否 | `true` | 是否启用调试控制台。打包时为 `false` 会把 Windows exe 改为 GUI 子系统,双击时不弹控制台。 |
开发模式支持 `F5`、`Ctrl+R` 和 `Cmd+R` 刷新当前页面。`dev.watch=true` 时,`resources - exclude` 命中的文件保存、新增、删除或重命名后会自动刷新页面。`dev.watch=false` 时不会监听普通资源变化,但仍会监听 `app.json`,以便修改配置后自动恢复。`window.transparent` 同时影响原生窗口和 WebView,只能在窗口创建时应用;改变该字段后需要重启 `bt-app`。
开发目录运行时遇到 `app.json` 解析失败、入口文件缺失、`app.main` 缺失或脚本执行异常时,会在窗口内显示统一错误页并继续监听文件变化;修复后会自动重新加载。热重载错误状态会沿用上一次有效配置中的控制台设置,不会因为进入错误页而强制弹出控制台。
## resources 字段
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
| `resources` | string[] | 否 | `[]` | 打包时进入 Bundle 的资源规则,支持普通相对文件、glob 和 `assets/**` 这类递归目录规则。 |
| `exclude` | string[] | 否 | `[]` | 排除打包与开发监听的资源规则,优先级高于 `resources`。 |
构建时还会自动补齐必要资源:
- 当前目录存在 `app.json` 时自动加入 `app.json`。
- `static` 模式自动加入 `app.entry` 指向的入口文件。
- `app.main` 自动模式下如果存在 `main.bt`,自动加入 `main.bt`。
- 指定 `app.main` 字符串时自动加入该脚本。
- `app.main` 为 `false` 或空字符串时不需要主脚本;旧配置中 `resources` 残留的 `main.bt` 若文件不存在会被跳过。
- 当前目录存在 `server.bt` 时自动加入 `server.bt`。
- 配置了 `app.icon` 时自动加入图标文件。
最终资源集合按 `resources - exclude` 计算,该规则同时用于打包和开发模式文件监听。`dist/` 构建输出目录始终不会进入资源产物。`resources` 和 `exclude` 只能写项目内相对路径,不能写绝对路径,不能包含 `..`。普通文件不存在会打包失败;普通目录会递归收集目录内文件;`assets/**` 会递归收集目录内文件。
## 默认生成的 app.json
项目根目录没有 `app.json`,但存在 `index.html` 时,会生成以下默认配置:
```json
{
"app": {
"id": "org.btlang.bt_app",
"name": "BT-APP",
"title": "BT-APP",
"version": "1.0.0",
"description": "BT桌面软件",
"copyright": "Copyright 2026 BT",
"mode": "static",
"entry": "index.html",
"storage": "app",
"main": "main.bt"
},
"window": {
"width": 800,
"height": 500,
"resizable": true,
"fullscreen": false,
"hide_titlebar": false,
"transparent": false,
"always_on_top": false
},
"dev": {
"watch": true,
"delay": 500,
"devtools": true,
"console": true
},
"resources": [
"app.json",
"index.html",
"assets/**"
],
"exclude": []
}
```
默认配置中的 `app.main` 指向 `main.bt`。如果目录中还没有 `main.bt`,运行器会创建一个空文件,确保项目可以直接启动。默认资源会包含 `assets/**`,适配 Vue/Vite 常见构建产物。需要打包其他目录或文件时,请手动把它们写入 `resources`,bt-app 不再从 HTML 标签中自动扫描资源。
## mode运行模式
### static
该模式为静态HTML加载方式,需要配置`app.entry`为入口 HTML 文件路径,例如 index.html。
### server
该模式会执行当前目录的 `server.bt` 脚本,并启动Web服务,需要配置 `app.entry` 为该Web服务的完整URL,例如 `http://127.0.0.1:18280`。
提示:请确保 `server.bt` 脚本文件存在,并能正确启动 BT Web 服务。
### remote
该模式会直接打开远程URL,需要配置 `app.entry` 为远程URL,例如 `https://example.com`。
### 运行机制
以上三种运行模式都会自动执行当前目录的 `app.main` 脚本,并注入 `window.bt` 对象,用于与BT脚本进行交互。
- 如果 `app.main` 配置为 `false`,则不会执行该脚本。
- 如果 `app.main` 配置不存在,则自动查找当前目录的 `main.bt` 脚本并执行。
## 注意事项
- `app.name` 和 `app.title` 不同:`name` 为打包输出的文件名,`title` 为程序窗口的标题。
- `app.icon` 只接受 `.ico` 格式的图标文件。
- `app.file_associations[].icon` 同样只接受项目内 `.ico` 文件;文件不存在时构建会失败。
- `app.file_associations` 只在 Windows 打包应用启动时注册;仅执行 `bt-app.exe build` 不会修改开发机的文件关联。
- `window.transparent=true` 必须配合 `window.hide_titlebar=true`,并由页面把 `html`、`body` 背景设为 `transparent`。
- `index.html` 只作为页面入口,不承担配置职责。