routes_generator 0.0.5

Dart native

Automatically generate routes of pages for `MaterialApp` of `flutter`. Supports group routes, parameterized pages, dynamic routes.

English | 中文简体

routes_generator #

Provides source_gen Generator to generator routes for MaterialApp of flutter.

Non-intrusive, convention over configuration, only need to install and build.

Convention #

  • The routes.dart file used to export routes and related functions to MaterialApp, and routes.map.dart must be imported in the file routes.dart.
  • The pages directory relative to routes.dart contains your app views and routes, each file contains only one routing page, generator reads all .dart files inside this directory and generate routes map into routes.map.dart.
  • The above two conventions apply to any directory of the project.

Usage #

Basic Routes #

Add dev_dependencies.

dev_dependencies:
  routes_generator: any

Import routes.map.dart in the routes.dart file (add new if it does not exist), you do not need to add a new routes.map.dart file, it will be automatically generated.

// routes.dart
import 'package:flutter/widgets.dart';
import 'routes.map.dart' as p;

Map<String, WidgetBuilder> routes = p.routes;

Run code generation.

$ flutter pub run build_runner build

If there are multiple routes.map.dart, they need to be merged and used.

import 'routes.map.dart' as p;
import 'dev/routes.map.dart' as d;

class MyApp extends StatelessWidget {

  Widget build(BuildContext context) {
    return MaterialApp(
      routes: <String, WidgetBuilder>{...p.routes, ...d.routes}
    );
  }
}

Group Routes #

In addition to putting all routes in one Map, sometimes it is necessary to put some routes into a separate Map for special processing, such as detecting login before routing.

You need to add a private class named _RoutesGroup and define the supported group annotation instances, such as

class _RoutesGroup {
  final String name;
  const _RoutesGroup(this.name);
}
const authRequired = _RoutesGroup('authRoutes');

Add corresponding annotations on the routing page where required

@authRequired
class MySetting extends StatelessWidget {
  Widget build(BuildContext context) {
    // ...
  }
}

Conventional annotations are private class instances.The reason for not providing annotation classes is that routing needs to be used and managed, and random group names are not allowed when grouping is specified on the page.

Parameterized #

If the page widget is parameterized, the generator will automatically inject parameters.

class ParameterizedPage extends StatelessWidget {
  final String arg1;
  final String arg2;
  ParameterizedPage(this.arg1, {this.arg2});
}

The generated routes looks like this

Map<String, WidgetBuilder> routes = {
  '/parameterized': (context) {
    final Map args = ModalRoute.of(context).settings?.arguments ?? {};
    return ParameterizedPage(args['arg1'], arg2: args['arg2']);
  },
};

Dynamic Routes #

If the path of the page contains a directory or file name starting with an underscore (_), then the directory or file name will be used as a variable. such as /dynamic/_name/_id.dart, there are two variable in the path, name and id.

class DynamicPage extends StatelessWidget {
  final String name;
  final String id;
  DynamicPage(this.name, {this.id});
}

The generated routing table is an list, which variable name ends with Dynamic

List<WidgetBuilder Function(String)> routesDynamic = [
  (path) {
    final reg = RegExp(r'^/dynamic/(?<name>[^\/]+)$/(?<id>[^\/]+)$');
    final match = reg.firstMatch(path);
    if (match == null) return null;
    return (context) => DynamicPage(match.namedGroup('name'), id: match.namedGroup('id'));
  },
];

That should be used in onGenerateRoute

onGenerateRoute: (RouteSettings settings) {
  WidgetBuilder builder = routes[settings.name];
  if (builder == null) {
    for (final matcher in routesDynamic) {
      builder = matcher(settings.name);
      if (builder != null) {
        break;
      }
    }
  }
  if (builder == null) return null;
  return MaterialPageRoute(settings: settings, builder: builder);
}

Configuration #

