你有没有想过为 Dart 和 Flutter 开发一些工具,却苦于不知从何下手?又或者,你不想费劲去搞定如何连接到正在运行的 Dart 或 Flutter 应用,以便获取调试数据?就算工具做出来了,又该怎么部署,怎么让大家方便地用上呢?
现在,有个好消息要告诉你:所有这些难题,都将迎刃而解。
有了全新的 Dart & Flutter DevTools 扩展框架,你就能轻松打造出与现有 DevTools 工具套件紧密结合的开发者工具。这些扩展基于 Flutter Web 构建,并充分利用了 DevTools 现有的框架和实用工具,大大简化了开发者工具的创作过程。

DevTools 扩展是如何运作的?
DevTools 扩展会作为 pub
包的一部分进行发布。你可以选择将 DevTools 扩展添加到现有的 pub
包中,也可以专门创建一个只提供 DevTools 扩展的新包。无论哪种情况,最终用户都必须在其应用中,将提供 DevTools 扩展的那个包列为依赖项,这样才能在 DevTools 中看到这个扩展。
举个例子,假设我们有一个 package:foo
包,并且这个包提供了一个 DevTools 扩展。当用户在他们的应用中依赖 package:foo
时,他们就会自动获得这个包提供的 DevTools 扩展的访问权限。当 DevTools 检测到 package:foo
扩展可用时(根据用户应用或 IDE 提供的信息),DevTools 中就会新增一个名为"Foo"的标签页,里面包含了 package:foo
提供的开发者工具。

一些已经将 DevTools 扩展添加到现有包中的例子有:package:provider、package:patrol 和 package:drift。
支持哪些类型的工具?
借助 DevTools 扩展框架,你可以构建多种类型的工具,包括:
- 现有包的配套工具
- 作为独立包发布的新工具
- 与正在运行的应用交互的工具
- 不与正在运行的应用交互的工具
- 与 IDE 中打开的项目文件交互的工具
- 未来计划: 与分析服务器交互的工具(如果你希望此功能尽快实现,请为这个 issue 点赞!)
DevTools 扩展框架提供了开箱即用的功能,让你的扩展分发给用户变得无缝衔接:
- 用户可以在浏览器中的 DevTools 里使用你的工具
- 用户可以直接在他们的 IDE 中嵌入并使用你的工具
- 用户可以从 Dart 和 Flutter 支持的 IDE 中发现并打开你的工具
现在,让我们开始吧!
编写 DevTools 扩展:分步指南
开始之前
你需要准备:
- Flutter SDK 版本 >=
3.17.0--0.0.pre
& Dart SDK 版本 >=3.2
。 - 一个
Pub
包(可以是现有包,也可以是新创建的),用于添加 DevTools 扩展。
为了使用最新的
devtools_extensions
和devtools_app_shared
包,你可以在 Flutter 的master
或beta
通道进行扩展开发。
第一步:设置你的包层级结构
独立扩展
对于独立扩展(即不作为现有 pub
包的一部分发布的扩展),你可以将扩展的源代码包含在发布该扩展的同一个包中。这样做可以简化开发,而且由于你的包的用户会将其作为 dev_dependency
(开发依赖)添加,所以你的包大小不会影响用户应用的大小。你的包结构将如下所示:
arduino
my_new_tool
extension/
devtools/
build/
... # lib/ 目录下 Flutter web 应用的预编译输出
config.yaml
lib/ # 你的扩展 Flutter web 应用的源代码
src/
...
由于扩展必须构建为 Flutter web 应用,请使用 flutter create
命令来为你(的 DevTools)扩展生成包:
bash
flutter create --template app --platforms web my_new_tool
现在,在下一步中使用 my_new_tool
包来配置你的扩展。
伴随式扩展
对于伴随式扩展(即作为现有 pub
包的一部分发布的扩展),我们建议你将扩展的源代码放在你的 pub
包之外。这将有助于尽可能减小你的包大小,因为你会希望避免增加依赖你包的用户应用的大小。这里是推荐的包结构:
bash
foo/ # 你pub包的(原)仓库根目录
packages/
foo/ # 你的pub包
extension/
devtools/
build/
... # foo_devtools_extension/lib 的预编译输出
config.yaml
foo_devtools_extension/
lib/ # 你的扩展 Flutter web 应用的源代码
第二步:配置你的扩展
在将为用户提供 DevTools 扩展的 Dart 包中,添加一个顶级的 extension
目录:
swift
foo/
extension/
lib/
...
在 extension
目录下,严格按照所示创建以下结构:
arduino
extension/
devtools/
build/
config.yaml
config.yaml
文件包含 DevTools 加载扩展所需的元数据:
yaml
name: foo
version: 0.0.1
issueTracker: <link_to_your_issue_tracker.com>
materialIconCodePoint: '0xe0b1'
requiresConnection: true # 可选项 - 默认是 true
复制上面 config.yaml
文件的内容,并粘贴到你刚刚在包中创建的 config.yaml
文件里。务必使用所示的确切文件名和字段名,否则你的扩展可能无法在 DevTools 中加载。
对于每个键,填写你的包的相应值。
name
: 此 DevTools 扩展所属的包名。此字段的值将用于扩展页面的标题栏。 [必填]version
: 你的 DevTools 扩展的版本号。随着你为扩展发布新功能,此版本号应随时间演进。此字段的值将用于扩展页面的标题栏。 [必填]issueTracker
: 你的问题追踪器的 URL。当用户点击 DevTools UI 中的"报告问题"链接时,他们将被定向到此 URL。 [必填]

