多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

Dart 4.0 要彻底移除 dart:mirrors,Augmentations 应该要来了

Dart 4.0 要彻底移除 dart:mirrors,Augmentations 应该要来了 按照目前计划Dart 3.14 会在 2026 年 11 月正式把它标成deprecated然后 Dart 4.0 再完全移除也就是下个版本开始这个 Flutter 用不上的但是一直活跃在 Dart 的历史支持dart:mirrors就要完全退出历史舞台了。之前的dart:mirrors其实就是反射的作用程序运行起来以后可以拿到自己的MirrorSystem查相应的 library、class、method、field也可以通过InstanceMirror.invoke()这类 API 按名字调用方法比如服务端框架启动时扫描所有带路由 annotation 的方法再自动把它们注册到 HTTP Router序列化、对象映射、测试发现也可以在运行时枚举程序结构不需要提前生成代码但是在 Dart 2.0 开始 Web 编译器就不再支持dart:mirrors了而且 Flutter 很早前也不支持这个能力不然也不会至今都没有 内置 Json 序列化的原生能力。其实理解 mirrors 为什么和目前的 Dart 设计冲突用一个 HTTP Router 就很直观比如服务器启动时扫描所有 class找到带Route(/users)的方法然后运行时按方法名调用它这样对开发者来说确实很省事因为增加一个 handler 只需要写方法和 annotation但是对 AOT 编译器来说未来究竟会通过字符串访问哪些成员就很难确定只要编译器证明不了某个方法永远不会被反射访问那它就不能放心删除这个方法还可能需要保留类名、成员名、annotation、参数等 metadata这样就直接削弱了 tree shakingDart 的 AOT、Web 和 Wasm 编译都希望在编译期尽量建立完整的可达关系甚至 FFI 都要 tree shaking 但是 runtime reflection 会把一部分「谁会被调用」的决定留到了程序运行以后不是说做不了毕竟也有其他语言做到了只是说这么做的成本比较高所以编译器为了保证语义只能更加保守。毕竟只要 AOT 上了这一点要做好还是挺麻烦的比如 Kotlin 离开了 JVM生态后也是Kotlin/JVMKotlin/Native运行环境JVM直接编译成本地二进制编译方式JVM bytecode运行时由 JVM/JIT 执行LLVM AOT 为主不需要 JVM完整kotlin-reflect支持不支持 JVM 那套完整能力KClass.members支持不支持枚举 class 全部 methods/properties支持很有限Java Reflection支持没有 JVM自然没有::class/KClass支持支持但信息少很多函数/属性引用支持支持Native binary shrinking/AOT不是 JVM 传统强项是核心设计之一KClass本身是 Common APINative 也有所以你可以写obj::class、取simpleName、qualifiedName、做类型判断但是像KClass.members、nestedClasses、sealedSubclasses、supertypes这些真正开始“遍历一个类结构”的能力官方 API 目前直接标的是 JVM only。不过这次删除dart:mirrors其实也是 Dart 把坚持多年的工程方向正式固定下来动态发现尽量放在编译期或者代码生成阶段运行时执行已经显式化的调用关系现在官方自己的build_runner文档甚至已经直接把 Dart build system 作为 reflection 和 macros 的替代方案。目前来看这个对 Flutter 来说基本无感甚至可能还会是好事因为这说明 Augmentations 要来了反正之前也都不给用但是对于 Tooling 或者 Plugin 的开发说不准就得适配一次了比如一些纯 Dart Server、CLI、测试框架和内部工具尤其是直接依赖import dart:mirrors的项目。Dart SDK 自己现在就在迁移package:test_reflective_loader之前它也靠dart:mirrors做自动发现reflectiveTest方法现在官方也在转 CFE 在编译阶段直接把这些测试方法降成普通 constructor tear-off / method tear-off目的是保留“新增 test 方法直接dart test”的体验同时彻底移除 runtime mirrors而且不要求用户跑 build_runner。不过如果 Augmentations 能力能全面发布的话应该可以改善目前 generated code 和原声明之间的关系因为很多项目用dart:mirrors其实也不是真的需要“运行时随便反射一切”大家可能只是为了解决一些更具体的问题比如“我写了一个类能不能自动根据这个类的声明再补出一批重复代码”这也 Augmentations 能补掉相当一部分 mirrors 使用场景的原因比如最典型的 JSON 序列化以前用 mirrors 可以在运行时拿到User的字段列表看到name、age然后动态读取而 Augmentations 的思路完全反过来比如开发者写JsonSerializable() class User { final String name; final int age; }然后构建阶段 generator/analyzer 已经能看到User的结构于是生成的代码可以直接“补进”这个 classaugment class User { MapString, Object? toJson() { name: name, age: age, }; }也就是不需要运行时已经没有“检查 User 有哪些字段”这一步了name、age、toJson()全部可以在编译时变成正常 Dart 代码AOT 编译器可以理清楚关系该 tree-shake 什么也可以正常判断。这也是 Augmentations 目前设计的核心能力一个 declaration 可以分散到多个位置augmentation 可以给已有 class 增加成员、给函数补 body、增加 top-level declaration、给 enum 增加值等等。所以 11 月新版本 Flutter 和 Dart 要来了然后明年 4 版本也要来了。
返回列表