Introducing the Angel Framework

The Angel Framework Dart is a well-designed language with an extensive standard library and a dedicated VM, but it traditionally has only had strong support for the client side of Web applications. Angel was born to fill the void, and finally reached version 1.0.0 in 2017, after over a year of development.

What is Angel?

Angel is a highly-extensible, full-featured server-side Dart framework with support for:

  • Dependency injection
  • Complex routing
  • WebSockets
  • And much more...

Angel is designed to expedite the development of full-stack applications, so in addition to its server-side facilities, the framework also ships a client library that not only supports plain HTTP, REST, and WebSockets, but also provides an API nearly identical to the one on the server. Model classes do not have any io or mirrors dependencies, so you can safely use the same files to handle data on both ends of your project.

main() async {  
  var app = new Angel();
  app.get('/', () => 'Hello, world!');

  var server = await app.startServer(InternetAddress.LOOPBACK_IP_V4, 8080);
  // ...
}

How to use Angel

Thanks to the Angel CLI, scaffolding projects is as simple as running one shell command:

$ angel init my_project

Additional functionality of the CLI includes generating services, plug-ins, and validators, among other things. Of course, you must install it first:

$ pub global activate angel_cli

Angel's wiki contains thorough documentation on virtually every feature of the framework. More specific documentation on supplemental packages or plug-ins can be found in their respective Github repositories, as well. In addition, Angel's API's are documented in their code's comments, so it is easy to find explanations and examples on the Dartdocs site.

Angel opposed to other Frameworks

There is a handful of other frameworks offering functionality similar to Angel. Angel holds its own very well against competing libraries, and in several areas holds superior capability.

Most frameworks provide some type of ORM that combines data access with type safety; Angel is no different. However, rather than marrying users to any one specific database, Angel's data access is performed through an abstract service API, and supports any data store without a change in business logic. Out-of-the-box, Angel currently provides support for MongoDB, RethinkDB, and in-memory stores, and writing custom services is as easy as writing a regular Dart class. As mentioned earlier, model classes used with Angel can be used on any Dart platform. Other frameworks' base model types have server-side dependencies, which means that you ultimately have to rewrite the models, and manually keep them in sync with one another.

Server-side Dart frameworks tend to be declarative and annotation-driven, and thus depend heavily either on code generation, which effectively adds an extra build step to your application, or on reflection, which can lead to lower performance at runtime. Angel leans further toward the imperative paradigm, and only requires reflection on controllers and routes at application startup. Data serialization can easily be patched to use JSON.encode instead of reflection, to prevent your application from slowing down once it starts processing large amounts of data. In addition to the existing optimizations to dependency injection, users can also manually inject dependencies to no detriment:

automaticRoute(Angel app, WebSocketContext socket, User user, {String optionalParam}) async {  
  // Dependencies are provided automatically
}

manualRoute(RequestContext req, res) async {  
  // Manually inject
  var app = req.app;
  var socket = req.grab<WebSocketContext>('socket');
  // ...
}

Lastly, Angel is easy to extend with custom plug-ins. There are mechanisms in place to hook every part of the request or application lifecycle, and wiring up plug-ins that react to these is as simple as calling app.configure:

myPlugin(Angel app) async {  
  // Global middleware, run before every request
  app.before.add((req, res) async {
    res.headers['Angel'] = 'framework';
    return true;
  });
}

main() async {  
  var app = new Angel();
  await app.configure(myPlugin);
  // Or... Run it just before server startup
  app.justBeforeStart.add(myPlugin);
}

A similar plug-in architecture is not present in other Dart frameworks. This is a page straight out of Express.js's book, a major influence on Angel.

Conclusion

Angel offers a wealth of functionality to server-side projects, and is definitely worth considering for your next venture. Ultimately, its goal is to be the best option for full-stack development not only for Dart developers, but for developers from other platforms who want to build applications with a language as advanced as Dart.

Try it out! Check out the Github repository, and may even leave a star. ;)

Feedback (and issues) are welcome!