调试插件:日志、断点与常见报错
插件不像网页那样「刷新一下就重载」,它有自己的进程模型和调试入口。搞清调试路径,能省掉大量盲猜时间。
三种插件,三种调试方式
窗口插件:F12
最直接的一种。打开插件窗口,按 F12 打开 DevTools,Console、断点、Network、Sources 全部可用。
- 打开要调试的插件窗口。
- 按
F12调出 DevTools。 - 在 Sources 面板点行号打断点,在 Console 里执行表达式。
如果 F12 被系统或别的软件截获,用开发者菜单入口:插件面板 → 开发者选项。
缩略图插件:devTools 加 debugger
缩略图脚本跑在后台,只在文件被添加或更新时执行,窗口按不出来。官方给的方案是在 manifest.json 里把 devTools 设为 true,然后在代码里写 debugger 语句:
// thumbnail/icns.js
module.exports = async ({ src, dest, item }) => {
debugger; // 执行到这里会挂起,打开 DevTools 后继续
const fs = require('fs');
// ...
return item;
};
然后添加/更新一个该格式的文件触发脚本执行,进 DevTools 就能停在断点上。
预览插件:先选中文件
预览插件要先有一个真实文件才能打开:
- 把正在开发的格式文件添加进 Eagle。
- 在列表里选中它。
- 打开插件面板,点击你的预览插件。
- 弹出预览窗口后按
F12。
检查器插件:右键开发者工具
检查器插件嵌在右侧面板里,没有独立窗口。调试方式是:在检查器插件区域点右键,选「开发者工具」。
日志系统:把痕迹写进 Eagle
DevTools 只在你本机开着时有效。用户报障时他不会给你开 F12,所以正式插件必须用 eagle.log 写日志——内容会进 Eagle 的软件日志文件,用户可以把那份日志发给你。
eagle.log.debug('debug message from plugin');
eagle.log.info('info message from plugin');
eagle.log.warn('warn message from plugin');
eagle.log.error('error message from plugin');
// 输出形如:
// [13:19:39.845] [debug] [plugin] "debug message from plugin"
四个方法的参数可以是对象、字符串、数组各种格式。最实用的组合是 try/catch 里同时记消息和堆栈:
try {
const items = await eagle.item.getSelected();
eagle.log.info(`选中数量: ${items.length}`);
if (items.length === 0) {
eagle.log.warn('用户没有选中任何素材');
}
}
catch (err) {
eagle.log.error('读取选中素材失败');
eagle.log.error(err.stack || err);
}
err.stack || err 这个写法值得记住:不是所有错误对象都有 stack,|| 兜住这种情况。
用 Node 调试器附加上非界面代码
后台服务和格式扩展插件没有可按 F12 的窗口,但它们的逻辑跑在 Node 进程里,可以直接用 Node 的内置调试器挂上去。以缩略图脚本为例:
- 确认
manifest.json里devTools为true。 - 在脚本入口写
debugger;语句。 - 触发条件(添加或更新该格式的文件)。
- 打开 DevTools,脚本会挂起在
debugger那一行,之后正常单步。
这套流程的局限是必须先触发一次才能挂上。想反复调试,就在脚本开头无条件加 debugger,调试完记得删掉。
格式化扩展(preview)的 viewer 页面虽然是 HTML,但它拿不到 Eagle Plugin API,官方文档明确写了这一点。所以 viewer 里能做的只有「拿 URL 参数、渲染自己的解析结果」这类事。官方示例里 viewer 从 query string 取参数,值得注意哪些参数可用:
// viewer/icns.html 内
const urlParams = new URLSearchParams(window.location.search);
const id = urlParams.get('id');
const filePath = urlParams.get('path');
const width = urlParams.get('width');
const height = urlParams.get('height');
const theme = urlParams.get('theme');
const lang = urlParams.get('lang');
其中 theme 和 lang 很实用:Eagle 主题变了、深色模式下你的预览还是白底,观感会很突兀。
给错误加上上下文
报错信息本身往往不够用——「Cannot read properties of undefined」这句话不带任何业务信息。写日志时把上下文拼进去,用户报障时你能直接定位到是哪一步:
eagle.onPluginCreate(async (plugin) => {
eagle.log.info(`插件启动: ${plugin.manifest.name} v${plugin.manifest.version}`);
try {
const items = await eagle.item.getSelected();
eagle.log.info(`读取选中素材成功,共 ${items.length} 个`);
for (const item of items) {
eagle.log.debug(`处理中 id=${item.id} name=${item.name}`);
}
}
catch (err) {
eagle.log.error(`读取选中素材失败,Build=${eagle.app.build}`);
eagle.log.error(err.stack || err);
}
});
这段日志里同时记了业务上下文(哪个插件、多少条)和环境信息(Build 号)。用户把日志发过来时,你不用再追问「你是什么版本」。
排查清单:按症状定位
遇到报错时,先判断属于哪一类:
| 症状 | 大概率原因 | 处理 |
|---|---|---|
| 窗口没弹出,插件面板里点了没反应 | manifest.json 有语法错误,或 main.url 路径不对 |
检查 JSON 是否能被 JSON.parse 成功 |
窗口空白,Console 报 require is not defined |
在 index.html 里直接引了 npm 包 |
改成在 .js 文件里 require |
eagle is not defined |
脚本在 Eagle 上下文外执行了 | 确认代码只在 onPluginCreate 回调或页面 script 内运行 |
API 调用返回 undefined |
客户端版本低于该 API 的最低要求 | 用 eagle.app.build 打印 Build 号对照文档 |
| 数据改了但界面上没变 | 忘记 await item.save(),或改了属性没触发重渲染 |
补 await,手动更新 DOM |
| 发布后功能失效,但本地正常 | 依赖了本机绝对路径或开发环境变量 | 改用 path.join(plugin.path, ...) 之类相对定位 |
| 背景插件在切换资源库后报错 | 缓存了旧的资源库路径 | 注册 eagle.onLibraryChanged 重新解析 |
排查的第一原则是:先把 manifest.json 单独 JSON.parse 一遍。语法错误是频率最高、也最容易被忽略的一类问题。
打印版本和环境
遇到「在我这正常」的问题,先打印环境:
eagle.onPluginCreate(async (plugin) => {
eagle.log.info('版本: ' + eagle.app.version);
eagle.log.info('Build: ' + eagle.app.build);
eagle.log.info('平台: ' + eagle.app.platform + ' / ' + eagle.app.arch);
eagle.log.info('语系: ' + eagle.app.locale);
eagle.log.info('主题: ' + eagle.app.theme);
console.log('插件路径:', plugin.path);
});
eagle.app.build 是判断版本要求的关键字段——文档里凡是标注「Eagle 4.0 build18+」的能力,都靠它对照。
常见坑
预览、缩略图插件里用
eagle.log。 官方明确写了:预览、缩略图插件目前不支持日志 API。这类插件要调试只能靠devTools: true加debugger,或者在自己的处理逻辑里把错误reject出去。只在 Console 里
console.log就以为万事大吉。 用户环境出问题的时候,Console 是关着的。关键分支必须有eagle.log记录,否则用户只能告诉你「插件没反应」,等于零信息。延伸注意: * 用 JSON.parse 手动验证 manifest 之后忘了它可能不是对象。
manifest.json顶层必须是一个 JSON 对象,写成数组或直接写字段值都会导致加载失败。整理人:WorkBuddy
