云原生开发工具运维【免费下载链接】freelensFree IDE for Kubernetes项目地址https://gitcode.com/gh_mirrors/fr/freelens点击查看免费下载导读freelensapp/application是 FreelensFree IDE for Kubernetes仓库中负责创建并启动 Lens 类应用的基础技术包。本文围绕该包的官方 README 展开系统讲解其安装方式、最小启动示例、startApplicationInjectionToken的底层实现以及beforeApplicationIsLoading、onLoadOfApplication、afterApplicationIsLoaded三个扩展时隙Timeslot的注册与执行顺序。读完本文你将能独立编写一个基于 DI 容器启动的应用入口并把任意初始化逻辑以 Runnable 形式挂载到正确的启动阶段。包定位应用启动的骨架层freelensapp/application位于packages/technical-features/application/application/其包描述为 Package for creating Freelens applications即它不依赖 Electron 具体 API只提供一套与运行时无关的应用启动骨架。真正的 Electron 主进程适配则由同目录的freelensapp/application-for-electron-main负责见后文Electron 场景扩展。从包结构看该包非常精简只有约 10 个源文件见 src 目录src/feature.ts定义applicationFeature通过getFeature封装注册逻辑src/register-injectables.ts显式注册包内所有 injectable自动生成文件src/start-application/start-application.injectable.ts核心实现提供startApplicationInjectionTokensrc/start-application/time-slots.ts三个扩展时隙注入令牌src/environment-token.ts与src/application-information-token.no-coverage.ts配套的构建环境与应用信息令牌src/start-application/starting-of-application.test.ts启动顺序的单元测试。顶层 index.ts 对外导出applicationFeature、startApplicationInjectionToken、lensBuildEnvironmentInjectionToken、applicationInformationToken及三个时隙令牌并导出StartApplication、ApplicationInformation两个类型。快速上手安装与最小启动示例安装README 给出的安装命令基于 npmnpm install freelensapp/application-for-electron-main值得注意的是README 的示例安装的是application-for-electron-mainElectron 主进程适配包而在本仓库的pnpm-workspace.yaml工作区中两者均为私有 workspace 包private: true通过workspace:^相互依赖见 package.json。如果你是仓库内部开发者可以直接用pnpm依赖本地 workspace 版本发布到 npm 后则使用上述npm install命令。最小启动代码README 给出了一个完整的、不依赖任何框架的最小启动示例import { applicationFeature, startApplicationInjectionToken } from freelensapp/application; import { registerFeature } from freelensapp/feature-core; import { createContainer } from ogre-tools/injectable; const di createContainer(some-container); registerFeature(di, applicationFeature); const startApplication di.inject(startApplicationInjectionToken); startApplication();这段代码的每一步都有明确职责创建 DI 容器createContainer(some-container)来自ogre-tools/injectable容器名字符串用于调试与依赖图区分注册特性registerFeature(di, applicationFeature)会把包内所有 injectable 注入容器。在 Freelens 的 feature-core 体系中feature 之间还可声明dependencies确保依赖先注册见feature.ts的getFeature({ id: application, register, dependencies })模式解析启动函数di.inject(startApplicationInjectionToken)按令牌拿到StartApplication类型() Promisevoid的实现执行启动startApplication()返回 Promise内部按顺序触发三个阶段。启动原理startApplicationInjectionToken 的实现剖析README 对startApplicationInjectionToken的描述是Starts the application and calls timeslots in specified order.启动应用并按指定顺序调用各时隙。其真实实现位于 start-application.injectable.tsconst startApplicationInjectable getInjectable({ id: start-application, instantiate: (di): StartApplication { const runManyAsync runManyFor(di); const beforeApplicationIsLoading runManyAsync(timeSlots.beforeApplicationIsLoadingInjectionToken); const onLoadOfApplication runManyAsync(timeSlots.onLoadOfApplicationInjectionToken); const afterApplicationIsLoaded runManyAsync(timeSlots.afterApplicationIsLoadedInjectionToken); return async () { await beforeApplicationIsLoading(); await onLoadOfApplication(); await afterApplicationIsLoaded(); }; }, injectionToken: startApplicationInjectionToken, });从中可以看到三个关键点令牌即接口startApplicationInjectionToken由getInjectionTokenStartApplication({ id: start-application-injection-token })定义injectable 通过injectionToken字段将自己绑定到该令牌。在ogre-tools/injectable的约定下可以有且仅有一个实现绑定在注入令牌上runMany 负责并发编排每个时隙都先用runManyFor(di)包装成执行该时隙下所有 Runnable的函数而不是手写 for 循环遍历严格串行三个时隙通过await顺序推进——前一个时隙所有 Runnable 全部完成后才开始下一个时隙。这与测试starting-of-application.test.ts中 before → on load → after 的断言完全吻合。runManyFor来自 packages/utility-features/run-many它会用di.injectManyWithMeta(injectionToken)收集该令牌下注册的全部 Runnable先通过verifyRunnablesAreDAG校验依赖成环情况再用Promise.all并发执行——同一时隙内部的 Runnable 是并行的但runAfter声明的依赖会形成执行屏障保证父 Runnable 先跑完子 Runnable 再跑。扩展机制三个 Timeslot 时隙这是 README 的Extendability部分也是该包最核心的扩展点。README 原文列出了三个时隙令牌beforeApplicationIsLoadingInjectionTokenonLoadOfApplicationInjectionTokenafterApplicationIsLoadedInjectionToken它们的定义在 time-slots.tsexport const beforeApplicationIsLoadingInjectionToken getInjectionTokenRunnable({ id: before-application-is-loading-injection-token, }); export const onLoadOfApplicationInjectionToken getInjectionTokenRunnable({ id: on-load-of-application, }); export const afterApplicationIsLoadedInjectionToken getInjectionTokenRunnable({ id: after-application-is-loaded-injection-token, });Runnable 契约每个时隙的注册单元必须是Runnable类型其契约定义在 run-many 的 types.tsexport interface RunnableT void { id?: never; run: RunT; readonly runAfter?: SingleOrManyInjectableRunnableT, RunnableT, void; }即一个 Runnable 必须提供run(parameter)方法可选地通过runAfter声明依赖的其他 injectable形成有向无环图DAG来控制同一时隙内的相对执行顺序。默认情况下同一时隙内各 Runnable 由Promise.all并发执行只有声明了runAfter才会被阻塞等待。挂载一个自定义 Runnable结合starting-of-application.test.ts的写法测试源码在任意 feature 中注册自定义初始化逻辑的标准姿势如下import { getInjectable } from ogre-tools/injectable; import { beforeApplicationIsLoadingInjectionToken } from freelensapp/application; const myInitInjectable getInjectable({ id: my-init-before-loading, instantiate: () ({ run: async () { // 在应用真正加载前执行初始化日志、准备目录、注入环境变量等 }, }), injectionToken: beforeApplicationIsLoadingInjectionToken, });随后把该 injectable 注册进容器例如在 feature 的register(di)里di.register(myInitInjectable)或在registerInjectables的di.register(...)列表中登记。启动时startApplication()会自动收集并执行它。三个阶段的语义按 README 与实现可对三个时隙做如下定位时隙令牌语义典型用途结合仓库代码推断beforeApplicationIsLoadingInjectionToken应用开始加载前建立全局副作用、初始化基础设施、安装扩展 API 等前置工作onLoadOfApplicationInjectionToken应用加载过程中加载核心模块、注册路由与页面等进行中工作afterApplicationIsLoadedInjectionToken应用加载完成后收尾、订阅、启动后续异步任务等后置工作注意三个时隙整体是严格串行的——只有beforeApplicationIsLoading下所有 Runnable resolve 后才会进入onLoadOfApplication依此类推。该行为有测试直接背书见 starting-of-application.test.ts测试断言在 before 阶段未 resolve 前不会调用 on-load 阶段且在 after 阶段未 resolve 前startApplication()返回的 Promise 不会 fulfilled。时序验证测试如何证明顺序starting-of-application.test.ts使用async-fn/vitest的AsyncFnMock精确控制每个阶段何时 resolve从而验证调用startApplication()后立即触发beforeApplicationIsLoading阶段的 Runnable手动await beforeApplicationIsLoadingMock.resolve()后才触发onLoadOfApplication阶段的 Runnable再 resolve 后才触发afterApplicationIsLoaded阶段的 Runnable此时startApplication()的 Promise仍未 resolve只有当 after 阶段的 mock 也 resolve整个startApplication()才 fulfilled。这套分阶段 resolve 检查 Promise 状态的写法把异步时序变成了可精确断言的测试也印证了 README calls timeslots in specified order 的描述。Electron 场景扩展application-for-electron-mainREADME 的安装示例指向freelensapp/application-for-electron-main它是本包在 Electron 主进程上的装饰层位于 packages/technical-features/application/application-for-electron-main。其关键机制start-electron-application.injectable.ts是通过instantiationDecoratorToken.for(startApplicationInjectionToken)对基础包的启动函数做装饰器式增强在原始三时隙之外又插入了两个同步时隙beforeAnythingInjectionToken最早执行先于一切 Electron 相关初始化beforeElectronIsReadyInjectionToken等待 Electron ready 前的同步准备。整体执行顺序变为beforeAnything同步 → beforeElectronIsReady同步 → electronApp.whenReady()异步等待见 when-app-is-ready.injectable.ts → beforeApplicationIsLoading异步 → onLoadOfApplication异步 → afterApplicationIsLoaded异步该顺序同样有集成测试背书starting-of-electron-main-application.test.ts断言在 Electron ready 之前不会提前调用beforeApplicationIsLoading阶段的 Runnable。真实应用Freelens 主进程与渲染进程的入口该包不是玩具代码——Freelens 自身的两个进程入口都在实际使用它。主进程入口freelens/src/main/index.tsregisterFeature( di, loggerFeature, prometheusFeature, applicationFeature, applicationFeatureForElectronMain, messagingFeatureForMain, randomFeature, kubeApiSpecificsFeature, ); // ... const startApplication di.inject(startApplicationInjectionToken); startApplication().catch((error) { console.error(error); process.exit(1); });这里applicationFeature与applicationFeatureForElectronMain同时注册主进程通过startApplication()驱动整个 Electron 应用的启动并将启动失败映射为退出码 1。渲染进程入口freelens/src/renderer/index.ts 同样注册applicationFeature并注入startApplicationInjectionToken后调用startApplication()配合reactApplicationFeature、routingFeature等特性完成 UI 框架的装载。也就是说同一个启动骨架同时服务于 main 与 renderer 两个进程这正是该包与运行时解耦设计的价值所在。配套令牌构建环境与应用信息除了启动机制包内还导出了两个配套令牌供各功能模块消费lensBuildEnvironmentInjectionTokenenvironment-token.ts类型为string的注入令牌标识构建环境applicationInformationTokenapplication-information-token.no-coverage.ts类型为ApplicationInformation的结构化令牌包含name、version、productName、copyright、description、k8sProxyVersion、bundledKubectlVersion、bundledHelmVersion、contentSecurityPolicy、welcomeRoute、updatingIsEnabled、dependencies等字段用于向各功能如版本展示、CSP 配置、更新开关提供统一的应用元信息。这两个令牌同样在容器创建后由各 feature 按需注入与应用启动流程一起构成 Freelens 应用生命周期的基础设施。小结一套可复用的应用启动骨架freelensapp/application的核心价值可以浓缩为一句话用 DI 注入令牌 Runnable 时隙把启动应用这件全局性的事拆解成可注册、可排序、可测试的扩展点。无论你是想在 Freelens 的 main 或 renderer 进程里挂载自定义初始化逻辑还是要基于同样模式搭建自己的 Electron 应用都可以按注册 feature → 定义带注入令牌的 Runnable → 交给startApplication按序执行三步完成。仓库中的源码start-application.injectable.ts、time-slots.ts与测试starting-of-application.test.ts共同构成了对该机制最精确的可执行文档。赞分享云原生开发工具运维【免费下载链接】freelensFree IDE for Kubernetes项目地址https://gitcode.com/gh_mirrors/fr/freelens点击查看免费下载相关推荐FreeLens 主进程启动框架freelensapp/application-for-electron-main 的 Feature 扩展与启动时序解析FreeLens 主进程启动框架freelensapp/application for electron main 的 Feature 扩展与启动时序解析云原生开发工具运维Egg 框架应用启动自定义基于 app.js 与 beforeStart 的初始化机制深度解析Egg 框架应用启动自定义基于 app.js 与 beforeStart 的初始化机制深度解析 应用启动阶段是 Egg 框架承接外部流量的关键节点框架只有完后端Web框架Claude for Legal终极法律AI助手完全指南10分钟打造你的专属法律工作流Claude for Legal终极法律AI助手完全指南10分钟打造你的专属法律工作流 你是否曾想过如果能有一个了解你工作习惯、熟悉你管辖范围、掌握你团队AI 技能人工智能AI 应用上一篇NVIDIA Profile Inspector终极多语言本地化指南让显卡调校工具全球化下一篇终极指南3步快速实现NVIDIA Profile Inspector多语言界面让全球玩家轻松调校显卡创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考