Angel3 Jael
Installation
In your pubspec.yaml:
dependencies:
angel3_jael: ^10.0.0
Usage
Just like mustache and other renderers, configuring Angel to use Jael is as simple as calling app.configure:
import 'package:angel3_framework/angel3_framework.dart';
import 'package:angel3_jael/angel3_jael.dart';
import 'package:file/file.dart';
AngelConfigurer myPlugin(FileSystem fileSystem) {
return (Angel app) async {
// Connect Jael to your server...
await app.configure(
jael(fileSystem.directory('views')),
);
};
}
package:angel3_jael supports caching views and minified html output by default, to improve performance. You might want to disable them in development, so consider setting these flags to false:
jael(viewsDirectory, cacheViews: false, minified: false);
Keep in mind that this package uses package:file, rather than dart:io.
The following is a basic example of a server setup that can render Jael templates from a directory named views:
import 'package:angel3_framework/angel3_framework.dart';
import 'package:angel3_framework/http.dart';
import 'package:angel3_jael/angel3_jael.dart';
import 'package:file/local.dart';
import 'package:logging/logging.dart';
void main() async {
var app = Angel();
var fileSystem = const LocalFileSystem();
await app.configure(
jael(fileSystem.directory('views')),
);
// Render the contents of views/index.jael
app.get('/', (req, res) => res.render('index', {'title': 'ESKETTIT'}));
app.fallback((req, res) => throw AngelHttpException.notFound());
app.logger = Logger('angel')
..onRecord.listen((rec) {
print(rec);
if (rec.error != null) print(rec.error);
if (rec.stackTrace != null) print(rec.stackTrace);
});
var http = AngelHttp(app);
await http.startServer('127.0.0.1', 3000);
print('Listening at ${http.uri}');
}
To apply additional transforms to parsed documents, provide a set of patch functions, like in package:jael3_preprocessor.
Members of values
{{ repo.name }} reads name of repo through the app's reflector, before the ways jael3 has (a key of a Map, a member of a core type, a key of toJson()). To read the members of your classes without dart:mirrors, as in a program compiled with dart compile exe, generate their reflection data with angel3_container_generator: mark them @injectable, add a part directive, run dart run build_runner build, and give the app a StaticReflector of the data:
@injectable
class Repo extends Model {
final String name;
Repo(this.name);
}
var app = Angel(reflector: StaticReflector.combine([modelsReflection]));
await app.configure(jael(fileSystem.directory('views')));
A memberResolver given to jael is asked first, for members of values the reflector does not describe.
Performance Optimization
For handling large volume of initial requests, consider using jaelTemplatePreload to preload all the JAEL templates
into an external cache.
var templateDir = fileSystem.directory('views');
// Preload JAEL view templates into cache
var viewCache = <String, Document>{};
await jaelTemplatePreload(templateDir, viewCache);
// Inject cache into JAEL renderer
await app.configure(
jael(fileSystem.directory('views'), cache: viewCache),
);
Migrating from 9.x to 10.0.0
The breaking changes of each release are listed in the CHANGELOG. Those of 10.0.0 that may need changes in an app:
- Relative paths: a view is resolved relative to its own directory, where it was the views directory, so the
extendandincludetags of a view in a subdirectory are read relative to that subdirectory, as those of its parents are. Change paths such as<extend src="layouts/main.jael">inviews/admin/page.jaelto be relative toviews/admin, e.g.<extend src="../layouts/main.jael">. - Members of values:
{{ repo.name }}readsnamethrough the app's reflector, asjael3no longer usesdart:mirrors. See Members of values.