ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

使用 @yarnpkg/builder 构建 Yarn 插件:脚手架、TypeScript 打包与发布全指南

使用 @yarnpkg/builder 构建 Yarn 插件:脚手架、TypeScript 打包与发布全指南 开发工具CLI【免费下载链接】berry Active development trunk for Yarn ⚒项目地址https://gitcode.com/gh_mirrors/be/berry点击查看免费下载本文面向希望在 Yarn 3.x 生态中开发、构建与管理复杂插件的开发者完整讲解官方插件构建工具yarnpkg/builder的安装、三个核心命令new plugin、build plugin、build bundle的用法与全部可选参数并结合本仓库Yarn Berry monorepo中packages/yarnpkg-builder的源码实现剖析插件的生成模板、esbuild 打包原理、动态库外置策略与最终产物格式。读完本文你将能够从零生成一个 TypeScript 插件工程、构建出可直接被 Yarn 加载的单文件插件并理解 Yarn 官方插件体系背后的构建机制。一、yarnpkg/builder 是什么yarnpkg/builder是 Yarn BerryYarn 2/3/4 系列官方维护的一个 CLI 工具定位是为创建、构建和管理复杂插件而设计。它之于 Yarn 插件开发正如官方文档packages/docusaurus/docs/advanced/04-technical/plugin-tutorial.mdx中所形容的这个 builder 之于 Yarn就像 Next.js 之于 Web 开发——一个专门帮助你用 TypeScript 编写、打包和发布插件的开箱即用工具。Yarn 插件本质上是在运行时被 Yarn 加载的独立 JavaScript 脚本可以向 Yarn 注入新命令command、注册生命周期钩子hook、访问yarnpkg/core提供的核心 API。当插件规模变大、命令变多时手写单文件脚本会变得难以维护yarnpkg/builder正是为解决这一痛点而生。该包的工程信息见 packages/yarnpkg-builder/package.json当前仓库内版本为4.2.4许可证 BSD-2-Clause要求 Node.js 18.12.0运行时依赖yarnpkg/cli、yarnpkg/core、yarnpkg/fslib三个 workspace 包以及chalk终端着色、clipanion命令行框架Yarn 自身的命令体系也基于它、esbuild实际是esbuild-wasm用于在浏览器/纯 JS 环境下也能完成打包、semver、tslib。二、版本兼容性面向 Yarn 3.x 的插件在开始之前必须先明确版本对应关系原文关键信息务必重视当前版本的 builder 是为Yarn 3.x创建插件而设计的。Yarn 3 插件不兼容Yarn 2 安装但 Yarn 2 插件通常兼容 Yarn 3。如果你希望为 Yarn 2 创建插件请使用 builder 的 v2.xyarn add yarnpkg/builder^2。也就是说用本仓库master 分支中的 builder 生成的插件面向 Yarn 3 及以上存量 Yarn 2 插件一般可以继续在 Yarn 3 中使用若你的目标运行时是 Yarn 2需要锁定yarnpkg/builder^2版本。这一兼容性约束源于插件与 Yarn 运行时yarnpkg/cli、yarnpkg/core的 API 绑定关系插件构建时会将核心库当作动态库外置详见下文动态库外置一节因此插件与运行时版本必须匹配。三、核心特性yarnpkg/builder官方列出的特性如下builder new plugin命令一键生成插件工程脚手架builder build plugin命令构建复杂插件输出可直接加载的产物开箱即用地支持 TypeScript模板、入口、tsconfig 均已配好内部使用 ESBuild自带 treeshaking摇树、minification压缩及多种优化无需额外配置。从 sources/cli.ts 的 CLI 注册代码可以看到命令全集NewPluginCommand、BuildBundleCommand、BuildPluginCommand三个业务命令外加 clipanion 内置的DefinitionsCommand输出命令定义、HelpCommand帮助、VersionCommand版本。CLI 的二进制名称为builder。四、安装在插件工程或任意想使用 builder 的项目中将其作为开发依赖安装yarn add -D yarnpkg/builder安装后即可通过yarn builder ...或builder ...若已置于 PATH调用相关命令。五、命令总览yarnpkg/builder提供三个命令命令用途适用范围builder new plugin创建新插件生成模板工程所有用户builder build plugin构建本地插件打包为单文件所有用户builder build bundle从本仓库构建yarn.js单文件Yarn 自身二进制内部使用下面分别结合源码深入展开。六、builder new plugin一键生成插件工程6.1 基本用法builder new plugin yarn-plugin-hello-world命令接收一个位置参数target目标目录名/路径。其核心实现位于 sources/commands/new/plugin.ts将目标解析为可移植路径若目录已存在且非空直接抛出UsageError中止脚手架The target directory (...) isnt empty; aborting the scaffolding.递归创建目标目录及sources/子目录依次写入sources/index.ts、.gitignore、package.json、tsconfig.json四个文件输出提示信息Scaffolding done! Just go into 目录 and run yarn yarn build 。6.2 生成的插件源码模板生成的核心文件sources/index.ts是一个可直接运行的Hello World插件完整展示了 Yarn 插件的三种基本能力命令、钩子、导出import {Plugin} from yarnpkg/core; import {BaseCommand} from yarnpkg/cli; import {Option} from clipanion; class HelloWorldCommand extends BaseCommand { static paths [ [hello, world], ]; name Option.String(--name, John Doe, { description: Your name, }); async execute() { console.log(Hello ${this.name}!); } } const plugin: Plugin { hooks: { afterAllInstalled: () { console.log(What a great install, am I right?); }, }, commands: [ HelloWorldCommand, ], }; export default plugin;这一模板与官方插件教程plugin-tutorial.mdx中手写插件的方式一脉相承但以 TypeScript 类型安全的形式呈现命令注册通过BaseCommand来自yarnpkg/clistatic paths [[...]]声明命令路径这里为hello world二级命令用 clipanion 的Option.String声明带默认值的选项钩子注册通过hooks.afterAllInstalled在每次安装完成后触发回调默认导出导出Plugin对象Yarn 运行时加载后即可识别。6.3 生成的工程配置同时生成的package.json由 new/plugin.ts 写入包含{ name: yarn-plugin-helloworld, private: true, main: ./sources/index.ts, dependencies: { yarnpkg/cli: 与 builder 相同的版本, yarnpkg/core: 与 builder 相同的版本, clipanion: 与 builder 相同的版本 }, devDependencies: { types/node: ^本机 Node 主版本号.0.0, yarnpkg/builder: ^4.2.4, rimraf: 5.0.0, typescript: 与 builder 相同的版本 }, scripts: { build: builder build plugin, build:dev: builder build plugin --no-minify, clean: rimraf bundles } }值得注意的几个设计细节三个运行时依赖的版本直接继承自 builder 自身的依赖版本源码中通过require(yarnpkg/builder/package.json).dependencies[...]读取从而保证插件与 Yarn 运行时 API 严格对齐types/node版本按本机 Node 主版本动态生成预置了build生产构建、build:dev跳过压缩的开发构建、clean清理bundles/产物目录三个脚本其中bundles/也被写入.gitignorenew/plugin.ts。生成的tsconfig.json同样由模板写出核心编译选项为{ compilerOptions: { experimentalDecorators: true, module: commonjs, target: ES2021, lib: [ES2021] }, include: [sources/**/*.ts] }6.4 进入工程后的开发流程按脚手架提示操作cd yarn-plugin-hello-world yarn # 安装依赖 yarn build # 等价于 builder build plugin产出 bundles/yarn-plugin-helloworld.js构建产物位于bundles/目录即为可被 Yarn 加载的插件文件。七、builder build plugin把 TypeScript 插件打包成单文件7.1 基本用法与选项builder build plugin builder build plugin --no-minify # 开发模式跳过压缩/摇树/变量名混淆 builder build plugin --source-map # 在 bundle 中内联 source map builder build plugin --metafile # 额外产出 esbuild metafile构建元数据命令实现位于 sources/commands/build/plugin.ts各选项定义如下选项类型默认值说明--no-minifyBooleanfalse开发模式构建不做压缩、混淆、摇树优化--source-mapBooleanfalse在 bundle 内联 source map--metafileBooleanfalse在 bundle 旁产出.meta.json元数据文件7.2 构建流程与产物格式构建核心逻辑build/plugin.ts读取当前目录package.json的name与main字段通过getNormalizedName将插件名规范化为yarnpkg/plugin-name形式——该函数要求名称匹配yarn-plugin-something或scope/yarn-plugin-*模式否则抛出Invalid plugin name错误规范化后arcanis/yarn-plugin-foo、mael/yarn-plugin-foo等名字都会统一映射为yarnpkg/plugin-foo这正是任何人都可以覆盖官方插件的命名机制用 esbuild 以entryPoints: [main ?? sources/index]为入口打包bundle: true输出到bundles/name.js通过 esbuild 的banner/footer 机制把产物包装为 Yarn 插件运行时约定的格式/* eslint-disable */ //prettier-ignore module.exports { name: yarnpkg/plugin-hello-world, factory: function (require) { ... /* 打包后的插件实现 */ return plugin; } };这个{name, factory}结构正是 Yarn 加载插件时的标准契约name声明插件标识factory(require)接收 Yarn 注入的require函数用于获取yarnpkg/core、yarnpkg/cli等动态库返回包含commands、hooks等成员的对象。手写插件见 plugin-tutorial.mdx也是同一结构builder 只是把这个样板自动完成了。其余 esbuild 配置要点format: iife、platform: node目标 Node 版本取自 builder 自身engines.node的最小版本semver.minVersionresolveExtensions覆盖.tsx/.ts/.jsx/.mjs/.js/.css/.json即默认扩展名外加.mjssupported中将node:前缀导入/require 标记为不支持node-colon-prefix-import: false让 esbuild 剥离该前缀——这是为了兼容旧版插件运行时Yarn 内部对node:内建模块前缀的处理细节见 build/plugin.ts 的注释对应 Yarn 的 #5997 修复logLevel: silent警告统一经由StreamReport输出带文件:行:列定位信息构建结束会打印 Bundle 路径与Bundle size字节数失败则输出Failed to build name并返回非零退出码。7.3 动态库外置为什么插件能共享 Yarn 的运行时 APIbuilder build plugin的一个关键机制是dynamic-lib-resolverbuild/plugin.ts它注册了一个 esbuildonResolve插件把所有动态库请求标记为external: true从而在打包时不将它们打进产物而是在运行时由 Yarn 通过factory(require)注入。判断逻辑在 sources/tools/isDynamicLib.tsimport {getDynamicLibs} from yarnpkg/cli; export const isDynamicLib (request: string) { if (getDynamicLibs().has(request)) return true; if (request.match(/^yarnpkg\/plugin-/)) return true; return false; };即满足以下任一条件即视为动态库是yarnpkg/cli暴露的动态库集合成员yarnpkg/core、yarnpkg/cli、clipanion、typanion等可经 yarnpkg-cli/sources 中的getDynamicLibs查看全集请求以yarnpkg/plugin-开头即其他插件。路径解析用了一个精妙的包名正则pathRegExpbuild/plugin.ts用于区分真正的依赖包请求与文件路径请求——文件路径相对/绝对路径、Windows 盘符路径不会被外置。正是这套机制让插件得以像使用 peer dependency 一样复用 Yarn 自身的核心 API产物体积也因此大幅缩小。八、builder build bundle构建 Yarn 自身二进制内部命令8.1 用途builder build bundle该命令用于从本仓库构建 Yarn 的可执行单文件yarn.js——即实际安装在用户项目中的 Yarn 二进制文件。它在 sources/commands/build/bundle.ts 中实现README 明确标注为internal内部命令普通插件开发者通常无需使用但理解它能帮助你把握 Yarn 自身的插件体系构成。8.2 选项选项类型默认值说明--profileStringstandard只包含指定 profile 中的插件用组合多个 profile如standardextra--pluginArray[]额外显式加入的插件路径列表可多次传入--no-git-hashBooleanfalse不在 bundle 版本号中附带当前 commit 的 git hash--no-minifyBooleanfalse开发模式不做压缩/混淆/摇树--source-mapBooleanfalse内联 source map--metafileBooleanfalse产出yarn.meta.json元数据8.3 插件清单的 Profile 机制findPluginssources/tools/findPlugins.ts从当前目录package.json中读取构建配置{ yarnpkg/builder: { bundles: { standard: [packages/plugin-essentials, ...] } } }逻辑要点若package.json缺少yarnpkg/builder.bundles配置直接报错This command requires your package.json to contain specific configuration keys--profile缺省为standard支持用连接多个 profile如standardfoo每个 profile 名必须存在于bundles键集合中否则报Invalid profile并列出合法值最终插件清单 各 profile 下的插件并集 --plugin显式传入的插件去重后按序输出。在本仓库中plugins.yml 记录了官方认可的插件清单yarnpkg/plugin-constraints、yarnpkg/plugin-exec、yarnpkg/plugin-interactive-tools、yarnpkg/plugin-stage、yarnpkg/plugin-typescript、yarnpkg/plugin-version、yarnpkg/plugin-workspace-tools等其中/master/占位会在yarn plugin import时被替换为实际发布 tag这些插件正是通过 builder 构建后以{name, factory}单文件形式供 Yarn 下载与加载的。8.4 构建与版本号处理入口为sources/cli.ts产物输出到bundles/yarn.js构建完成后chmod 0o755赋予可执行权限版本号 package.json的version若未指定--no-git-hash会尝试调用git show -s --prettyformat:%ad.%h --dateshort获取提交日期与短哈希拼装为类似4.2.4-git.20240926.hash-abcdef1的版本预发布版本用.连接正式版本用-连接详见 bundle.ts通过 esbuilddefine注入YARN_VERSION等编译期常量--no-minify模式下还会额外注入process.env.NODE_ENVproduction、process.env.DEVfalse等为 React、ink、mkdirp 等库提供正确的生产环境语义使用val-loader插件在构建时执行getPluginConfiguration.ts的.val.js编译产物把modules动态库plugins插件清单静态嵌入配置bundle.ts构建结束同样报告 Bundle path / size / version并逐个列出纳入的插件清单→ yarnpkg/plugin-...。8.5 在本仓库中运行仓库提供了开发入口脚本 scripts/run-builder.js它直接加载packages/yarnpkg-builder/sources/boot-cli-dev.js经 setup-ts-execution 完成 TS 运行时准备后进入 cli.ts因此在本仓库根目录可直接以yarn node scripts/run-builder.js build bundle之类的方式调用 builder 命令进行验证产物落在仓库的bundles/目录。注意该命令面向仓库内部开发普通插件工程请使用builder new plugin/builder build plugin。九、把构建好的插件接入 Yarn构建产物bundles/yarn-plugin-name.js可以通过 Yarn 的插件机制加载配置文件方式在项目根目录.yarnrc.yml的plugins字段中登记插件路径官方插件教程 plugin-tutorial.mdx 展示了这一用法yarn plugin import官方插件如 plugins.yml 所列可通过导入命令拉取对应 URL 的构建产物/master/占位符会在运行时被替换为 CLI 版本对应的 release tag环境变量方式YARN_PLUGINS环境变量分号分隔的插件路径列表可在运行时动态加载插件供第三方工具在不改动用户.yarnrc.yml的前提下注册插件详见 plugin-tutorial.mdx。十、小结一条完整的插件开发流水线综合全文使用yarnpkg/builder的完整工作流为yarn add -D yarnpkg/builder安装构建工具Yarn 3.x 目标若面向 Yarn 2 使用yarnpkg/builder^2builder new plugin yarn-plugin-my-plugin生成 TypeScript 工程含sources/index.ts、package.json、tsconfig.json、.gitignore在sources/index.ts中基于Plugin类型、BaseCommand与 clipanion 选项装饰器编写命令与钩子yarn build即builder build plugin由 esbuild 完成摇树、压缩与{name, factory}包装产出bundles/yarn-plugin-my-plugin.js开发迭代时用yarn build:dev--no-minify加速将产物通过.yarnrc.yml的plugins、yarn plugin import或YARN_PLUGINS接入 Yarn 运行验证。yarnpkg/builder通过将 TypeScript 支持、ESBuild 优化、动态库外置、命名规范化与 profile 机制封装为三个命令把 Yarn 插件从手写单文件脚本升级为可工程化、可发布、可覆盖官方插件的完整开发体系而本仓库 packages/yarnpkg-builder/sources 下的实现代码就是理解这套体系的最佳教材。赞分享开发工具CLI【免费下载链接】berry Active development trunk for Yarn ⚒项目地址https://gitcode.com/gh_mirrors/be/berry点击查看免费下载相关推荐Joplin 插件开发指南使用 generator-joplin 脚手架从零构建、打包与发布插件Joplin 插件开发指南使用 generator joplin 脚手架从零构建、打包与发布插件 本篇技术指南以 Joplin 官方 Yeoman 生成器 g知识管理跨平台插件系统Joplin 插件开发实战使用 generator-joplin 脚手架从零构建、打包与发布插件Joplin 插件开发实战使用 generator joplin 脚手架从零构建、打包与发布插件 Joplin 是支持 Windows、macOS、Linux知识管理跨平台插件系统Joplin 插件开发入门使用 generator-joplin 脚手架从零构建、打包与发布插件Joplin 插件开发入门使用 generator joplin 脚手架从零构建、打包与发布插件 本指南围绕 Joplin 官方插件脚手架 generator知识管理跨平台插件系统上一篇免费城通网盘高速解析工具终极指南30倍下载速度提升的完整解决方案下一篇为什么你需要微软XML编辑器5分钟掌握XML Notepad完整指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表