Skip to content

hook/build.dart Data assets support #146264

Description

@dcharkes

Update 2026-05-12: This is available under flutter config --enable-dart-data-assets. Please report any issues that you find.

Update 2026-09-29: With @RecordUse() info available in link hooks since Dart 3.13, this experiment can be used to do tree-shaking of assets (#64106).

The hook/build.dart of packages should be able to not only add native code assets, but also data assets.

In Flutter, these data assets should be made available through the existing asset bundle API.

This issue tracks the flutter implementation for this in flutter tools.

Tracking issue for Dart and Flutter combined:

Umbrella issue for native assets:

cc @mosuem @andrewkolos @christopherfujino

Activity

  1. added
    toolAffects the "flutter" command-line tool. See also t: labels.
    team-toolOwned by Flutter Tool team
    on Apr 4, 2024
  2. added
    triaged-toolTriaged by Flutter Tool team
    P2Important issues not at the top of the work list
    on Apr 4, 2024
  3. added
    tool-still-validIssues that have been deemed still valid as part of the Flutter Tools issue cleanup initiative.
    on Jul 11, 2025
  4. dcharkes commented on Sep 25, 2026

    @dcharkes
    ContributorAuthor

    What benefits would we get from deprecating pubspec.yaml assets: and asset transformers in favor DataAssets from hook/build.dart and hook/link.dart?

    • Tree-shaking unused assets Tree shake unused assets #64106. Based on what Dart code is reachable after Dart whole-program optimization. This is a long-requested feature in Flutter.
    • Building abstractions on top of assets and still be able to tree-shake via abstraction lowering in between link hooks. E.g. instead of I package icons/translations needing to have const arguments everywhere, a package invoking such package can have const arguments that it knows how to translate down into uses for the lower packages. For example abstraction and lower-level. This would not be possible with Let asset transformers read the program's recorded uses #193219.
    • Reducing bespoke solutions in Flutter.
      • Asset flavors and os-specific assets would naturally fold into using link hooks and tree shaking. For flavors and OS-specific assets, asset identifiers may already not overlap, so user-code is already branching at runtime to load the right asset ID. Since flavor and target OS are compile-time constants, special casing this is not needed.
      • Asset transformers do a subset of use cases compared to link hooks, so these can be removed.
    • Step towards SDK-agnostic packages with data assets. (Data assets feature dart-lang/sdk#54003). When we have data assets support also in the Dart SDK, packages for translations, etc can be written in a way that works both in Flutter and Dart standalone.

    Migration path for users

    1. Convert the asset entries in the pubspec yaml to a file system traversal in the build hook:
    flutter:
      assets:
        - assets/

    ->

    import 'package:data_assets/data_assets.dart';
    import 'package:hooks/hooks.dart';
    
    void main(List<String> args) async {
      await build(args, (input, output) async {
        await output.addDataAssetDirectories(
          [
            'assets', // The usual location for Flutter apps to place their assets
          ],
          recursive: true, // Include everything recursively
          input: input,
          // To enable tree-shaking in the link hook: route assets to the link hook instead of app bundle directly.
          routing: input.config.linkingEnabled
              ? ToLinkHook(input.packageName)
              : const ToAppBundle(),
        );
      });
    }

    (If we believe a lot of people will write this code over and over again, we could simplify this to:

    import 'package:data_assets/data_assets.dart';
    
    void main(List<String> args) async => registerDataAssets([
      'assets',
    ]);
    1. If tree-shaking is wanted, add @RecordUse() annotations to the code using assets. Check out this example app for various patterns with tree-shaking and resizing images, tree-shaking audio files, and tree-shaking and pruning translation files. The code might need massaging to center around const objects and static invocations with const arguments for tree-shaking to work. (This is standard practice already in the places where we have custom asset tree-shaking: icon fonts, and translation pipelines in g3.)

    2. Flavors and platforms-specific assets fold naturally into tree-shaking. These already require runtime branching in the code. The branch points should be annotated with @RecordUse(), either const arguments or const instances. This refactoring will most likely be trivial due to flavors being a const-from-environment and platform-branching being done on Platform.is... or a similar vm-platform-const value.

    What is needed to ship this?

    • Fix bugs / corner cases with data assets implementation
      • Data assets from build hooks are ignored if there are 0 assets from pubspec.yaml.
      • add data assets to flutter test
      • add data assets from dev dependencies in flutter drive --release and flutter build apk integration_test/... --release.
      • make widget-preview aware of data asset changes
    • Add assets: special treatment to DataAssets special treatment in Flutter
      • Assets from the root package are not namespaced in their package and can be accessed by their name. Do the same for data assets.
      • Images can live in 2.0x and similar directories for DPR (device pixel ratio), do the same for data assets.
    • Optional add a flavor and platform to the LinkInput and run the link hooks without @RecordUse() but with this info for development mode. This would enable Flutter-specific link hooks to prevent copying assets for other flavors to the device. (But maybe in development mode you want the assets for all flavors?!)
    • Turn data assets experimental flag on by default
    • Update documentation after first stable release with experiment flag on.

    Out of scope

    • Migrating pubspec.yaml->flutter->fonts. Now that tree-shaking info is available to packages, fonts might not need to be a built-in asset type to Flutter. They might be able to be built on top of data assets, including the tree shaking of icon fonts.
    • Migrating pubspec.yaml->flutter->shaders. Same argument.
    • Migrating pubspec.yaml->flutter->deferred-components->assets. Not many users use this. The clean way to do this would be to not require users to manually assign assets to deferred modules, but to infer this information from where the assets are used in the Dart code. Dart code is split up in loading_units which are assigned to deferred modules. The @RecordUse() recordings know in which loading unit the Dart code ended up. So, we should be able to automatically assign assets to the right deferred module. But since this is a niche use case we would defer supporting deferred loading.
  5. dcharkes commented on Sep 25, 2026

    @dcharkes
    ContributorAuthor

    @mit-mit @kevmoo @mariamhas WDYT? Is providing tree-shakable assets worth an ecosystem migration away from pubspec.yaml -> flutter -> assets?

    cc @goderbauer

  6. kevmoo commented on Sep 25, 2026

    @kevmoo
    Contributor

    I'm a BIG fan of less magic in Flutter and more general, extensible solution in Dart.

    The technical bits looks reasonable on a first pass.

  7. kevmoo commented on Sep 29, 2026

    @kevmoo
    Contributor

    Adding one follow-up thought on the migration / deprecation question (Option 1: deprecate flutter: assets: in pubspec.yaml vs Option 2: additive hooks):

    1. Deprecate pubspec.yaml transformers:: Strongly in favor. hook/build.dart and hook/link.dart strictly supersede YAML asset transformers.
    2. Canonical for packages & advanced assets: For ecosystem packages, design systems, icons, and localization, DataAsset + @RecordUse() in hook/build.dart / hook/link.dart should be the recommended path—that's where cross-package composition and tree-shaking (Tree shake unused assets #64106) have the highest leverage.
    3. Declarative sugar for simple app assets: I'd be cautious about forcing a hello-world or simple Flutter app to add hooks + data_assets dependencies and write a hook/build.dart script just to include a static logo.png. If flutter_tools can desugar pubspec.yaml flutter: assets: into the DataAsset pipeline under the hood, we get a single engine (less magic in Flutter) while keeping the 2-line YAML ergonomics for simple static app bundles until/unless they need programmatic bundling or tree-shaking.
  8. dcharkes commented on Sep 29, 2026

    @dcharkes
    ContributorAuthor

    @CarlosMendonca @kevmoo If we keep flutter: assets:, but deprecate flutter: assets: transformers: we should update the documentation as follows after the the first stable release that has the data assets experiment turned on by default:

  9. zanderso commented on Sep 29, 2026

    @zanderso
    Member

    Currently, assets (including asset transformers, I think?) are covered by hot reload/restart. Losing the ability to hot reload assets would be a regression.

  10. mariamhas commented on Sep 29, 2026

    @mariamhas
    Contributor

    Im also curious how this might impact tooling like dart migrate which from my highlevel understanding depends on a pubspec?

  11. dcharkes commented on Sep 30, 2026

    @dcharkes
    ContributorAuthor

    Currently, assets (including asset transformers, I think?) are covered by hot reload/restart. Losing the ability to hot reload assets would be a regression.

    Yes, hot restart and hot reload are covered.

    Migrating Fonts

    I also took a look at the longer term plan for migrating fonts.

    Option 1: Data assets only, fonts as package

    The lean core, completely remove fonts bundling from the Flutter Engine and Font pre-loading from the Flutter engine/framework. For this we need two components:

    1. SynchronousDataAssets. assets which can be accessed synchronously at runtime. Currently assets can only be assets via a Future, due to the system calls doing the actual loading. However, Fonts in the native platforms are mmaped in synchronously on their first use. And on web they are preloaded before the users' main. The DataAssets from build hooks with the Flutter assets API (https://docs.flutter.dev/ui/assets/assets-and-images) is asynchronous. We need a synchronous variant for which the bundling format + embedder promise synchronous access.
    2. Option A: Breaking change of fonts API: const TextStyle(fontFamily: 'Raleway') has no way to know that it's raleway.ttf. A better way to structure this API would be to have const TextStyle(fontFamily2: raleway) where const raleway = FontFamily(asset: 'my_package/assets/raleway.ttf', bold: ...). This would be proper encapsulation. And also makes tree-shaking via @RecordUse() trivial because you can simply look at all the const instances. (The current icon-font tree-shaker cannot omit fonts and icon fonts when they are completely unused.)
      Option B: Leverage link hooks to collect the font-mappings in a JSON file in package:fonts under a known data-asset, and load that asset before the users' main to register all fonts.

    Option 2: FontAssets

    Keep all the special casing in the engine and framework for bundling fonts, but allow reporting them from build and link hooks. This keeps leveraging the mmap lazy sync loading on the native backends, and the eager registration via reading the FontManifest.json in the engine before the user program runs.

    POC: #174860

    (I'd recommend against this, this does not provide a leaner Flutter.)

    Migrating Shaders

    This is much easier than fonts. These are already accessed via an asset key, and asynchronous. And @bdero already has a PR in flight to make the impellerc executable available in build hooks (#189821).

    @bdero Are there any other things missing for fully supporting shaders: from the pubspec.yaml from build hooks via data assets?

  12. dcharkes commented on Sep 30, 2026

    @dcharkes
    ContributorAuthor

    Im also curious how this might impact tooling like dart migrate which from my highlevel understanding depends on a pubspec?

    I cannot find any use of the pubspec assets in flutter migrate.

    Side note: @zanderso mentioned that if we do want to remove support for an old way of doing things, we should write a migrator to the new world.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Important issues not at the top of the work listteam-toolOwned by Flutter Tool teamtoolAffects the "flutter" command-line tool. See also t: labels.tool-still-validIssues that have been deemed still valid as part of the Flutter Tools issue cleanup initiative.triaged-toolTriaged by Flutter Tool team

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions