# 项目结构

一个清晰规范的工程目录结构，不仅能让你在开发时事半功倍，更是构建、打包与部署顺利进行的前提。

根据插件功能的丰富程度，项目结构可以从极简的几行代码平滑演进到功能完备的前后端协同工程：
- **纯动作插件**：仅需根目录下的 `manifest.json` 与后台入口脚本；
- **超级块与带界面的插件**：推荐将 HTML、CSS、前端脚本与图片资源归拢在独立的页面目录中。

以官方的“多实例计数器”示例为例，标准的工程组织方式如下：

```text
counter/
├── manifest.json       # 核心清单：声明插件身份、能力与入口
├── package.json        # 依赖与模块声明
├── index.js            # 后台逻辑入口
└── pages/              # 页面与静态资源目录
    └── counter/
        ├── index.html  # 超级块主界面
        └── settings.html # 超级块自定义配置面板
```

---

## 1. 后台入口（main）

在 `manifest.json` 中，`main` 字段指定了后台逻辑在插件包内的相对路径（如 `"main": "index.js"`）。

- **工作目录与环境**：飞块在启动插件时，会自动把插件根目录设为工作目录（cwd），并由飞块内置的 Node.js 运行时拉起该入口。
- **模块规范**：推荐使用标准 CommonJS。在 `package.json` 中配置 `"type": "commonjs"`，在代码中直接使用 `require()`。
- **SDK 加载机制**：官方 SDK 的实际路径会在启动时由飞块通过环境变量 `process.env.FLYONDECK_SDK_PATH` 动态注入，你无需担心版本耦合。

---

## 2. 页面与前端静态资源

超级块的前端页面运行在隔离的沙箱中，资源引用规则十分直观：

- **主页面定位（`page`）**：清单中的 `page` 字段填写相对于插件根目录的主 HTML 路径（如 `"pages/counter/index.html"`）。
- **配置页面定位（`configPage`）**：请特别注意，**`configPage` 是相对于主页面所在目录解析的**。因此在上述目录中，只需填写 `"settings.html"`，而不是冗长的 `"pages/counter/settings.html"`。
- **相对路径引用**：在 HTML 内部引入同目录的 CSS、客户端 JS 或图片时，直接使用相对路径（如 `<link rel="stylesheet" href="./style.css">`）。
- **页面 SDK 引入**：飞块宿主会在请求时自动拦截并提供页面 SDK，你只需在 `<head>` 中引入固定路径即可。详细使用方式请参阅[创建超级块](./widgets.md)。

---

## 3. 插件数据存储规范

插件在运行期间可能会产生持久化配置、缓存或临时文件。飞块为每个插件都分配了专属的隔离目录：

- **持久化数据（`context.storage.dataDir`）**：存放需要长期保留的业务数据（如用户的自定义设置、待办事项、本地轻量数据库等）。
- **可再生缓存（`context.storage.cacheDir`）**：存放临时下载的封面图片、计算缓存等。操作系统或宿主可能适时清理该目录。

> ⚠️ **重要规范**：  
> 切勿将运行数据直接写回插件安装包目录内，也不要随意写入用户的系统主目录（`~`）。遵循宿主分配的存储路径，能确保插件在版本升级、覆盖安装时数据平滑迁移。详见 [storage 参考](../reference/storage.md)。

---

## 4. 使用 TypeScript 进行工程化开发

如果你偏好 TypeScript 的强类型检查与开发体验：

1. **源码与产物分离**：将源码放置于 `src/`（如 `src/index.ts`），并配置 `tsconfig.json` 输出至 `dist/`（如 `dist/index.js`）；
2. **清单指向编译产物**：在 `manifest.json` 中，务必将 `main` 填写为最终的 JavaScript 产物路径（如 `"main": "dist/index.js"`）；
3. **前端代码预构建**：页面脚本若使用了打包工具（如 Vite 或 esbuild），请同样确保先编译出静态文件。

> 💡 **构建时机**：飞块在安装或加载插件时只负责运行已有文件，不会执行你的编译构建命令。打包或调试前请确认已运行构建流程。

---

## 5. 依赖包与原生程序处理

- **关于 npm 依赖**：使用第三方 npm 包时，请将生产依赖（`dependencies`）一同打包进插件，或利用打包工具打入最终的 bundle。清单中的 `manifest.dependencies` 专指对**其他飞块插件**的依赖，不会替你拉取 npm 包。
- **关于原生二进制可执行文件（Native Tools）**：如果插件需要调用由 C/C++、Go 或 Rust 编译的独立二进制工具，可通过 [context.native.execute()](../reference/native.md) 调起。请务必在 `hostPlatforms` 中如实声明支持的操作系统，并在运行时根据操作系统分支加载对应的架构二进制。
