Skip to main content

hot_patch_generator 0.1.0 copy "hot_patch_generator: ^0.1.0" to clipboard
hot_patch_generator: ^0.1.0 copied to clipboard

读取 @PatchEntry注解,把 Flutter widget 静态翻译为与源文件同名的 JS 模块(包级 widget 工厂 + 组件类),供 hot_patch 运行时热更渲染。

hot_patch_generator #

构建期把带 @PatchEntry 注解的 Flutter widget 静态翻译为 JS 模块, 供 hot_patch 运行时热更渲染。

全程使用 analyzer 静态解析源码,不执行任何 Dart 代码,也不要求组件做任何改造: 被翻译的类始终是一个完全正常的 Flutter widget。

安装 #

dev_dependencies:
  hot_patch_generator: ^0.1.0
  build_runner: ^2.4.13

然后在项目根目录运行:

dart run build_runner build --delete-conflicting-outputs

产物 #

产物目录 patch/ 与 lib/ 源码路径一一对应,文件名与 Dart 源文件同名:

源码 产物 说明
lib/components/counter.dart patch/components/counter.js 含 @PatchEntry 的组件产物
lib/model/user.dart patch/model/user.js 普通类 / 静态单例(export class / export const)
(包根伪资产 $package$) patch/flutter.js、patch/provider.js 每个 package 一个文件的 widget 工厂模块
(包根伪资产 $package$) patch/manifest.json patch 清单:基本信息 + 打包时间 + 各 JS 资源的内容 hash
  • 按文件内容分流(与目录无关):含 @PatchEntry → 组件产物;仅含普通类 (非私有、非抽象、非组件)→ 模型/单例产物;都没有 → 不产出。
  • package 级模块(patch/<package>.js)与清单都挂在包根伪资产 $package$ 下: 输入是整包、输出路径静态,使用方无需任何种子文件或配置——依赖本包并跑 build_runner 即可产出。
  • patch/flutter.js 内含共享结点工厂 __h 与全部 flutter widget 工厂; 其它包模块与组件产物统一从它 import { __h }。

注意:Flutter 的目录 asset 声明不递归,需在 pubspec.yaml 的 assets: 里逐目录(或逐文件)显式声明产物路径。

配置 #

ui_widget(package 模块)与 patch_entry(组件/模型产物)不读任何 options。 其余两个 builder 的选项均为可选,缺省即开箱可用:

targets:
  $default:
    builders:
      # 宿主注入注册产物(lib/generated/host_methods.dart)的目标运行时;
      # 仅当换用别的运行时实现时才需要覆盖。
      hot_patch_generator:ui_host_register:
        options:
          register_import: "package:<runtime>/<runtime>.dart"
          register_call: "<Runtime>.registerHostMethod"
      # patch/manifest.json 里的基本信息;缺省取包名 / 省略版本。
      hot_patch_generator:ui_patch_manifest:
        options:
          name: my_app
          version: 1.2.3

翻译设计原则 #

翻译产物必须与 Dart 源码一比一对应,这是本框架的核心约束:

  1. Dart 合法写法都要静态翻译支持。遇到不认识的语法形态,补正式翻译分支(在 dart2js.dart 的表达式/语句/类渲染等统一翻译路径上一比一映射成等价 JS),不降级、不兜底成通用节点、不让用户改 Dart 写法来适配框架。所有翻译只有一处实现,组件与普通类共用。
  2. 禁止临时方案。报错时不得在 demo 里加临时字段/中间层绕过(如为规避 setState 无 diff 而加的镜像触发字段);产物 JS 应与 Dart 写法逐行对应,修就修翻译路径本身。
  3. 能力按文件隔离。新增运行时能力(如 ScrollController / TextEditingController id-bridge)时,宿主侧按能力放 hot_patch/lib/src/js_ui/capabilities/ 独立文件,不动 js_widget_registry / js_ui_widget 核心;JS 运行时片段按能力拆命名字符串、由 runtime_source.dart 拼接。
  4. 默认值与 Flutter 百分百一致。宿主渲染时 nullable 属性缺省保持 null,不得默认成 0 / EdgeInsets.zero 等覆盖 Flutter 主题默认。
  5. 注册 key 与类名一致。宿主 r.register('X', ...) 的 key 与产物 JS 里的 type 字符串保持同名,不另起别名。

扩展:新增 widget 支持 #

「某个 widget 怎么翻译成 JS」是策略,由 WidgetTranslator 实现:

class MyWidgetTranslator extends WidgetTranslator {
  const MyWidgetTranslator();

  @override
  Set<String> get types => {'MyWidget'};

  @override
  Map<String, Object?> toJson(Expression e, WidgetTranslateContext ctx) { ... }
}

在 WidgetTranslatorRegistry 里 register 即可,核心代码零改动。 内置策略见 lib/src/translator/builtin_translators.dart (Column / Row / Text / Scaffold / provider 系列等)。

代码结构 #

本包按功能分目录组织(lib/src/ 下),依赖单向无环:

目录 / 文件 作用
lib/builder.dart 对外入口:build.yaml 的四个 builder 工厂函数
lib/src/translator/ 翻译内核:Dart AST → JS(唯一入口 translateClass)
lib/src/builders/ build_runner Builder 实现与产物组装
translator/  ←  builders/  ←  builder.dart

lib/src/translator/:js_translator(公共语言层)· dart2js(类声明)· widget2js(widget 树)· class_translator(唯一入口)· source_index(注解识别 / import 源文件解析)· host_injected(@HostInjected 通道表,翻译层自扫)· style_translators · builtin_translators(内置 widget 策略)。

lib/src/builders/ 按 builder 再分目录:

  • patch_entry/:component_builder(收集本文件根类并统一调 translateClass,并把结果拼装为同名 JS 产物)· class_table · singleton_support
  • ui_widget/:widget_module_builder(package 模块产物 + 各逻辑 组件/sliver 代理的 JS 类源码,仅本 builder 使用)
  • ui_host_register/:host_register_builder(宿主侧注册清单生成; @HostInjected 的识别口径在 translator/host_injected.dart)
  • ui_patch_manifest/:patch_manifest_builder(产出 patch/manifest.json; 靠 required_inputs: [".js"] 排到 patch_entry / ui_widget 之后的阶段, 用 findAssets('patch/**.js') 列出全部 JS 产物逐个算 hash)
  • 根下为各 builder 共用的产物基础:product_path · js_widget_defs(nodeHelperPackage / packageModulePath / 有 JS 类的 widget 类型集合)

框架的其它包:

包 作用
hot_patch_annotations 声明式注解
hot_patch_generator 本包:build.yaml + 工厂入口 + 翻译/构建实现
hot_patch 运行时加载 JS 补丁渲染组件,由 JS 驱动逻辑

使用方只需在 dev_dependencies 里依赖 hot_patch_generator。

License #

MIT

1
likes
0
points
204
downloads

Publisher

unverified uploader

Weekly Downloads

读取 @PatchEntry注解,把 Flutter widget 静态翻译为与源文件同名的 JS 模块(包级 widget 工厂 + 组件类),供 hot_patch 运行时热更渲染。

Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

analyzer, build, crypto, glob

More

Packages that depend on hot_patch_generator