PostProcessBuilder仅触发一次的原因及持续运行解决方案
问题:PostProcessBuilder仅首次构建时触发,无法随主Builder每次运行
我的实现代码
1. MoveBuilder 类实现
class MoveBuilder extends PostProcessBuilder { @override Iterable<String> get inputExtensions => ['.g.dart']; MoveModelBuilder() ; @override Future<void> build(PostProcessBuildStep buildStep) async { log.info('MOVE THE FILE'); } }
2. 顶层工厂函数
PostProcessBuilder moveSomething(BuilderOptions options) { return MoveModelBuilder(); }
3. 生成器包的 build.yaml 配置
builders: my_builder: import: "package:my_package/src/builders/builders.dart" builder_factories: ["buildSomething"] build_extensions: {'.dart': ['.g.dart']} auto_apply: none build_to: source applies_builders: - my_package|move_builder post_process_builders: move_builder: import: "package:my_package/src/builders/builders.dart" builder_factory: moveSomething
4. 使用生成器的外部包 build.yaml 配置
targets: $default: builders: my_package|my_builder: enabled: true generate_for: - lib/*/input_folder/*.dart my_package|move_builder: enabled: true generate_for: - lib/*/relative_output_folder/*.g.dart
问题现象
仅首次运行build_runner命令时MoveBuilder会被触发,且仅在出现「缓存资产图已重置」的警告后才会触发。需要让它每次在主Builder运行完成后都执行。
解决方案
核心问题分析
- 缓存机制限制:PostProcessBuilder默认仅在输入资产(这里是
.g.dart文件)内容变更时触发。主Builder生成.g.dart后,若内容无变化,构建缓存会判定资产未修改,不会触发后续的PostProcessBuilder。 - 配置冲突:外部包中直接启用
move_builder并指定generate_for为目标路径的.g.dart,但主Builder生成的文件实际在输入路径下,导致PostProcessBuilder无法正确追踪资产的生成事件。
修复步骤
移除外部包中对
move_builder的单独配置
主Builder已经通过applies_builders声明了对move_builder的依赖,外部包无需重复启用,否则会干扰构建依赖链。修改外部包的build.yaml:targets: $default: builders: my_package|my_builder: enabled: true generate_for: - lib/*/input_folder/*.dart强制触发PostProcessBuilder(临时方案)
如果必须使用PostProcessBuilder,可以在build方法中标记输入资产为已修改,强制构建系统下次运行时重新处理:@override Future<void> build(PostProcessBuildStep buildStep) async { log.info('MOVE THE FILE'); // 标记资产为已修改,打破缓存 await buildStep.canRead(buildStep.inputId); buildStep.inputId.changeState(AssetState.modified); }注意:这种方式会跳过缓存优化,可能降低构建效率。
最佳实践:不要用PostProcessBuilder移动文件
Dart Build系统官方推荐通过构建扩展的捕获组直接指定输出路径,替代事后移动文件的操作,这是更符合构建系统设计的方案。
实现方式
修改主Builder的build_extensions配置,使用捕获组将生成文件直接输出到目标路径:
builders: my_builder: # ... 其他配置 build_extensions: {'lib/*/input_folder/*.dart': ['lib/$1/relative_output_folder/*.g.dart']}
这样主Builder处理lib/x/input_folder/a.dart时,会直接将生成的.g.dart文件输出到lib/x/relative_output_folder/a.g.dart,完全不需要PostProcessBuilder介入。
内容的提问来源于stack exchange,提问作者anonymous-dev
相关产品推荐
相关产品推荐

