Generate barrel files for Dart and Flutter packages with build_runner
based on code annotations.
In Dart, visibility of a class, global variable or any other top-level element can be limited to a single library (single .dart
file or a group of .dart
files united with part
and part of
directives) by simply naming those elements with _
prefix. This way, information about code visibility in as close to the code itself as possible.
However, there is no similar mechanism to scope code elements visibility to a package where they are located, keeping them accessible to all the rest of the code in the same package, but making them inaccessible from outside. To reach the same effect, when creating a Dart or Flutter package, it is common to put all .dart
files under the /lib/src
folder and create a new .dart
file under the /lib
folder (usually named after the package), that contains export
directives for files and Dart code elements that should be exposed from that package. These files are called "barrel files".
This approach helps with encapsulation as users of these packages will get warnings if they import a file from the /lib/src
folder instead of importing one of barrel files from the /lib
folder. However, in this case the information about code visibility gets detached from the code itself and is controlled in a barrel file in a different location.
For packages that rely on code-generation with build_runner
, it can be beneficial to use the barrel_files
package to create barrel files based on annotations placed directly above code elements that should be visible outside those packages.
A special annotation to mark public code provides information about code visibility right where it is needed - next to the code itself!
Add barrel_files_annotation
to dependencies
and barrel_files
to dev_dependencies
section of the pubspec.yaml
file:
dependencies:
barrel_files_annotation:
...
dev_dependencies:
barrel_files:
build_runner:
...
Annotate classes, enums, global constants and any other top level elements that are not private to the package with @includeInBarrelFile
:
import 'package:barrel_files_annotation/barrel_files_annotation.dart';
@includeInBarrelFile
class ExampleClass {}
@includeInBarrelFile
const exampleGlobalConst = 0;
@includeInBarrelFile
enum ExampleEnum {one, two, three}
@includeInBarrelFile
String exampleFunction() => 'example';
@includeInBarrelFile
typedef ExampleTypeDef = void Function(int i);
To run the code generator, execute the following command:
dart run build_runner build --delete-conflicting-outputs
A new .dart
file will be created under the /lib
folder. If the example usage of @includeInBarrelFile
annotation above is located in the lib/src/example_input.dart
file of the example_package
package, the output will be:
// GENERATED CODE - DO NOT MODIFY BY HAND
export 'package:example_package/src/example_input.dart'
show
ExampleClass,
ExampleEnum,
ExampleTypeDef,
exampleFunction,
exampleGlobalConst;
By default, barrel file name matches the package name, example_package
in the example above.
To customize the generated file name (and possibly location), create or modify the build.yaml
file located next to the pubspec.yaml
file:
targets:
$default:
builders:
barrel_files|barrel_files:
options:
barrel_file_name: "custom_example.dart"
This setup will result in lib/custom_example.dart
barrel file being created.
barrel_files
supports only one barrel file generation.