diff --git a/docs/pages/docs/Advanced Features/builder_options.md b/docs/pages/docs/Advanced Features/builder_options.md index 5ccb801d..83578477 100644 --- a/docs/pages/docs/Advanced Features/builder_options.md +++ b/docs/pages/docs/Advanced Features/builder_options.md @@ -182,7 +182,7 @@ targets: # using .drift files with type converters. drift_dev|preparing_builder: enabled: true - + run_built_value: dependencies: ['your_package_name'] builders: @@ -218,3 +218,133 @@ and use the non-shared generator instead. Finally, we need to the build system to run drift first, and all the other builders otherwise. This is why we split the builders up into multiple targets. The first target will only run drift, the second target has a dependency on the first one and will run all the other builders. + +## Modular code generation + +By default, drift generates code from a single entrypoint - all tables, views +and queries for a database are generated into a single part file. +For larger projects, this file can become quite large, slowing down builds and +the analyzer when it is re-generated. +Starting from Drift version 2.3.0, a new, modular, build setup is available as +an alternative for larger projects. +With this setup, drift generates multiple files and automatically manages +imports between them. + +{% block "blocks/alert" title="Experimental" color="success" %} +Please be aware that modular code generation is a drift feature in active +development. It is not fully stable yet, with minor breaking changes to be +expected until Drift 2.4.0. + +For those interested in trying this out - please report all issues or +inconveniences you run into. Your feedback is cruicial to stabilize this feature! +{% endblock %} + +As a motivating example, consider a large drift project with many tables or +views being split across different files: + +``` +lib/src/database/ +├── database.dart +├── tables/ +│ ├── users.drift +│ ├── settings.drift +│ ├── groups.drift +│ └── search.drift +└── views/ + ├── friends.drift + └── categories.dart +``` + +While a modular structure (with `import`s in drift files) is helpful to structure +sources, drift still generates everything into a single `database.g.dart` file. +With a growing number of tables and queries, drift may need to generate tens of +thousands of lines of code for data classes, companions and query results. + +With its modular generation mode, drift instead generates sources for each input +file, like this: + +``` +lib/src/database/ +├── database.dart +├── database.drift.dart +├── tables/ +│ ├── users.drift +│ ├── users.drift.dart +│ ├── settings.drift +│ ├── settings.drift.dart +│ └── ... +└── views/ + ├── friends.drift + ├── friends.drift.dart + ├── categories.dart + └── categories.drift.dart +``` + +### Enabling modular code generation + +_Note_: A small example using modular code generation is also part of [drift's repository](https://github.com/simolus3/drift/tree/develop/examples/modular). + +As drift's modular code generation mode generates different file patterns than +the default builder, it needs to be enabled explicitly. For this, create a +`build.yaml` file in which you disable the default `drift_dev` build and enable +the two builders for modular generation: `drift_dev:analyzer` and +`drift_dev:modular`. They should both get the same options: + +```yaml +targets: + $default: + builders: + drift_dev: + # disable drift's default builder, we're using the modular setup + # instead. + enabled: false + + # Instead, enable drift_dev:analyzer and drift_dev:modular manually: + drift_dev:analyzer: + enabled: true + options: &options + # Drift build options, as per https://drift.simonbinder.eu/docs/advanced-features/builder_options/ + store_date_time_values_as_text: true + named_parameters: true + sql: + dialect: sqlite + options: + version: "3.39" + modules: [fts5] + drift_dev:modular: + enabled: true + # We use yaml anchors to give the two builders the same options + options: *options +``` + +### What gets generated + +With modular generation, drift generates standalone Dart libraries (Dart files +without a `part of` statement). This also means that you no longer need `part` +statements in your sources. Instead, you import the generated `.drift.dart` +files. + +When it comes to using the generated code, not much is different: The API for +the database and DAOs stays mostly the same. +A big exception are how `.drift` files are handled in the modular generation +mode. In the default builder, all queries in all drift files are generated as +methods on the database. +With modular code generation, drift generates an implicit database accessor +reachable through getters from the database class. Consider a file `user.drift` +like this: + +```sql +CREATE TABLE users ( + id INTEGER NOT NULL, + created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + name TEXT NOT NULL, + is_admin BOOLEAN NOT NULL DEFAULT FALSE +); + +findUsers($predicate = TRUE): SELECT * FROM users WHERE $predicate; +``` + +If such a `users.drift` file is included from a database, we no longer generate +a `findUsers` method for the database itself. +Instead, a `users.drift.dart` file contains a [database accessor]({{ 'daos.md' | pageUrl }}) called `UsersDrift` which is implicitly added to the database. +To call `findUsers`, you'd now call `database.usersDrift.findUsers()`. \ No newline at end of file diff --git a/drift/CHANGELOG.md b/drift/CHANGELOG.md index 091d5f86..9b73db74 100644 --- a/drift/CHANGELOG.md +++ b/drift/CHANGELOG.md @@ -9,6 +9,9 @@ - Add `singleClientMode` to `remote()` and `DriftIsolate` connections to make the common case with one client more efficient. - Fix a concurrency issues around transactions. +- __Experimental__: Add a [modular generation mode](https://drift.simonbinder.eu/docs/advanced-features/builder_options/#enabling-modular-code-generation) + in which drift will generate multiple smaller files instead of one very large + one with all tables and generated queries. ## 2.2.0