materialIconCodePoint
: 对应于material/icons.dart
中某个图标的 codepoint 值。此图标将用于 DevTools 顶级标签栏中该扩展的标签页。 [必填]

requiresConnection
: 表示该扩展是否需要连接到一个 Dart 或 Flutter 应用才能使用。这是一个可选字段,如果未指定,将默认为true
。 [可选]
有关 config.yaml
规范的最新文档,请参阅 extension_config_spec.md
。
现在是时候构建你的扩展了。
第三步:构建你的扩展
创建 Flutter web 应用。
注意: 如果你正在构建一个独立扩展,请跳过此步骤,因为你已经在设置包层级结构时完成了此操作。
- 在你希望扩展源代码所在的目录中,运行以下命令,将
foo_devtools_extension
替换为<你的包名>_devtools_extension
:
css
flutter create --template app --platforms web foo_devtools_extension
- 将
package:devtools_extensions
依赖项添加到你的扩展 Flutter web 应用中。
csharp
flutter pub add devtools_extensions
你可能还会希望添加对 package:devtools_app_shared
的依赖,该包包含共享服务、实用工具和 UI 组件,供你在构建扩展时使用。请参阅 devtools_app_shared/example
获取示例用法。
csharp
flutter pub add devtools_app_shared
在你的 Flutter web 应用的根部添加 DevToolsExtension
Widget。 在 lib/main.dart
中,添加以下内容:
dart
import 'package:devtools_extensions/devtools_extensions.dart';
import 'package:flutter/material.dart';
void main() {
runApp(const DevToolsExtension());
}
class FooDevToolsExtension extends StatelessWidget {
const FooDevToolsExtension({super.key});
@override
Widget build(BuildContext context) {
return const DevToolsExtension(
child: Placeholder(), // Build your extension here
);
}
}
DevToolsExtension
Widget 会自动执行与 DevTools 交互所需的所有扩展初始化。在你的扩展 web 应用的任何地方,你都可以访问以下全局变量:
extensionManager
: 一个用于与 DevTools 或扩展框架交互的管理器。serviceManager
: 一个用于与已连接的 VM 服务交互的管理器(如果存在)。dtdManager
: 一个用于与 Dart Tooling Daemon 交互的管理器(如果存在)。
第四步:调试你的扩展
在开发和维护你的 DevTools 扩展时,你会希望运行、调试和测试你的扩展 Flutter web 应用。你有几种不同的选项,如下所述。
选项 A:使用模拟的 DevTools 环境(推荐用于开发)
出于调试目的,你可能希望使用"模拟的 DevTools 环境"。这是一个模拟环境,允许你构建扩展,而无需将其开发为 DevTools 中的嵌入式 iFrame。以这种方式运行你的扩展,会用一个模拟 DevTools 到 DevTools 扩展连接的环境来包裹你的扩展。它还为你提供了热重启和更快的开发周期。

