Dart & Flutter DevTools 扩展

你有没有想过为 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:providerpackage:patrolpackage: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_extensionsdevtools_app_shared 包,你可以在 Flutter 的 masterbeta 通道进行扩展开发。

第一步:设置你的包层级结构

独立扩展

对于独立扩展(即不作为现有 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 应用。

注意: 如果你正在构建一个独立扩展,请跳过此步骤,因为你已经在设置包层级结构时完成了此操作。

  1. 在你希望扩展源代码所在的目录中,运行以下命令,将 foo_devtools_extension 替换为 <你的包名>_devtools_extension
css 复制代码
flutter create --template app --platforms web foo_devtools_extension
  1. 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 环境中测试你的更改时,你需要执行一系列设置步骤:

  1. 将你的扩展开发到可以准备在真实的 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
  1. 准备一个测试环境,并添加对提供扩展的 pub 包的依赖。 在你添加对你的包的依赖的 Dart 或 Flutter 项目中,添加一个指向你本地包源代码的 path 依赖(该包包含你的扩展资源的 extension/devtools/ 目录)。完成此操作后,在该包上运行 pub get。 如果你的扩展需要一个正在运行的应用程序,那么你需要运行依赖于你的扩展的应用程序。 如果你的扩展不需要正在运行的应用程序,那么你需要在支持的 IDE(VS Code 或 IntelliJ / Android Studio)中打开依赖于你的包的测试 Dart 或 Flutter 项目。

  2. 通过以下方式之一启动 DevTools: 如果你的扩展需要一个正在运行的应用程序,你可以从运行测试应用程序时命令行打印的 URI 中打开 DevTools,或者从你运行测试应用程序的 IDE 中打开 DevTools。 如果你的扩展不需要正在运行的应用程序,你可以在支持的 IDE(VS Code 或 IntelliJ / Android Studio)中打开依赖于你的包的 Dart 或 Flutter 项目。从 IDE 中打开 DevTools,以在浏览器中查看你的扩展。 如果你需要 DevTools 的本地或未发布更改,你需要从源代码构建并运行 DevTools。请参阅 DevTools 的 CONTRIBUTING.md 以获取操作指南。你需要构建带有服务器和前端的 DevTools 来测试扩展------请参阅 说明

  3. **打开 DevTools 后,你会在 DevTools 应用栏中看到你的扩展的标签页。**你的扩展的启用或禁用状态由 DevTools 管理,并通过屏幕右上角操作按钮中的"扩展"菜单进行公开。

第五步:发布你的包含 DevTools 扩展的包

为了让一个包能向其用户提供 DevTools 扩展,它必须在发布时包含 your_pub_package/extension/devtools/ 目录下预期的内容(请参阅上面的设置说明)。

  1. 确保 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
  1. 使用 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,感恩。

相关推荐
Hilaku12 分钟前
深入background-image:你可能不知道的几个性能优化与高级技巧
前端·css
南岸月明14 分钟前
副业自媒体1年终于明白:为什么会表达的人,能量越来越强,更能赚到钱?
前端
Danny_FD28 分钟前
Vue + Element UI 实现模糊搜索自动补全
前端·javascript
gnip33 分钟前
闭包实现一个简单Vue3的状态管理
前端·javascript
斐济岛上有一只斐济38 分钟前
后端程序员的CSS复习
前端
Enddme41 分钟前
《面试必问!JavaScript 中this 全方位避坑指南 (含高频题解析)》
前端·javascript·面试
有梦想的程序员43 分钟前
微信小程序使用 Tailwind CSS version 3
前端
溟洵1 小时前
Qt 窗口 工具栏QToolBar、状态栏StatusBar
开发语言·前端·数据库·c++·后端·qt
用户2519162427111 小时前
Canvas之图像合成
前端·javascript·canvas
每天开心1 小时前
噜噜旅游App(4)——构建旅游智能客服模块,实现AI聊天
前端·微信小程序·前端框架