ARTICLE DETAIL

资讯详情

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

Halo ESM UI 插件运行时规范深度解析:Provider Manifest、宿主运行时快照与 Import Map 共享依赖

Halo ESM UI 插件运行时规范深度解析:Provider Manifest、宿主运行时快照与 Import Map 共享依赖 Halo ESM UI 插件运行时规范深度解析Provider Manifest、宿主运行时快照与 Import Map 共享依赖【免费下载链接】haloHalo 是一款强大易用的开源建站工具从个人博客、知识库到企业官网、在线商城Halo 都能助您轻松实现一站式满足您的多样化建站需求。项目地址: https://gitcode.com/GitHub_Trending/ha/haloHalo 的 Console 与 User Center 管理界面允许插件和主题以 UI 模块的形式注入路由、组件、表单与扩展点。本文基于仓库内的正式规范 ui-plugin-esm-runtime spec结合halo-dev/ui-plugin-bundler-kit、halo-dev/ui-shared与后端UiPluginEndpoint的实现系统讲解 Halo 2.x 中 ESM 格式 UI Provider 的清单格式、宿主运行时快照、共享依赖解析、Provider 描述符、注册 Store、混合加载、失败隔离与缓存边界。读完本文你将理解 ESM 与 legacy IIFE 两种 UI Provider 在 Halo 中的共存机制掌握ui-plugin.json清单的校验规则、共享依赖的边界划分以及插件/主题开发者与 Halo 核心维护者在运行时协议上各自承担的责任。一、规范定位Halo UI Provider 从 IIFE 到 ESM 的运行时协议Halo 管理端Console与用户中心User Center的插件 UI 生态经历了从传统 IIFE 全局脚本到标准 ESM 模块的演进。ui-plugin-esm-runtime规范定义了这一演进中的核心运行时契约覆盖六大主题Provider UI module manifest插件或主题如何用一份生成式清单描述自己提供的 ESM UI 模块Halo host runtime snapshot宿主Halo 本体如何发布其共享运行时事实实际解析版本与根级导出供 Provider 构建期比对Host-owned shared dependency resolution浏览器端共享包根package root到 Halo 运行时模块的映射由谁拥有Versioned provider descriptor后端如何通过一个认证响应描述当前所有 UI ProviderShared UI provider registration storeProvider 之间如何通过只读的共享 Store 互查可用性与注册状态Mixed legacy and ESM loading / failure isolation / lifecycle boundary两类 Provider 如何在同一个页面会话中共存、隔离失败并安全地管理缓存。从仓库源码看规范被拆分为两端的落地实现前端构建工具链位于 ui/packages/ui-plugin-bundler-kit负责 manifest 生成、快照校验、ESM 输出插件共享运行时 API 位于 ui/packages/shared/srcstores.uiPlugins()、definePlugin、PluginModule类型后端描述符端点位于 UiPluginEndpoint.java。三者共同构成构建期验证 运行期发现 运行期隔离的完整链路。二、Provider UI Module Manifestui-plugin.json清单2.1 清单语义规范要求HaloSHALL以一份生成的 Provider Manifest 作为插件或主题所提供 ESM UI 模块的权威描述。清单文件名固定为ui-plugin.json其结构为{ format: esm, entry: ./assets/entries/index.js, style: ./assets/entries/style.css }字段类型必填说明formatstring是必须为esm缺失或为其他值时 Provider 按无效处理entrystring是ESM 入口模块路径相对于 Provider 资源根目录stylestring否启动样式表路径至多一个同样相对 Provider 资源根目录对应实现见 provider-manifest.tsEsmProviderManifest接口只允许format、entry、style三个键。validateEsmProviderManifest对清单做了严格校验必须是对象、必须同时包含entry与format、不允许出现这三个键之外的任何键、format必须严格等于esm、entry必须是字符串。2.2 路径合法性约束拒绝逃逸 Provider 根目录规范明确规定清单中的资源路径不得是绝对路径、跨域 URL如https://...或越过 Provider 根目录的路径。实现上由normalizeProviderResourcePath承担provider-manifest.ts其判定逻辑包括反斜杠统一归一化为正斜杠以/或//开头绝对路径直接拒绝匹配协议前缀/^[a-zA-Z][a-zA-Z\d.-]*:/即http:、data:等直接拒绝包含?或#查询参数、片段直接拒绝经path.posix.normalize归一化后若结果为..或以../开头判定为逃逸根目录并拒绝。这从构建产物侧就杜绝了 Provider 资源越权读取配合运行时后端的静态资源映射共同构成安全边界。2.3 清单由构建插件自动生成清单不是手写的而是 ESM Provider 构建的产物。在 Vite 生态中vite-esm.ts 的createViteEsmProviderPlugin会在generateBundle阶段自动生成清单并作为 asset 写入产物vite-esm.ts 第 34-68 行检查产物中恰好一个入口 chunk且该入口必须导出default对应下文PluginModule入口关联的 CSS 至多一个否则报错ESM UI provider output must contain at most one entry stylesheet将入口与可选的样式路径填入 manifestemitFile输出ui-plugin.json。也就是说一个合法的 ESM UI Provider 产物 一个带 default 导出的入口模块 可选一个启动样式 自动生成的ui-plugin.json。2.4 无清单与无效清单的分流规范规定了两种降级/拒绝路径Provider 没有 manifest即插件或主题提供了 UI 打包资源但没有ui-plugin.jsonHaloSHALL将其归类为 legacy IIFE Provider走既有的全局脚本协议Provider manifest 存在但无效JSON 解析失败、format不支持、缺少运行时字段、资源路径非法——HaloSHALL将该 Provider 标记为invalid并且禁止回退为按 legacy IIFE 执行其资源。三、Halo Host Runtime Snapshot稀疏不可变运行时快照3.1 快照的语义与组成规范要求 Halo 发布稀疏、不可变的运行时快照snapshot记录某个 Halo 基线baseline实际供应的共享运行时事实但不得声称一个受支持的 Provider 依赖范围。快照中的关键字段包括精确解析的宿主版本exact resolved host version如vue的3.5.41各共享包根的实际包级运行时导出package-root runtime exports供运行时桥接使用的runtime描述bridge桥名称、global全局名、identitysingleton或shared。仓库中真实的快照文件为 runtime-snapshots/halo-2.26.0.json以haloVersion: 2.26.0为基线记录了 10 个共享包根的事实共享包根快照中的精确版本runtime.identityvue3.5.41singletonvue-router5.1.0singletonpinia4.0.3singletonaxios1.16.1sharedformkit/vue2.1.2singletonformkit/core2.1.2singletonhalo-dev/ui-shared2.26.0sharedhalo-dev/components2.26.0sharedhalo-dev/api-client2.26.0sharedhalo-dev/richtext-editor2.26.0shared快照同时记录了每个包根的实际导出列表例如vue的ref、computed、createApp、h等全部根级导出halo-dev/components的VButton、VCard、Dialog、Toast等快照中的exports数组必须来自真实浏览器产物并接受校验——不允许保留浏览器产物中并不存在的合成导出对应规范 Scenario Snapshot exports are generated。3.2 共享包根白名单什么能共享、什么不能共享包根白名单定义于 runtime-snapshot.ts 的SHARED_PACKAGE_ROOTS恰好对应规范要求的十个根。快照校验器validateHaloHostRuntimeSnapshot要求快照的packages键集合与白名单逐一精确相等runtime-snapshot.ts 第 58-67 行。同时规范明确不得把 VueUse、Tiptap、ProseMirror、其他 FormKit 子包以及任意第三方依赖暴露为共享运行时 specifier。这与 constants/externals.ts 中 legacy globals 的形态形成对比VueUse 仅为 legacy IIFE 提供window.VueUse兼容全局并标注TODO(Halo 3): Remove after legacy IIFE UI provider support ends.但绝不成为 ESM 共享 specifier——ESM Provider 源码里 import VueUse 时构建工具会将其打进 Provider 自己的产物。3.3 快照的版本选择与复用selectHaloHostRuntimeSnapshot 实现了规范中的两条选择规则为某个 Halo 版本选择最新且基线不晚于当前发布的快照lte(snapshot.haloVersion, target.version)预发布版本prerelease按其稳定核心版本比较快照新旧当目标版本带 prerelease 后缀时若快照的haloVersion与目标的major.minor.patch完全一致也视为合格——避免把同核心的更新快照误判为旧发布。返回值中reusedOlderSnapshot标识当前是否复用了更早的不可变快照对应规范 Scenario Halo release reuses a snapshot只要共享版本事实、根导出、运行时桥行为不变允许复用最新早期快照而不重复发布。若没有任何可用快照函数会抛出错误并提示Updatehalo-dev/ui-plugin-bundler-kitor select IIFE output。3.4 快照从实际解析而非声明生成规范要求快照记录实际 Halo UI 构建解析得到的版本而不是声明范围、peer 后缀、workspace 协议或 link 协议。resolveSharedPackageruntime-snapshot.ts 第 113-148 行通过resolvePackageJSON按[browser, import, default]条件解析包根校验包名与版本存在后返回实际解析结果validateResolvedSharedPackage则将其与快照中的宿主版本对比输出两个尽力而为的诊断维度而非自动构建失败newerThanHostProvider 解析版本比宿主新 → 警告differentMajor主版本号不同 → 更强警告。这与规范 Scenario Provider version differs from the snapshot 完全一致差异仅作为诊断上下文报告不构成兼容性证明也不自动拒绝构建。另外规范规定快照生成/校验不必在每个包构建或 CI 任务中自动运行halo-dev/ui-plugin-bundler-kit的包版本用于派生 Halo 基线与带版本的输出路径。四、Host-Owned Shared Dependency Resolution共享依赖解析归宿主4.1 Import Map 先行浏览器端共享依赖解析的核心机制是Import Map。规范要求Console 或 User Center 启动时HaloSHALL在任何消费共享 specifier 的宿主或 Provider 模块被解析之前安装其 Import MapScenario Import Map precedes provider modules。此后 ESM Provider 中import { ref } from vue这类语句会由浏览器解析为当前 Halo 发布提供的运行时 URL。关键边界Provider 提供的 Import Map 或共享 specifier 映射会被宿主忽略或拒绝Scenario Provider attempts to override shared mapping——共享映射的所有权在宿主不在插件/主题。4.2 身份敏感依赖必须真正共享规范强调宿主与 ESM Provider 使用 Vue、Vue Router、Pinia、FormKit Vue、FormKit Core 时必须使用同一个宿主拥有的模块身份与状态Scenario Identity-sensitive dependencies are shared。这对应快照中identity: singleton的语义——例如 Provider 与宿主必须共享同一个 Vue 实例和 Pinia Store 上下文否则provide/inject、useRoute、defineStore会各自为政。FormKit 是一个典型例子Provider 导入formkit/vue或formkit/core时两个根都必须解析到同一个 Halo 构建的 FormKit 模块图Scenario FormKit Vue and Core are imported at runtimenode 查找、表单提交、reset 等操作与宿主观察同一个 Core 注册表即便 Provider 打包了其他保留formkit/core运行时导入的formkit/*私有包该 Core 导入也必须指向宿主拥有的 FormKit 图而不是一份私有 Core 副本Scenario Private FormKit package uses Core。4.3 axios 与 API Client 的分层约定规范对网络层做了精细分层Scenario Provider imports Axios / Provider uses the Halo API clientProvider 导入axios获得 Halo 提供的标准 Axios 模块但不隐式获得halo-dev/api-client内部使用的已配置 Axios 实例Provider 从halo-dev/api-client导入axiosInstance获得单独创建的共享 Halo API 实例自带宿主认证与错误处理普通 Provider 客户端应使用axios.create()创建而不是去修改共享实例的默认配置或拦截器。五、Versioned Provider Descriptor统一的 Provider 描述符5.1 端点与响应结构后端以单个认证响应描述当前全部 UI Provider端点为GET ui-plugins/-/providers见 UiPluginEndpoint.java 第 46-52 行operationId 为fetchUiPluginProviders响应体直接使用UiPluginProviderDescriptor类型。响应结构定义在 UiPluginProviderDescriptor.javaUiPluginProviderDescriptor ├── providers: ListProvider // 有序 Provider 列表每个出现恰好一次 └── legacyScript: String (nullable) // 仅当存在 legacy Provider 时的带目录版本的聚合脚本 URL每个Provider记录的字段为字段说明nameHalo 拥有的 Provider 标识插件名或主题名typeplugin或themeversion已安装版本kindlegacy/esm/invalid三种分类与加载模式entryESM 入口 URLESM Provider 必需style启动样式表 URL可选reason发现失败原因invalidProvider 必需规范还约束该列表是权威的发现、启动样式优先级与注册顺序来源响应不得再暴露单独的目录版本、注册列表、样式表列表、ESM Provider 列表或无效 Provider 列表Scenario Provider descriptor is requested。legacyScript仅在至少一个 Provider 被分类为 legacy 时出现。5.2 描述符的 OpenAPI 与类型客户端消费Halo 生成 OpenAPI 文档与 TypeScript API 客户端时必须包含该端点及其完整响应 schema并保证plugin/theme类型、必需字段在生成的模型中保留Console 与 User Center必须使用生成的 API 方法与模型而不是维护一套手写的平行描述符契约Scenario Provider descriptor is consumed by the Halo UI。从 api-docs/openapi/v3_0/aggregated.json 中可以找到对应的UiPluginV1alpha1ConsoleApi与UiPluginProvider、UiPluginProviderKindEnum、UiPluginProviderTypeEnum等生成模型。5.3 ESM 资源的 URL 映射与缓存键ESM 插件资源入口 URL 使用现有/plugins/{name}/assets/ui/映射或选定的 legacy/assets/console/回退URL 带稳定的插件级缓存键查询参数ESM 主题资源入口 URL 使用/themes/{name}/ui-plugin/assets/映射同样带主题级稳定缓存键不兼容主题当激活主题的状态报告UnsatisfiedRequiresVersion时HaloSHALL在读取或导入其入口之前就将其 UI Provider 分类为invalid并把主题兼容性消息作为reason暴露给描述符Scenario Activated theme is incompatible with Halo。5.4 启动样式与 legacy 聚合样式桥描述符中的样式 URL 遵循直接指向 Provider 自身静态资源的原则样式 URL 挂在所属 Provider 记录上使用 Provider 静态资源映射使相对 CSS 资源能相对其所属 Provider 解析异步 chunk 的 CSS不得出现在 Provider 记录的样式字段中Scenario Startup stylesheets are described。对 Halo 2.x 的 legacy 客户端ui-plugins/-/bundle.css聚合端点仍然保留作为兼容桥它不再把 CSS 源码拼接在聚合 URL 下而是按顺序输出引用各 Provider 直接样式 URL 的 CSSimport规则实现中带有TODO(Halo 3)注释标识将在 legacy IIFE 支持结束后移除UiPluginEndpoint.java 第 53-67 行 中两个 bundle 端点同样带TODO(Halo 3)注释。bundle.js与bundle.css都通过?v查询参数携带目录版本作为缓存键未带版本时临时重定向到带版本的 URL。5.5 启动期间的状态变更描述符响应创建后若插件/主题发生变化Halo不得声称前一响应内容不可变也不得拷贝 Provider 资源支持的恢复边界是整页刷新以获取新版本化的当前描述符Scenario Provider state changes during startup。六、Shared UI Provider Registration Storestores.uiPlugins()6.1 Store 形态与生命周期状态halo-dev/ui-shared导出格式中立的 Provider 可用性与注册元数据 Storestores.uiPlugins()。实现见 ui/packages/shared/src/stores/index.tsUiPluginRegistration{ name, type: plugin | theme, version, status: pending | registered | failed }UiPluginsStoreProvider 可消费的只读接口registrations、get(name)、isEnabled(name)、isRegistered(name)UiPluginsHostStoreinternal宿主加载器专用_seed、_setStatus两个下划线前缀的内部方法。描述符到达后宿主在评估任何 legacy 或 ESM Provider 入口之前先填充 Store有效 Provider 以pending起步被描述符发现阶段即判定无效的 Provider 以failed起步。isEnabled(name)响应式地指示该 UI Provider 是否出现在当前描述符中与 IIFE/ESM 格式无关isRegistered(name)只有在该 Provider 的模块注册在当前页面提交成功后才为true对被发现的 legacy Provider 没有 UI 模块这一兼容场景视为成功的兼容空操作并报告为 registered。消费者不应依赖 Provider 求值或注册顺序Scenario Enabled provider is queried / Registered provider is queried。6.2 只读约束与隔离边界Provider 读取其他 Provider 的记录时只能获得身份、类型、版本与生命周期状态公开 Store不得暴露其他 Provider 的PluginModule、路由、组件或可调用实现Scenario Provider reads another providers record注册集合与宿主生命周期操作被文档化为只读消费客户端侧的变更逃生舱_seed/_setStatus不作为受支持的 API 或安全边界Scenario Provider attempts to mutate registration metadata规范同时提供了对window[providerName]与window.enabledUiPlugins存在性检查的迁移指引文档将引导 Provider 使用共享注册 Store 替代而直接访问其他 Provider 模块实现始终不受支持。Store 消费侧还有两个配套类型definePlugin 提供类型安全的PluginModule定义辅助函数PluginModule 定义了 ESM 入口 default 导出的形状——formkit自定义 FormKit 输入、components全局组件、routes/ucRoutesConsole / 用户中心路由支持RouteRecordRaw[]与追加到既有父路由的RouteRecordAppend[]、extensionPoints扩展点注册如post:list-item:operation:create、dashboard:widgets:create等。七、Mixed Legacy 与 ESM Provider 加载规范要求 legacy IIFE 与 ESM 两类 UI Provider 能在同一个Console / User Center 会话中共存且不需要重建 legacy Provider描述符驱动会话初始化 UI Provider 时返回当前 provider-neutral 描述符包含启用的插件 Provider 与激活的主题 Provider未激活主题不包含Scenario Mixed legacy and ESM provider loadingLegacy 聚合加载存在 legacy Provider 时通过描述符中带目录版本的聚合 bundle 行为加载聚合排除ESM Provider但其 legacy enabled-provider 元数据包含所有有效启用的 Provider无论格式ESM 入口并行加载所有独立入口 import 并行启动以 all-settled 语义等待Provider 能自行加载其相对异步 chunk 与产物资源单个入口 import settle 后不重载页面启动资源全并发多个 Provider 的样式、ESM 入口与 legacy 脚本在等待任何一个 settle 之前全部启动样式元素保持 provider-list 顺序与网络完成顺序无关Halo不得引入会把 Provider 启动串行化的应用级请求批处理稳定初始化顺序即使独立 ESM import 以非确定性顺序 settle接受的 Provider 模块仍按稳定的 Provider 顺序初始化任何 Provider 不得依赖 ESM 求值顺序或直接从另一个 Provider 导入启动样式管理每个 Provider 的启动样式按 provider-list 顺序插入加载样式加载失败只影响其所属 Provider若该 Provider 后续在入口/导出/注册阶段失败则移除该 Provider 启动时插入的样式 link同时保留页面上已存在的同名匹配样式异步 chunk 的 CSS 由 bundler 运行时按需从 Provider 静态资源映射加载不会急切进入启动聚合。八、ESM Provider 失败隔离8.1 发现、导入与求值阶段的隔离单个 ESM Provider 入口在 fetch、link、evaluate 或导出合法PluginModule阶段失败时跳过该 Provider、继续加载并初始化其他有效 Provider、继续核心 Console / User Center 启动Scenario One ESM entry fails。Provider 的spec.requires与当前 Halo 版本不兼容时在导入其入口之前即拒绝拒绝信息需标识 Provider、其要求的 Halo 范围与当前 Halo 版本。多个 Provider 在一次启动中失败时向用户呈现单一汇总通知同时为日志与管理 UI 保留 provider 级结构化诊断。8.2 注册事务的回滚语义Provider 注册路由、组件、Store、扩展点等宿主集成失败时Scenario Provider registration fails synchronously对支持撤销的变更按逆序调用记录的移除/恢复句柄被失败 Provider 替换的命名路由恢复到先前注册的路由Halo 管理的匿名父路由具有内部身份允许恢复被替换的具名子路由在无法识别的匿名父路由下已注册的路由在替换成功时保留 legacy last-registration-wins 行为若替换成功但后续事务失败且无法可靠恢复诊断为不完整路由回滚并要求页面重载而不是在变更前就拒绝该 Provider继续注册后续 Provider任何无法逆转的变更都需诊断并以页面重载作为最终恢复边界FormKit 输入只从注册已成功提交的 Provider 收集。8.3 启动后的懒路由 chunk 失败已接受 Provider 的路由或异步组件 chunk 在启动后失败时通过路由/组件错误处理将错误归因到该 Provider尽可能展示 provider 级失败状态而不禁用无关路由或 Provider嵌套异步组件错误从其组件实例父链继承 Provider 归属已解析的懒路由在解析组件不再匹配注册加载器时回退到活动匹配路由的 Provider 归属成功注册 Provider 的启动样式予以保留普通后代渲染或事件错误不得被重新归类为 Provider chunk 加载失败。此外若路由使用 Vue Router 认可的函数式组件则保留原组件而非包装成异步路由加载器Provider 注册与 Halo 核心组件同名的全局组件时保留核心组件与 FormKit 设置完成后的 legacy last-registration-wins 优先级Scenario Provider registers a functional route component / Provider overrides a same-named global component。8.4 非事务性副作用Provider 求值产生顶层副作用、定时器、事件监听或宿主注册表之外的异步工作Halo不得声称可回滚可观察的失败以完整页面重载作为恢复边界进行归因与诊断。九、Legacy UI Provider 兼容协议Halo 2.xHalo 2.x 全程保留既有 IIFE UI Provider 协议现有 IIFE 插件在spec.requires接受当前 Halo 版本时无需重建或新增 manifest即可加载保留既有 bundle 端点、全局模块注册、共享全局名、enabled-provider 元数据与ui到console资源回退Scenario Existing plugin artifact runs on a new Halo 2.x release仅提供 legacy 主样式表、无 UI 脚本的激活主题仍保留在enabledUiPlugins兼容元数据中提供既有 IIFE UI 模块的主题继续走 legacy 聚合与全局模块协议legacy 共享依赖升级时发布前运行冻结的 legacy fixtures 与维护的生态使用样例保留已知使用的导出或添加聚焦的兼容行为上游行为兼容性对每个 Provider 而言是尽力而为而非保证window.VueUse兼容全局在 Halo 2.x 保留但该兼容行为不使 VueUse 成为 ESM 共享 specifier所有仅为保留 IIFE Provider 全局、元数据全局、聚合别名、资源回退、bundler 全局映射或全局支持的 ESM 桥而存在的代码源码须带TODO(Halo 3)注释并在适用处使用语言的弃用标记可对照 externals.ts 与 UiPluginEndpoint.java 中的TODO(Halo 3)注释实例。十、UI Provider 生命周期与缓存边界模块替换边界完整的 Console / User Center 页面加载是受支持的模块替换边界插件/主题在页面模块图启动后变更时Halo要求或提示完整页面重载不做运行中 Provider 模块的热卸载或热替换Scenario Provider is installed, upgraded, enabled, disabled, or activated生产资源缓存默认 preset 产出的 ESM 资源未覆盖 bundler-kit 资源命名默认值时的入口与启动样式文件名包含内容派生哈希描述符 URL 使用 manifest 选择的 provider 相对路径不追加查询缓存键异步 chunk 与资源使用 provider 相对的内容哈希 URLlegacy 聚合 URL 带当前目录版本缓存键Provider 发现元数据被重新验证以反映当前启用的 Providerchunk 与入口同 URL异步 chunk 静态导入 Provider 入口的绑定binding时chunk 引用与描述符入口解析到同一规范 URL——浏览器不得因为 Halo 追加查询缓存键而二次 fetch 或二次求值同一入口Scenario A provider chunk imports the provider entry自定义命名覆盖调用方 bundler 配置或 hooks 以稳定或自定义文件名产出 ESM 入口、启动样式、异步 chunk 时Halo不改写这些资源、也不追加缓存键覆盖资源的缓存失效由 Provider 开发者负责开发资源缓存开发场景下直接加载的构建输出未变化时manifest 选择的入口与启动样式 URL 保持不变manifest、入口或启动样式变化时内容哈希的启动文件名与目录版本随之变化而其他未变化 Provider 保留原有直接资源 URL。十一、开发拓扑与打包拓扑的运行时对等性规范要求 ESM UI Provider 在代理开发拓扑与打包生产拓扑下行为一致开发拓扑开发者通过 Halo 开发服务器打开 Console/User Center 路由、UI 开发服务器独立运行时代理返回的 HTML 在模块入口之前包含开发 Import MapHalo UI 运行时模块从 UI 开发服务器加载而 API 与插件/主题 Provider 资源继续从 Halo 后端加载深层嵌套路由deep route下代理的入口、Import Map、共享运行时模块、Provider 入口与 chunk 都能正确解析不依赖UI 开发服务器作为文档源document origin生产拓扑Halo 以构建产物运行时打包的 Console / User Center HTML 将共享依赖映射到打包的内容哈希运行时资源所有宿主与 Provider 运行时资源在没有开发服务器 URL的情况下加载。十二、测试与进一步阅读规范的构建期行为在 bundler-kit 的测试中得到验证可结合以下文件深入provider-manifest.spec.ts清单校验与路径逃逸拒绝的用例runtime-snapshot.spec.ts快照校验、版本选择含 prerelease 比较与复用逻辑shared-dependencies.spec.ts共享依赖解析与版本差异诊断stores/index.spec.ts共享 Store 的isEnabled/isRegistered生命周期行为。相关规范文件还包括 ui-plugin-bundler-provider specProvider 构建与打包约定以及归档中的演进记录 support-esm-ui-plugins 与 simplify-esm-ui-provider-presets。小结围绕ui-plugin-esm-runtime规范Halo 2.x 构建了一整套构建期生成与校验 运行期宿主托管的 ESM UI Provider 体系ui-plugin.json清单约束了 Provider 的产物形状与路径安全宿主运行时快照以不可变、稀疏、源自实际解析的方式记录共享事实Import Map 与identity: singleton语义保证身份敏感依赖真正共享版本化描述符ui-plugins/-/providers成为唯一的发现与注册顺序权威stores.uiPlugins()为 Provider 间提供只读的注册互查混合加载、失败隔离与整页刷新缓存边界则保障了插件生态的健壮性同时以TODO(Halo 3)标记为 legacy IIFE 协议保留了一条清晰的退出路径。【免费下载链接】haloHalo 是一款强大易用的开源建站工具从个人博客、知识库到企业官网、在线商城Halo 都能助您轻松实现一站式满足您的多样化建站需求。项目地址: https://gitcode.com/GitHub_Trending/ha/halo创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表