If your project structure does not conform to the convention, or want to split the route according to the environment, such as, the development app provides more pages and features, which is very useful when switching between multiple development environments. Configuration is also provided.

Basic #

The following structure is typical and conforms to the convention.

├── lib
│   ├── dev
│   │   ├── drawer.dart
│   │   ├── pages
│   │   │   └── hosts.dart
│   │   ├── routes.dart
│   │   └── routes.map.dart
│   ├── main.dart
│   ├── main_dev.dart
│   ├── pages
│   │   ├── home.dart
│   │   ├── user
│   │   │   └── settings.dart
│   │   └── setting.dart
│   ├── routes.dart
│   ├── routes.map.dart
│   └── screen
│       ├── app.dart
│       └── home.dart

Configure it in build.yaml. The following configuration is in accordance with the convention. Already meet basic directory split requirements.

targets:
  $default:
    builders:
      routes_generator:
        options:
          ext: ".map.dart" # generated file extension
          routes:
            routes.dart: # routes.dart 
              name: "routes" # generated variable name
              pages: "pages" # pages directory, relative to `routes.dart`

Change or add the configuration to fit you situation. For example, the route directory is views instead of pages.

targets:
  $default:
    builders:
      routes_generator:
        options:
          ext: ".my.dart" # change generated file extension
          prefix: "/app" # add default prefix `/app` to route url
          routes:
            my_routes.dart: # change routes file
              name: "myRoutes" # change the variable name 
              pages: "../views" # change pages location
            dev/my_routes.dart:
              prefix: "/dev" # add prefix to dev route url, override default prefix `/app`
              name: "devRoutes"
              pages: "views"

Group #

If you have defined routing grouping in the project, you can also modify the default grouping parameters group. The group need to specify the class name and grouped field name.

targets:
  $default:
    builders:
      routes_generator:
        options:
          group: "MyPageRoutes.group" # change with class name and it's field name

The annotation is defined as follows.

class MyPageRoutes {
  final String group;
  const MyPageRoutes(this.group);
}

@MyPageRoutes(group: 'authRoutes')
class FirstPage extends StatelessWidget {
}

This option can also be in any routes sub-node, which will override the default option.

targets:
  $default:
    builders:
      routes_generator:
        options:
          group: "MyPageRoutes.group"
          routes:
            routes.dart:
              group: "SubPageRoutes.group"

Ignores #

If there are non-routing page files or directories in the pages directory, they can be ignored by configuration

targets:
  $default:
    builders:
      routes_generator:
        options:
          ignores: "**/widgets/**" # ignore all `widgets` directory in `pages`

Or configure multiple

targets:
  $default:
    builders:
      routes_generator:
        options:
          ignores:
            - "**/widgets/**" # ignore all `widgets` directory in `pages`
            - "**.g.dart" # ignore all generated files

This option can also be in any routes sub-node, which will override the default option. You can also set false to disable this option.

targets:
  $default:
    builders:
      routes_generator:
        options:
          ignores: "**.g.dart"
          routes:
            routes.dart:
              ignores: "**/widgets/**"
            dev/routes.dart:
              ignores: false # disable ignore any files

Dynamic #

The suffix name of dynamic routing variable can be configured. You can also set false to prohibit the generation of dynamic routing.

targets:
  $default:
    builders:
      routes_generator:
        options:
          dynamic: 'Dynamic'
          routes:
            routes.dart:
              dynamic: 'Dynamic'
            dev/routes.dart:
              dynamic: false # disable dynamic routes
0
likes
100
pub points
0%
popularity

Automatically generate routes of pages for `MaterialApp` of `flutter`. Supports group routes, parameterized pages, dynamic routes.

Repository (GitHub)
View/report issues

Documentation

API reference

Uploader

wenjunxiao51@gmail.com

License

MIT (LICENSE)

Dependencies

analyzer, build, build_config, glob, path, source_gen

More

Packages that depend on routes_generator