为 Super Productivity 开发 Solid.js 插件:官方样板工程完整实战指南

📅 发布时间:2026/9/13 1:59:29
为 Super Productivity 开发 Solid.js 插件:官方样板工程完整实战指南
为 Super Productivity 开发 Solid.js 插件官方样板工程完整实战指南【免费下载链接】super-productivitySuper Productivity is an advanced todo list app with integrated Timeboxing and time tracking capabilities. It also comes with integrations for Jira, GitLab, GitHub and Open Project.项目地址: https://gitcode.com/GitHub_Trending/su/super-productivity本篇指南围绕 Super Productivity 官方仓库中随附的Solid.js 插件样板工程位于packages/plugin-dev/boilerplate-solid-js系统讲解如何用 Solid.js TypeScript Vite 从零搭建一个可直接运行、可打包、可分发到 Super Productivity 的插件。读完本文你将掌握插件目录结构、manifest.json元数据编写、Plugin API 的注册与数据操作、事件钩子、插件 UI 与宿主应用的消息通信以及完整的开发—构建—打包—安装流水线。一、这个样板工程能做什么样板工程定位清晰为创建 Super Productivity 插件提供开箱即用的现代 TypeScript 基座核心特性如下对应 README 的 Features 章节Solid.js—— 快速、响应式的 UI 框架细粒度响应式信号 组件化开发TypeScript—— 借助super-productivity/plugin-api获得完整的插件 API 类型安全现代 UI—— 干净、响应式、自带暗色模式支持的界面样式Vite—— 闪电般快速的开发与构建工具链开箱即用—— 已内置覆盖各类插件功能的完整示例代码。一句话总结样板工程把插件开发基础设施构建、打包、内联、类型、i18n全部配好开发者只需专注于自己的业务逻辑。二、环境准备与快速开始2.1 环境要求依赖项版本要求Node.js16包管理器npm 或 yarnSuper Productivity8.0.0与manifest.json中minSupVersion: 8.0.0对应2.2 初始化插件工程Super Productivity 的插件开发目录位于仓库的packages/plugin-dev/其中已包含多个插件示例automations、doc-mode、todoist-import 等和样板工程boilerplate-solid-js。复制样板即可生成你自己的插件cd packages/plugin-dev cp -r boilerplate-solid-js my-plugin cd my-plugin2.3 安装依赖npm install安装完成后node_modules中会以file:协议链接仓库内的两个关键包见 package.jsonsuper-productivity/plugin-api→../../plugin-api官方 TypeScript 类型定义super-productivity/vite-plugin→../../vite-plugin为插件量身定制的 Vite 插件负责构建产物整理、HTML 资产内联。2.4 更新插件元数据编辑src/manifest.json按自己的插件进行定制将id改为全局唯一的标识符更新name、description、author按需调整permissions与hooks。注意id是插件的唯一标识打包文件名也会以${id}-v${version}.zip命名见下文打包章节务必确保唯一。三、manifest.json 插件清单详解manifest.json是插件与 Super Productivity 宿主之间最重要的契约文件。样板默认内容如下源码{ id: boilerplate-solid-js, name: Solid.js Boilerplate Plugin, version: 1.0.0, manifestVersion: 1, minSupVersion: 8.0.0, description: A boilerplate plugin demonstrating Solid.js integration with Super Productivity, author: Your Name, homepage: https://github.com/yourusername/your-plugin, repository: { type: git, url: https://github.com/yourusername/your-plugin.git }, permissions: [], hooks: [taskComplete, taskUpdate, contextChange], iFrame: true, sidePanel: false, isSkipMenuEntry: false, icon: icon.svg, i18n: { languages: [en, de] } }对照 Plugin API 中定义的PluginManifest接口types.ts各字段含义如下字段类型说明idstring插件唯一标识同时用于打包产物命名namestring插件显示名称manifestVersionnumber清单格式版本号当前为1versionstring插件版本号语义化版本minSupVersionstring兼容的最低 Super Productivity 版本descriptionstring插件简介hooksHooks[]插件订阅的宿主事件列表详见下文事件钩子permissionsstring[]插件申请的能力清单例如网络请求需要声明httpiFrameboolean为true时插件 UI 以 iframe 形式加载index.html被渲染为视图sidePanelboolean为true时插件加载到右侧面板而非路由视图isSkipMenuEntryboolean是否跳过默认生成的菜单入口iconstring插件图标 SVG 路径相对插件根目录i18n.languagesstring[]支持的界面语言代码列表如[en, de]另外PluginManifest还支持allowedHosts精确声明插件可访问的域名白名单配合http权限生效未声明则request默认拒绝、type: standard | issueProvider、nodeScriptConfig、uiKit、jsonSchemaCfg等高级字段开发者可根据需要扩展。四、开发、构建、打包与部署的完整命令链路样板工程的package.json提供了完整的脚本集源码scripts: { dev: vite, build: vite build, preview: vite preview, lint: eslint ., format: prettier --write ., typecheck: tsc --noEmit, package: node scripts/build-plugin.js, deploy: npm run build }4.1 开发npm run dev启动 Vite 开发服务器进入 watch 模式源码修改后插件会实时重建配合浏览器 HMR 可以快速迭代 UI。开发调试时可将 Super Productivity 的插件目录指向构建产物进行即时验证。4.2 构建npm run build调用vite build生成生产构建产物输出到dist/目录。关键点在于vite.config.ts源码同时挂载了vite-plugin-solid和官方提供的superProductivityPlugin()import { defineConfig } from vite; import solidPlugin from vite-plugin-solid; import { superProductivityPlugin } from super-productivity/vite-plugin; export default defineConfig({ plugins: [solidPlugin(), superProductivityPlugin()], test: { environment: jsdom, globals: true, transformMode: { web: [/\.[jt]sx?$/] }, }, resolve: { conditions: [development, browser] }, });superProductivityPlugin()实现见 vite-plugin/src/index.ts在closeBundle钩子中替你做完了三类收尾工作复制产物把src/manifest.json、src/assets/icon.svg复制到dist/并把i18n/目录下的.json翻译文件一并复制过去处理 HTML将 Vite 生成的index.js含 modulepreload 移除与index.css通过字符串替换内联进index.htmlinlineAssets默认true可选自动同步配置copyTo选项后构建完成会把dist/递归复制到指定目录便于构建即热更新到正在运行的宿主应用。4.3 打包npm run package执行 scripts/build-plugin.js流程为先执行npm run build确保产物最新读取src/manifest.json以${manifest.id}-v${manifest.version}.zip作为输出文件名如boilerplate-solid-js-v1.0.0.zip使用archiverzlib压缩级别 9把dist/整个目录打成 ZIP输出 ZIP 到插件工程根目录并打印文件大小。npm run package4.4 带 HTML UI 的插件必须使用内联npm run deploy如果插件带有index.htmlUI 组件、侧边面板等推荐使用 deploy 命令npm run deploy从仓库实际脚本看deploy等价于npm run build内联逻辑由super-productivity/vite-plugin在构建期完成。为什么必须内联这是本项目插件机制的关键约束Super Productivity 以data:URL 的方式加载插件 HTML因此index.html无法引用任何外部文件。superProductivityPlugin默认开启的inlineAssets会把所有 JS 与 CSS 直接嵌进 HTML确保插件在data:URL 环境下能完整运行。若你的插件包含 UI 却跳过这一步会出现脚本、样式全部失效的诡异问题。4.5 其他辅助命令npm run typechecktsc --noEmit静态类型检查排查构建错误的首选工具npm run lint/npm run formatESLint Prettier 代码规范检查与格式化npm run preview本地预览构建产物。五、项目结构解析样板工程的目录结构如下src/ ├── assets/ # 静态资源图标、图片 │ └── icon.svg # 插件图标 ├── app/ # Solid.js 应用 │ ├── App.tsx # 主应用组件 │ └── App.css # 应用样式 ├── index.html # 插件 UI 入口 ├── index.tsx # UI 初始化挂载 Solid 根组件 ├── plugin.ts # 插件逻辑与 API 集成 └── manifest.json # 插件元数据 scripts/ └── build-plugin.js # 插件打包脚本 dist/ # 构建产物已被 .gitignore 忽略 ├── assets/ ├── index.html # 已内联所有 JS/CSS ├── index.js ├── plugin.js └── manifest.json各入口文件的职责src/index.tsx源码找到#root节点并用render()挂载 Solid 根组件Appsrc/plugin.ts源码运行在宿主渲染进程中的主脚本负责注册 UI 入口、事件钩子和消息处理器——这是插件的大脑src/app/App.tsx源码Solid.js 编写的插件界面通过window.parent.postMessage与plugin.ts通信dist/最终被打包分发的完整产物。六、Plugin API 实战6.1 基础接入插件 API 通过全局对象plugin暴露在plugin.ts中声明即可获得类型支持import { PluginInterface } from super-productivity/plugin-api; declare const plugin: PluginInterface;与样板实际代码对照当前版本从super-productivity/plugin-api导出的是PluginAPI类型见 plugin.tsplugin为宿主注入的全局实例。无论接口名如何演进全局对象 声明式注册的接入模式不变。PluginAPI接口types.ts还提供了cfg主题、平台、应用版本等基础配置、Hooks枚举常量以及完整的日志对象plugin.loginfo/debug/warn/error等。6.2 UI 注册header 按钮、菜单项与快捷键文档中给出的经典示例注册三种入口// 注册头部按钮 plugin.registerHeaderButton({ icon: rocket, tooltip: Open Plugin, action: () plugin.showIndexHtmlAsView(), }); // 注册菜单项 plugin.registerMenuEntry({ label: My Plugin, icon: rocket, action: () plugin.showIndexHtmlAsView(), }); // 注册键盘快捷键 plugin.registerShortcut({ keys: ctrlshiftm, label: Open My Plugin, action: () plugin.showIndexHtmlAsView(), });三个入口统一通过plugin.showIndexHtmlAsView()把插件 UI 渲染为应用视图。样板实际实现plugin.ts与文档略有出入注意当前签名为registerHeaderButton({ icon, label, onClick })registerMenuEntry({ label, icon, onClick })registerShortcut({ id, label, onExec })id用于后续unregisterShortcut精确移除。此外 API 还提供registerSidePanelButton侧边面板按钮和registerWorkContextHeaderButton仅在特定工作上下文——项目/标签/Today 下显示的按钮扩展 UI 场景很灵活。6.3 数据操作任务、项目与标签// 获取任务 const tasks await plugin.getTasks(); const archivedTasks await plugin.getArchivedTasks(); // 创建任务 const newTask await plugin.addTask({ title: New Task, projectId: project-id, }); // 更新任务 await plugin.updateTask(task-id, { title: Updated Title, isDone: true, }); // 获取项目和标签 const projects await plugin.getAllProjects(); const tags await plugin.getAllTags();从PluginAPI接口看数据操作能力远不止于此types.ts任务getCurrentContextTasks()、getSelectedTask()、getFocusedTask()、getAppState()任务/项目/标签/笔记/重复任务/计数器的全量只读快照、deleteTask()、batchUpdateForProject()、reorderTasks()、selectTask()项目addProject()、updateProject()、deleteProject()级联删除项目内任务Inbox 不可删标签addTag()、updateTag()数据模型Tasktypes.ts包含timeEstimate、timeSpent、tagIds、subTaskIds、repeatCfgId、issueId等字段插件可直接读写Project与Tag类型同样开放。6.4 事件钩子订阅宿主事件// 任务完成 plugin.on(taskComplete, (task) { console.log(Task completed:, task.title); }); // 任务更新 plugin.on(taskUpdate, (task) { console.log(Task updated:, task); }); // 上下文切换 plugin.on(contextChange, (context) { console.log(Context changed:, context); });与仓库实现对照当前版本使用plugin.registerHook(PluginHooks.X, handler)注册钩子且钩子名称以PluginHooks枚举为准types.ts。完整枚举如下枚举值字符串触发时机TASK_CREATEDtaskCreated任务创建TASK_COMPLETEtaskComplete任务完成TASK_UPDATEtaskUpdate任务更新含changesTASK_DELETEtaskDelete任务删除CURRENT_TASK_CHANGEcurrentTaskChange当前计时任务切换FINISH_DAYfinishDay结束一天LANGUAGE_CHANGElanguageChange界面语言切换PERSISTED_DATA_CHANGEDpersistedDataChanged持久化数据变化ACTIONaction自定义动作ANY_TASK_UPDATEanyTaskUpdate任意任务更新统一载荷PROJECT_LIST_UPDATEprojectListUpdate项目列表更新WORK_CONTEXT_CHANGEworkContextChange工作上下文切换样板manifest.json中声明的contextChange属于文档化旧写法当前枚举的标准值是workContextChange。声明hooks时建议与PluginHooks枚举保持一致避免钩子不生效。每个钩子的载荷类型TaskCompletePayload、TaskUpdatePayload、WorkContextChangePayload等也都在 types.ts 中有明确定义。样板实际代码示范了registerHook的完整用法包括任务完成时的成功通知、项目切换时的日志记录以及语言切换时向 iframe 广播languageChanged消息plugin.ts。6.5 插件与 UI 的通信postMessage 消息桥plugin.ts宿主进程侧与 Solid.js UIiframe 内无法直接调用彼此函数两者通过window.postMessage通信。宿主侧注册消息处理器// 在 plugin.ts 中 plugin.onMessage(myCommand, async (data) { // 处理来自 UI 的消息 return { result: success }; });UI 侧发送带messageId的消息并等待响应这是样板 App.tsx 中sendMessage的完整实现const sendMessage async (type: string, payload?: any) { return new Promise((resolve) { const messageId Math.random().toString(36).substr(2, 9); const handler (event: MessageEvent) { if (event.data.messageId messageId) { window.removeEventListener(message, handler); resolve(event.data.response); } }; window.addEventListener(message, handler); window.parent.postMessage({ type, payload, messageId }, *); }); }; // 用法示例 const result await sendMessage(myCommand, { foo: bar });在样板工程中这套协议被进一步规范化useTranslate工具useTranslate.ts以type: PLUGIN_MESSAGEmessageId发送监听type: PLUGIN_MESSAGE_RESPONSE的响应。plugin.ts侧则用plugin.onMessage处理各种message.type样板已内置getStats、createTask、getTasks、getAllProjects、saveSettings、loadSettings、translate、getCurrentLanguage等命令plugin.ts。这套请求—响应桥接模式是所有带 UI 的 Super Productivity 插件都要复用的核心通信范式。6.6 i18n 国际化样板支持多语言插件界面在manifest.json的i18n.languages声明语言如[en, de]在工程根目录i18n/下按语言放置 JSON 文件如 en.json、de.json构建时由 vite 插件自动复制到dist/i18n/UI 中通过sendMessage(translate, { key, params })取值useTranslate钩子还封装了响应式翻译能力t(APP.TITLE)并自动监听languageChanged事件实时刷新界面文案宿主语言切换时plugin.ts通过PluginHooks.LANGUAGE_CHANGE钩子向 iframe 广播新的语言plugin.ts。七、定制你的插件7.1 样式定制样板已内置 CSS 自定义属性theming、暗色模式与响应式设计。修改src/app/App.css即可调整外观App 组件中还通过settings().theme切换data-theme属性来应用明暗主题App.tsx与 Super Productivity 自身的主题体系一致。7.2 新增功能想做的事操作位置新增 UI 组件在src/app/下新建.tsx文件新增 API 端点/命令在src/plugin.ts中通过plugin.onMessage增加case分支新增事件钩子在manifest.json的hooks声明并在plugin.ts用registerHook处理新增权限在manifest.json的permissions中追加声明八、最佳实践类型安全始终使用super-productivity/plugin-api导出的 TypeScript 类型Task、Project、PluginAPI、PluginHooks等充分利用编译期检查错误处理所有异步操作包裹在 try-catch 中避免未捕获异常影响宿主应用可参考 App.tsx 中onMount/refreshData的模式性能高效使用 Solid.js 的 signals 与 effects避免不必要的重渲染大数据量渲染优先使用For/Show等内置控制流安全绝不暴露敏感数据或危险操作发起网络请求前在manifest.json中声明http权限并精确配置allowedHosts白名单用户体验为异步操作提供 loading 状态与错误反馈样板已在App.tsx中示范isLoading信号 加载提示。九、将插件部署到 Super Productivity完整分发流程npm run build # 1. 构建若带 HTML UI内联资产已在此步完成 npm run package # 2. 打包生成 id-vversion.zip然后在 Super Productivity 中安装打开 Super Productivity进入Settings → Plugins点击Upload Plugin选择生成的 ZIP 文件。安装后插件即出现在菜单/头部按钮中可立即验证功能。迭代开发时可结合 vite 插件的copyTo选项把构建产物自动同步到本地调试目录实现改代码—构建—热更新的快速闭环。十、常见问题排查插件无法加载查看浏览器控制台错误信息验证manifest.json是否为合法 JSON确认minSupVersion与当前 Super Productivity 版本匹配样板要求 8.0.0。API 调用失败检查manifest.json中是否声明了所需permissions如网络请求的http确认 Super Productivity 运行的是正确版本查看控制台中的错误日志可使用plugin.log输出调试信息。构建错误运行npm run typecheck检查 TypeScript 类型错误确保所有依赖已安装必要时清空node_modules后重新npm install。十一、进一步探索仓库内的同类实现样板工程不是孤立示例packages/plugin-dev/目录下还有大量基于同一技术栈与 API 的真实插件是绝佳的进阶学习素材automations完整的自动化规则插件触发条件 执行动作 规则编辑器 UI展示了复杂插件如何组织src/core、src/app等模块并自带全套 vitest 单测*.spec.tsdoc-mode、todoist-import、sync-md覆盖文档模式、数据导入、Markdown 同步等真实业务场景plugin-api 类型定义插件 API 的唯一事实来源含详尽的 JSDoc 注释vite-plugin 实现理解构建与内联细节的最佳入口。从复制boilerplate-solid-js、跑通npm run dev开始对照 插件开发文档 与 开发指南如存在你就能快速进入 Super Productivity 插件开发的正轨。【免费下载链接】super-productivitySuper Productivity is an advanced todo list app with integrated Timeboxing and time tracking capabilities. It also comes with integrations for Jira, GitLab, GitHub and Open Project.项目地址: https://gitcode.com/GitHub_Trending/su/super-productivity创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考