Flutter for OpenHarmony:mason_cli 拒绝重复劳动,用砖块构建你的代码模板(强大的脚手架生成器) 深度解析与鸿蒙适配指南
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net

前言
作为开发者,我们每天都在做大量的重复劳动:
- 创建一个新页面:StatefulWidget, Bloc, State, Event, View… 哪怕用 snippet 也要敲好几下。
- 新建一个 API 接口:Model, Repository, Service… 哪怕 Ctrl+C/V 也要改好几个地方。
- 项目初始化:配置 lint, CI/CD, 目录结构… 每次新项目都要来一遍。
Mason 不仅仅是一个 CLI 工具,它是一套基于 Mustache 模板引擎的 代码生成生态系统。它允许你将任何代码片段、文件甚至整个项目结构封装成 Brick(砖块)。
当你需要复用时,只需一行命令 mason make my_brick,Mason 就会询问你的变量(如类名、是否需要测试),然后为你铺好砖瓦。
对于 OpenHarmony 开发者,Mason 的价值尤为巨大。鸿蒙项目结构复杂(ets/dart 混合),配置繁多(module.json5)。有了 Mason,你可以一键生成完美的鸿蒙混合工程。
在团队协作或多项目维护时,我们经常需要创建结构相似的文件(如 Bloc, Page, Model)。手动复制粘贴不仅慢,还容易出错(忘记改类名、文件名)。
mason_cli 是 Dart 生态中最流行的模板生成工具。它引入了 “Brick”(砖块)的概念,让你像搭积木一样快速生成包含动态变量的文件结构。它不仅能生成简单的 Widget,还能生成整个 Clean Architecture 项目骨架。
一、核心原理与 Mustache 语法解析
1.1 Brick 结构解剖
一个 Brick 本质上是一个包含 brick.yaml 和 __brick__ 目录的文件夹。
- brick.yaml: 元数据配置(name, version, vars)。
- brick/: 模板文件存放处。这里的文件名和内容均支持变量替换。
# brick.yamlname: feature_brick description: A new Flutter feature with Bloc vars:name:type: string description: The name of the feature (e.g. login) default: my_feature prompt: What is the feature name?use_freezed:type: boolean description: Use freezed for state?default:true1.2 Mustache 模板语法
Mason 使用强大的 Mustache 语法:
- 变量替换:
{{name}}->Login - 变量变换 (Case Conversion):
{{name.pascalCase()}}->LoginFeatures{{name.snakeCase()}}->login_features
- 条件渲染:
{{#use_freezed}} ... {{/use_freezed}} - 文件重命名:
__brick__/{{name.snakeCase()}}_page.dart->login_page.dart
变量 (Vars)
Mustache 数据
Render
Write
用户输入/参数
Mason 引擎
Brick 模板库
生成的代码文件
项目目录

二、核心命令与工作流
2.1 安装与初始化
# 全局安装 dart pub global activate mason_cli # 初始化 workspace mason init 这会在项目根目录生成 mason.yaml,相当于 pubspec.yaml,用于管理引用的 Brick。
2.2 添加 Brick
你可以从本地路径、Git 仓库或官方仓库 BrickHub 添加。
# 从 BrickHub 添加 (官方推荐) mason add hello # 从本地路径添加 mason add my_brick --path ./bricks/my_brick 2.3 生成代码 (Make)
mason make hello --name "OpenHarmony"# 输出: Hello OpenHarmony!三、OpenHarmony 平台适配实战
在鸿蒙项目中,我们经常需要处理特定配置。让我们创建一个 Ohos Module Config Brick。
3.1 创建 Brick
mason new ohos_module 3.2 编写模板
编辑 bricks/ohos_module/__brick__/module.json5:
{ "module": { "name": "{{name.camelCase()}}", "type": "{{type}}", // entry or feature "description": "$string:{{name}}_desc", "mainElement": "{{name.pascalCase()}}Ability", "deviceTypes": [ "{{#support_phone}}phone{{/support_phone}}", "{{#support_tablet}}tablet{{/support_tablet}}" ], "pages": "$profile:main_pages" } } 在 brick.yaml 中定义变量:
vars:name:type: string prompt: Module Name?type:type: enum values:[entry, feature, shared]default: entry support_phone:type: boolean default:truesupport_tablet:type: boolean default:false3.3 使用效果
运行 mason make ohos_module,交互式提问:
? Module Name? (my_module) > login_module ? Module Type? (entry) > feature ? Support Phone? (Y/n) > Y ? Support Tablet? (n/Y) > Y 生成的 module.json5:
{ "module": { "name": "loginModule", "type": "feature", "deviceTypes": [ "phone", "tablet" ], ... } } 这极大地减少了手写 JSON 的错误率,特别是对于不熟悉鸿蒙配置的 Flutter 开发者。
四、进阶技巧:构建 Clean Architecture 生成器
在大型项目中,我们通常遵循 Clean Architecture。如果不使用生成器,每写一个 Feature 都要创建 10+ 个文件。
我们来构建一个 Full Feature Generator。
4.1 目录结构模板
bricks/clean_feature/__brick__/lib/features/{{name.snakeCase()}}/:
- domain/
entities/{{name.snakeCase()}}.dartrepositories/{{name.snakeCase()}}_repo.dart
- data/
models/{{name.snakeCase()}}_model.dartdatasources/{{name.snakeCase()}}_remote_source.dartrepositories/{{name.snakeCase()}}_repo_impl.dart
- presentation/
bloc/{{name.snakeCase()}}_bloc.dartpages/{{name.snakeCase()}}_page.dart
4.2 核心代码模板 (以 Bloc 为例)
__brick__/lib/features/{{name.snakeCase()}}/presentation/bloc/{{name.snakeCase()}}_bloc.dart:
import'package:flutter_bloc/flutter_bloc.dart';import'package:equatable/equatable.dart';part'{{name.snakeCase()}}_event.dart';part'{{name.snakeCase()}}_state.dart';class{{name.pascalCase()}}BlocextendsBloc<{{name.pascalCase()}}Event,{{name.pascalCase()}}State>{{{name.pascalCase()}}Bloc():super({{name.pascalCase()}}Initial()){on<{{name.pascalCase()}}Event>((event, emit){// TODO: implement event handler});}}4.3 钩子脚本 (Hooks)
Mason 支持在生成前后执行 Dart 脚本(pre_gen.dart, post_gen.dart)。
例如,生成完文件后,我们可以自动运行 flutter pub get 或者 build_runner。
bricks/clean_feature/hooks/post_gen.dart:
import'dart:io';import'package:mason/mason.dart';voidrun(HookContext context)async{final progress = context.logger.progress('Running build_runner...');awaitProcess.run('flutter',['pub','run','build_runner','build','--delete-conflicting-outputs']); progress.complete('Done!');}
五、完整演示:从零到一生成登录模块
假设我们需要为一个新的鸿蒙 App 生成登录模块。
- 准备:
mason add clean_feature --path ./bricks/clean_feature - 执行:
mason make clean_feature - 输入:
- Feature Name:
authentication - State Management:
bloc - Use Freezed:
yes
- Feature Name:
几秒钟后,整个 lib/features/authentication 目录生成完毕,包含了 Entity, Model, Repository Interface, Repository Impl, Bloc, Cubit, Page, Unit Tests。甚至连 build_runner 都跑完了,Freezed 文件也生成好了。

六、总结
mason_cli 是 Flutter 工程化的基石。它将团队的最佳实践(项目结构、代码规范、常用模式)固化为可复用的 Brick。
对于 OpenHarmony 团队,如果你们有一套独特的混合开发规范,强烈建议编写一套内部的 Bricks。新人入职后,一行 mason make 就能写出符合规范的代码,再也不用手动 Review 格式问题了。
最佳实践:
- 版本控制:将 Bricks 放入单独的 Git 仓库,通过 git url 引用。
- 细粒度拆分:不要把整个 App 做成一个 Brick。拆分成
page_brick,model_brick,repo_brick,组合使用更灵活。 - BrickHub:多去 brickhub.dev 逛逛,那里有全世界开发者贡献的优质 Brick(如
clean_architecture,api_service)。