从零开发 Joplin 插件:基于 Yeoman 生成器与 Webpack 构建框架的完整实战指南
从零开发 Joplin 插件基于 Yeoman 生成器与 Webpack 构建框架的完整实战指南【免费下载链接】joplinJoplin - the privacy-focused note taking app with sync capabilities for Windows, macOS, Linux, Android and iOS.项目地址: https://gitcode.com/GitHub_Trending/jo/joplin本文以 Joplin 插件开发的标准流程为主线系统讲解如何通过generator-joplin脚手架快速创建插件工程、理解/src目录结构与清单文件、使用 Webpack 完成构建与 JPL 打包、维护版本号并最终发布到官方插件仓库。文中所有命令与配置均可直接复制运行并结合本仓库内置的codemirror5-and-codemirror6示例插件给出源码级的佐证读完后你将掌握 Joplin 插件从脚手架生成、构建、发布到更新维护的完整闭环能力。插件开发概览框架、构建器与 APIJoplin 插件体系由三部分构成插件源码本身基于 TypeScript、插件构建框架Webpack 驱动的generator-joplin工程、以及Joplin Plugin API以api/目录中的.d.ts类型声明形式提供。本仓库中 packages/generator-joplin 即为官方 Yeoman 生成器的实现其package.json声明了核心依赖yeoman-generator与slugify专门用于Scaffolds out a new Joplin plugin。一个典型的插件工程包含以下关键角色文件/目录作用/src/index.ts插件源码入口点注册插件生命周期与各类 API 调用/src/manifest.json插件清单声明名称、版本、作者、最低应用版本等元数据/plugin.config.json构建配置用于声明需要额外编译的外部脚本content scripts / webview scripts/webpack.config.jsWebpack 构建脚本负责编译、拷贝资源并生成 JPL 归档/dist/编译产物输出目录/publish/发布目录存放打包好的.jpl与.json文件环境准备安装 Yeoman 与 generator-joplin开发插件前需要 Node.js 环境文档假设已预装 node.js。随后通过 npm 全局安装 Yeoman 与 Joplin 生成器npm install -g yo4.3.1 npm install -g generator-joplin其中yo4.3.1为文档锁定的 Yeoman 版本generator-joplin即本仓库 packages/generator-joplin 对应发布的 npm 包。安装完成后在空目录中生成新插件工程yo --node-package-manager npm joplin生成器会询问插件名称等基本信息并自动完成工程骨架、package.json含joplin-plugin-前缀的包名与joplin-plugin关键字、webpack.config.js、tsconfig.json以及src/目录的初始化。项目结构入口、清单与构建配置生成后的工程里最核心的两个文件是/src/index.ts插件源码入口点。以本仓库示例插件 packages/app-cli/tests/support/plugins/codemirror5-and-codemirror6/src/index.ts 为例它通过joplin.plugins.register({ onStart: ... })注册启动逻辑并在onStart中调用registerSettings()注册设置项、调用registerCodeMirrorContentScript()注册内容脚本。/src/manifest.json插件清单。示例清单 src/manifest.json 声明了manifest_version: 1、插件id如com.example.cm6-test、app_min_version如2.13、version、name、author等字段此外还支持homepage_url、repository_url、keywords、categories、screenshots、icons等可选元数据。第三个值得关注的文件是/plugin.config.json它用于声明 外部脚本content scripts 或 webview scripts。示例插件中该文件内容如下{ extraScripts: [ contentScripts/codeMirror5.ts, contentScripts/codeMirror6.ts ] }工程默认采用 TypeScript但你也可以调整配置改用纯 JavaScript。构建插件npm run dist 的三阶段流水线插件的构建由 Webpack 驱动最终在/dist生成编译后的代码并在工程根目录准确说是/publish生成可供分发的 JPL 归档文件。构建命令非常简单npm run dist从示例插件 package.json 可以看到该命令的完整定义dist: webpack --env joplin-plugin-configbuildMain webpack --env joplin-plugin-configbuildExtraScripts webpack --env joplin-plugin-configcreateArchive这里通过--env joplin-plugin-config参数依次触发 webpack.config.js 中的三个构建阶段该文件注释明确指出三个 Webpack 配置必须串行执行因此采用多次运行 Webpack 而非并行配置的方式buildMain以./src/index.ts为入口编译主插件代码并通过CopyPlugin将/src下其余文件CSS、静态资源、无需编译的 JS拷贝到/dist。该阶段还会先清空并重建dist/与publish/目录。buildExtraScripts遍历plugin.config.json中的extraScripts为每个外部脚本单独生成一个 Webpack 配置并编译。由于会覆盖上一步拷贝过来的同名 JS 文件因此无需编译的 JS 被直接拷贝需要编译的TS 或带依赖的则被正确编译。createArchive以./dist/index.js为入口在onBuildCompleted钩子中执行createPluginArchive()用tar将dist内容打成.jpl与createPluginInfo()生成附带_publish_hash与_publish_commit的.json信息文件。值得注意的实现细节是Webpack 5 默认不再为 Node 内置模块提供 polyfill而插件运行在 Electron 的 Node 环境中因此webpack.config.js将builtinModules全部显式设为false以抑制警告。若dist目录为空createPluginArchive会直接抛错提示归档未创建。更新清单版本号npm run updateVersion发布前需要递增版本号运行npm run updateVersion该脚本只递增版本号的patch 部分——例如1.0.3变为1.0.4同时同步更新package.json与manifest.json中的版本号保证两者一致。其底层实现位于webpack.config.js的updateVersion()函数解析版本号字符串、末位数字加一后分别写回两个文件若两者最终不一致还会输出黄色警告提醒手动对齐。发布插件满足三项条件后自动入库插件通过npm publish发布到 npmjs.com。之后 Joplin 官方会运行脚本扫描已发布的包将其自动收录进 Joplin 插件仓库前提是满足以下条件package.json的name以joplin-plugin-开头例如joplin-plugin-toc。示例插件的包名joplin-plugin-codemirror-6-plugin即符合此规则。package.json的keywords包含joplin-plugin。publish/目录下存在.jpl和.json文件它们由npm run dist构建产生对应webpack.config.js中的pluginArchiveFilePath与pluginInfoFilePath。通常情况下插件生成器会自动完成这一切——设置package.json的名称与关键字并把正确文件放入publish目录。但如果插件始终没有出现在仓库中请逐条核对上述三项条件。webpack.config.js中的validatePackageJson()函数会在打包时对前两项做运行时校验包名缺少joplin-plugin-前缀或keywords缺失joplin-plugin时输出黄色警告同时建议使用prepare脚本而非postinstall以确保发布前执行构建。更新插件框架npm run update当需要升级插件框架时运行npm run update该命令会重装generator-joplin并调用yo joplin --update --force见示例插件package.json中update: npm install -g generator-joplin yo joplin --node-package-manager npm --update --force。它通常能做出正确选择合并而非覆盖package.json与.gitignore的变更并且不会改动/src目录与README.md。唯一可能出问题的是webpack.config.js因为它会被整体覆盖。因此官方建议如果你需要自定义构建行为不要直接改这个文件而是新建独立的 JavaScript 文件并在webpack.config.js中require引入——这样更新框架时只需恢复那一行引入语句即可自定义逻辑得以保留。外部脚本文件 extraScripts 深入为什么需要额外编译默认情况下Webpack 只编译src/index.ts及其 import 的文件其余文件会被原样拷贝进插件包。多数场景下这已足够但以下两类情况需要对外部脚本单独编译脚本是 TypeScript 文件必须编译为 JavaScript 才能运行脚本依赖了package.json中新增的模块无论 JS 还是 TS都必须编译以便把依赖打进 JPL 文件。典型场景是 content scripts 和 webview scripts。配置方法将脚本路径加入plugin.config.json的extraScripts数组路径相对/src。例如/src/webviews/index.ts应写为webviews/index.ts。编译后的文件始终以.js扩展名命名——你将得到webviews/index.js插件中引用该文件时也使用这个路径。webpack.config.js的resolveExtraScriptPath()完整展示了这一处理过程拼接./src/name校验文件存在、去掉扩展名作为输出文件名输出配置为library: defaultlibraryTarget: commonjs即编译产物以 CommonJS 默认导出形式供 Joplin 加载。示例佐证同时支持 CodeMirror 5 与 6 的内容脚本本仓库的示例插件codemirror5-and-codemirror6是理解该机制的绝佳范本。其plugin.config.json将两个内容脚本声明为extraScripts而webpack.config.js还专门定义了一份externalContentScriptLibraries列表包含codemirror/view、codemirror/state、codemirror/language等 CodeMirror 6 官方包通过externalsType: commonjs让内容脚本可以直接require(codemirror/...)引用这些库而无需重复打包。在 src/index.ts 中插件以ContentScriptType.CodeMirrorPlugin类型注册了两个内容脚本路径指向编译产物./contentScripts/${id}.js并注册了消息监听器const registerMessageListener async (contentScriptId: string) { await joplin.contentScripts.onMessage( contentScriptId, async (message: any) { if (message getSettings) { const settingValue await joplin.settings.value(highlightLineSettingId); return { highlightActiveLine: settingValue }; } }, ); };而两个内容脚本则分别面向两代编辑器实现同一功能高亮当前行 行号CodeMirror 6 版本codeMirror6.ts通过context.postMessage(getSettings)向主进程询问设置值再用codeMirrorWrapper.addExtension(lineNumbers())与highlightActiveLine()注入扩展若codeMirrorWrapper.cm6不存在则直接返回保证只在 CodeMirror 6 编辑器生效。CodeMirror 5 版本codeMirror5.ts通过defineOption(enable-highlight-extension, ...)自定义选项并读取设置后调用this.setOption(styleActiveLine, ...)通过codeMirrorResources加载addon/selection/active-line.js插件并在codeMirrorOptions中设置默认选项若codeMirror.cm6为真则跳过只对 CodeMirror 5 生效。两个脚本还通过assets: () [{ name: ./style.css }]声明共享样式资源。这个双版本示例直观展示了同一个设置项、同一套消息通信协议如何被extraScripts机制编译成两个独立内容脚本并分别适配新旧编辑器——这正是plugin.config.json外部脚本机制在实际插件中的典型应用。小结插件开发的标准工作流至此一条完整的 Joplin 插件开发链路已经清晰npm install -g yo4.3.1npm install -g generator-joplin准备脚手架yo --node-package-manager npm joplin生成工程聚焦src/index.ts与src/manifest.json按需在plugin.config.json声明extraScripts编译内容脚本或 webview 脚本npm run dist触发buildMain → buildExtraScripts → createArchive三阶段构建产出/dist与/publish中的 JPLnpm run updateVersion同步递增版本号npm publish发布到 npm满足包名、关键字、publish/产物三项条件后自动进入 Joplin 插件仓库升级框架时使用npm run update通过独立 JS 文件保留对webpack.config.js的自定义。你可以在本仓库 packages/generator-joplin 查看生成器实现在 packages/app-cli/tests/support/plugins/codemirror5-and-codemirror6 查看完整可运行的示例插件动手构建并验证上述每一个环节。【免费下载链接】joplinJoplin - the privacy-focused note taking app with sync capabilities for Windows, macOS, Linux, Android and iOS.项目地址: https://gitcode.com/GitHub_Trending/jo/joplin创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考