Module
A module clusters all rotes and binds relative to an scope or feature of the application and may contain sub modules forming one single composition. It means that to access a bind, it needs to be in a parent module that's already started, otherwise, the bind will not be visible to be recovered using a system injection. A Module’s lifetime ends when the last page is closed.
Routing between modules
The shelf_modular works with "dynamic routes”, segments, query, fragments, very similar to what we see on web. Let’s take a look at the anatomy of a “path”. To access a route within a submodule, we will need to consider the segments of the route path represented by URI (Uniform Resource Identifier). For example:
/home/user/1
We call “segment” the text separated by /. For example, the URI /home/user/1 has three segment, being them [‘home’, ‘user’, ‘1’];
Use the Route.module builder to add a module to another:
class AModule extends Module {
List<ModularRoute> get routes => [
Route.get('/', () => Response.ok('path -> /')),
Route.module('/b-module', module: BModule()),
];
}
class BModule extends Module {
List<ModularRoute> get routes => [
Route.get('/', () => Response.ok('path -> /b-module/')),
Route.get('/other', () => Response.ok('path -> /b-module/other')),
];
}
In this scenario, there are two routes in AModule, a Route.get called / and a Route.module called /b-module.
The BModule contains another two Route.get called / and /other, respectively.
What would you call Route.get /other?
The answer is in follow up. Assuming that AModule is the application’s root module,
then the initial segment will be the name of the BModule, because we need to get a route that is within it.
/b-module
The next segment will be the name of the route we want, the /other.
/b-module/other
READY! When you execute the http://localhost:3000/b-module/other’) e verá a resposta: path -> /b-module/other.
The logic is the same when the submodule contains a route named as /. Understanding this, we assume that the available routes in this example are:
/ => `path -> /`
/b-module/ => 'path -> /b-module/'
/b-module/other => 'path -> /b-module/other'
When the concatenation of named routes takes place and generates a //, this route is normalized to /. This explains the first example of the session.
If there is a route called / in the submodule shelf_modular will understand it as “default” route, if no other segment is already placed after the module. For example:
/b-module => 'path -> /b-module/'
Same as:
/b-module/ => 'path -> /b-module/'
Module import
A module can be created only to store binds. A use case would be established when we have a Shared or Core Module containing all the main binds and distributed among all modules. To use a module only with binds, we must import it into a module containing routes. See the next example:
class CoreModule extends Module {
List<Bind> get binds => [
Bind.singleton((i) => HttpClient(), export: true),
Bind.singleton((i) => LocalStorage(), export: true),
]
}
class AppModule extends Module {
List<Module> get imports => [
CoreModule(),
]
...
}
Note that CoreModule binds are marked with the export flag export: true, this means that the bind can be imported into another module.
The module import is only for Binds. Routes won't be imported.