欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.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.yaml
name: 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: true

1.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: true
  support_tablet:
    type: boolean
    default: false

3.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()}}.dart
    • repositories/{{name.snakeCase()}}_repo.dart
  • data/
    • models/{{name.snakeCase()}}_model.dart
    • datasources/{{name.snakeCase()}}_remote_source.dart
    • repositories/{{name.snakeCase()}}_repo_impl.dart
  • presentation/
    • bloc/{{name.snakeCase()}}_bloc.dart
    • pages/{{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()}}Bloc extends Bloc<{{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';

void run(HookContext context) async {
  final progress = context.logger.progress('Running build_runner...');
  
  await Process.run(
    'flutter', 
    ['pub', 'run', 'build_runner', 'build', '--delete-conflicting-outputs']
  );
  
  progress.complete('Done!');
}

在这里插入图片描述

五、完整演示:从零到一生成登录模块

假设我们需要为一个新的鸿蒙 App 生成登录模块。

  1. 准备: mason add clean_feature --path ./bricks/clean_feature
  2. 执行: mason make clean_feature
  3. 输入:
    • Feature Name: authentication
    • State Management: bloc
    • Use Freezed: yes

几秒钟后,整个 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 格式问题了。

最佳实践

  1. 版本控制:将 Bricks 放入单独的 Git 仓库,通过 git url 引用。
  2. 细粒度拆分:不要把整个 App 做成一个 Brick。拆分成 page_brick, model_brick, repo_brick,组合使用更灵活。
  3. BrickHub:多去 brickhub.dev 逛逛,那里有全世界开发者贡献的优质 Brick(如 clean_architecture, api_service)。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