Skip to content

Barrel Files

When building a package, a feature, or an API, we will create a folder structure with all the source code inside. If we stop here and don’t export the files that will be required in other places of the app, we will force developers to have a long and messy import section. Furthermore, any refactor that affects file names in one feature will require changes in other places that could be avoided.

For a package, the structure could look something like:

  • Directorymy_package/
    • Directorylib/
      • Directorysrc/
        • Directorymodels/
          • model_1.dart
          • model_2.dart
        • Directorywidgets/
          • widget_1.dart
          • widget_2.dart
    • Directorytest/
    • pubspec.yaml

And for a feature, it could look like:

  • Directorymy_feature/
    • Directorybloc/
      • feature_bloc.dart
      • feature_event.dart
      • feature_state.dart
    • Directoryview/
      • feature_page.dart
      • feature_view.dart
    • Directorywidgets/
      • widget_1.dart
      • widget_2.dart

In both cases, if we want to use both widget_1.dart and widget_2.dart in other parts of the app, we will have to import them separately like:

import 'package:my_package/lib/src/widgets/widget_1';
import 'package:my_package/lib/src/widgets/widget_2';

In the case of a refactor, updating all those imports is inefficient. Barrel files help solve this problem.

Barrel files

Barrel files are responsible for exporting other public facing files that should be made available to the rest of the app.

It is recommended to create one barrel file per folder, exporting all files from that folder that could be required elsewhere. You should also have a top level barrel file to export the package as a whole.

With these changes, let’s update the folder structures for both scenarios.

A package with barrel files should look like:

  • Directorymy_package/
    • Directorylib/
      • Directorysrc/
        • Directorymodels/
          • model_1.dart
          • model_2.dart
          • models.dart
        • Directorywidgets/
          • widget_1.dart
          • widget_2.dart
          • widgets.dart
      • my_package.dart
    • Directorytest/
    • pubspec.yaml

And for a feature, it should look like:

  • Directorymy_feature/
    • Directorybloc/
      • feature_bloc.dart
      • feature_event.dart
      • feature_state.dart
    • Directoryview/
      • feature_page.dart
      • feature_view.dart
      • view.dart
    • my_feature.dart

Finally let’s see what these files contain. Continuing with the package example, we have three barrel files: models.dart, widgets.dart and my_package.dart.

models.dart:

export 'model_1.dart';
export 'model_2.dart';

widgets.dart:

export 'widget_1.dart';
export 'widget_2.dart';

my_package.dart:

export 'src/models/models.dart';
export 'src/widgets/widgets.dart';

Bloc and barrel files

By convention, blocs are typically broken into separate files consisting of the events, states, and the bloc itself:

  • Directorybloc/
    • feature_bloc.dart
    • feature_event.dart
    • feature_state.dart

In this case, we don’t add an extra barrel file since the feature_bloc.dart file is working as such, thanks to the part of directives. You can read more about it in the bloc documentation.