- 你的 DevTools 扩展。
- 测试应用的 VM 服务 URI,你的 DevTools 扩展将与该应用进行交互。这个应用应该依赖于你的扩展的父包(本例中是
package:foo
)。 - 用于执行用户可能从 DevTools 触发的操作的按钮。
- 显示你的扩展和 DevTools 之间将发送的消息的日志。
模拟环境通过环境变量 use_simulated_environment
启用。要使用此标志运行你的扩展 web 应用,请在 VS Code 的 launch.json
文件中添加一个配置:
json
{
...
"configurations": [
...
{
"name": "foo_devtools_extension + simulated environment",
"cwd": "packages/foo_devtools_extension",
"request": "launch",
"type": "dart",
"args": [
"--dart-define=use_simulated_environment=true"
],
},
]
}
或者从命令行启动你的应用,并添加以下标志:
ini
flutter run -d chrome - dart-define=use_simulated_environment=true
选项 B:使用真实的 DevTools 环境
一旦你的扩展开发到一定阶段,准备好在真实的 DevTools 环境中测试你的更改时,你需要执行一系列设置步骤:
- 将你的扩展开发到可以准备在真实的 DevTools 环境中测试更改的程度 。构建你的 Flutter web 应用,并将构建好的资源从
your_extension_web_app/build/web
复制到你的pub
包的extension/devtools/build
目录。 使用package:devtools_extensions
中的build_and_copy
命令来帮助完成此步骤。
bash
cd your_extension_web_app;
flutter pub get;
dart run devtools_extensions build_and_copy --source=. --dest=path/to/your_pub_package/extension/devtools
注意: 如果你正在使用上面推荐的包结构来为现有 pub
包添加扩展,那么 --dest
的值应该是 ../你的_pub_包/extension/devtools
。
为了确保你的扩展在 DevTools 中加载设置正确,请运行 package:devtools_extensions
中的 validate
命令。--package
参数应该指向将发布此扩展的 Dart 包的根目录。
bash
cd your_extension_web_app;
flutter pub get;
dart run devtools_extensions validate --package=path/to/your_pub_package
-
准备一个测试环境,并添加对提供扩展的
pub
包的依赖。 在你添加对你的包的依赖的 Dart 或 Flutter 项目中,添加一个指向你本地包源代码的path
依赖(该包包含你的扩展资源的extension/devtools/
目录)。完成此操作后,在该包上运行pub get
。 如果你的扩展需要一个正在运行的应用程序,那么你需要运行依赖于你的扩展的应用程序。 如果你的扩展不需要正在运行的应用程序,那么你需要在支持的 IDE(VS Code 或 IntelliJ / Android Studio)中打开依赖于你的包的测试 Dart 或 Flutter 项目。 -
通过以下方式之一启动 DevTools: 如果你的扩展需要一个正在运行的应用程序,你可以从运行测试应用程序时命令行打印的 URI 中打开 DevTools,或者从你运行测试应用程序的 IDE 中打开 DevTools。 如果你的扩展不需要正在运行的应用程序,你可以在支持的 IDE(VS Code 或 IntelliJ / Android Studio)中打开依赖于你的包的 Dart 或 Flutter 项目。从 IDE 中打开 DevTools,以在浏览器中查看你的扩展。 如果你需要 DevTools 的本地或未发布更改,你需要从源代码构建并运行 DevTools。请参阅 DevTools 的
CONTRIBUTING.md
以获取操作指南。你需要构建带有服务器和前端的 DevTools 来测试扩展------请参阅 说明。 -
**打开 DevTools 后,你会在 DevTools 应用栏中看到你的扩展的标签页。**你的扩展的启用或禁用状态由 DevTools 管理,并通过屏幕右上角操作按钮中的"扩展"菜单进行公开。


第五步:发布你的包含 DevTools 扩展的包
为了让一个包能向其用户提供 DevTools 扩展,它必须在发布时包含 your_pub_package/extension/devtools/
目录下预期的内容(请参阅上面的设置说明)。
- 确保
extension/devtools/config.yaml
文件存在,并已按照上述规范进行配置。你可以运行package:devtools_extensions
中的validate
命令进行验证。
bash
cd your_extension_web_app;
flutter pub get;
dart run devtools_extensions validate --package=path/to/pkg_providing_your_extension_assets
- 使用
package:devtools_extensions
提供的build_and_copy
命令来构建你的扩展,并将输出复制到extension/devtools
目录:
ini
cd your_extension_web_app;
flutter pub get;
dart run devtools_extensions build_and_copy --source=. --dest=path/to/your_pub_package/extension/devtools
然后将你的包发布到 pub.dev
:运行 flutter pub publish
。在运行 pub publish
时,如果你的 config.yaml
文件不存在或 build
目录为空(不符合要求),你将看到一条警告。
有关发布包的更多指导,请参阅 package:devtools_extensions
的发布指南。
结论
就是这样!现在,当用户依赖你的包的最新版本时,他们将自动获得你在 DevTools 扩展中提供的工具。
对于问题和功能请求,请在 DevTools 的 问题追踪器 上提交问题。
如需一般支持和访问 DevTools 扩展作者社区,请查看 Discord 频道 #devtools-extension-authors
(你需要首先加入 Flutter Discord 服务器)。
最后欢迎关注我的公众号:OpenFlutter,感恩。