Version 2.0.0 of the batteries-included Web application framework for Dart is coming very soon. Here's what you need to know.

Since early 2016, I've been working on and maintaining Angel, a server-side Dart Web framework designed to increase developer productivity by providing "all batteries included" out-of-the-box, and putting an emphasis on customizability and configurability.

Like all long-lived software projects (if you consider two years to be "long-lived"), Angel has, of course, gone through many, many changes. None of these features were present by package:angel_framework@1.0.0, but were all added down the line:

In addition to features added, though, many design choices have been rethought, or revealed themselves to not be the best tools for the job. Angel was initially born as a tool to help me ship full-stack apps quickly, as a one-person team. Most teams are not made of just one person, though, because teams are inherently multiple people.

Enter package:angel_framework@2.0.0.


The goal of 2.0.0 is clear - to clean up common workflows, and make Angel a more attractive choice for teams and enterprise users. This will involve, but is not limited to, the following changes:

An Overall More Mature Framework

As time went on, and Dart-the-language adopted strong-typing, many decisions that originally made sense when Dart was still gradually typed began to become liabilities, and were harder to maintain in larger projects.

Angel 2 plays by the rules of strong mode, and avoids dynamic when possible. It also removing usage of dart:mirrors by default. Other decisions were made to speed up the most common use cases, and therefore improve Angel's performance at a larger scale, both in terms of CPU time, and developer time.

Overall, version 2 intends to make Angel a batteries-included solution for projects of any size, like a Ruby on Rails for a changing Web development world.

Cross over to the DART side.

Relatively speaking, there are still not as many users of Dart on the server-side, but an attractive full-stack option that works hand-in-hand with Flutter might be just what some people need to cross over to the Dart side.

GraphQL Support

Full details can be found in my earlier announcement of GraphQL coming to Angel.

GraphQL, created by Facebook, is a query language and specification for a strong type system that can be used by clients to query back-ends through a single endpoint, and also to allow clients to specify the shape of the response expected for a given request.

By bringing a spec-compliant GraphQL implementation to Angel, teams can take advantage of GraphQL tooling, like GraphiQL and others, while also being able to work with Dart 2 code on the back-end. While this can be especially helpful when using Angel as the back-end for Flutter, Angular, or another Dart front-end, it also means that you can write your frontend in another language, like JavaScript, and interact with the server with existing, well-tested GraphQL clients, like Apollo.

No More Reflection

As was mentioned earlier, Angel will no longer require dart:mirrors by default. The main reason for this is that now, all request handlers are required to have the signature FutureOr RequestHandler(RequestContext, ResponseContext);. Before, you could pass a handler with any kind of parameters, and Angel's IoC system would inject dependencies on-the-fly. Now, to use IoC, you have to opt-in, using a function named ioc.

Now, instead of relying on the unmaintained package:container, Angel now uses a custom package:angel_container, which uses simple Maps to provide singletons and factories for dependencies, which users fetch on-demand:

// Create a container instance.
var container = new Container(MirrorsReflector());

// Register a singleton.
container.registerSingleton<Engine>(Engine(40));

// Register a factory that creates a truck.
container.registerFactory<Truck>((container) {
  return _TruckImpl(container.make<Engine>());
});

// Use `make` to create an instance.
var truck = container.make<Truck>();

// Should print: 'Vroom! I have 40 horsepower in my engine.'
truck.drive();

// We can make a child container with its own factory.
var childContainer = container.createChild();

childContainer.registerFactory<Truck>((container) {
  return _TruckImpl(Engine(5666));
});

// Make a truck with 5666 HP.
childContainer.make<Truck>().drive();

// However, calling `make<Engine>` will return the Engine singleton we created above.
print(childContainer.make<Engine>().horsePower);

Out-of-the-box, Angel uses a container implementation called EmptyReflector, which doesn't actually perform any reflection. Users who want to use the old pattern can either use the MirrorsReflector, or the code generator in package:angel_container_generator.

With these changes, not only is it much faster to run Angel handlers (as the overhead of figuring out the correct signature/params is gone), but Angel can also run in Flutter, where dart:mirrors is disallowed.

No More dynamic-ness

Along with the removal of dart:mirrors by default come many of the benefits of Dart's static typing, mainly the fact that the analyzer knows what a value is without you having to explicitly perform an as typecast.

When you have to keep track of types yourself, the burden of preventing type errors falls onto the developer. With every line, the burden increases, so once your project grows, liberal use of dynamic typing can be problematic. Just ask Python programmers about that. ;)

Obviously, weak typing is not necessarily a bad thing, but in a language that has embraced strong typing, it makes sense for an application framework to follow suit.

First-class Support for Flutter

Flutter in action.

Much of the credit for what has brought the Dart language back into the spotlight as of late can be attributed to Flutter, Google's cross-platform, Dart-based, mobile framework for building Android and iOS apps from a single codebase.

For many people, the opportunity to build a front-end and back-end using the same language and libraries, as well as the ability to share some business logic between platforms, is enticing enough that they might consider building the back-end for a Flutter app in Dart as well, potentially as an alternative to Firebase or any third-party provider.

With this in mind, Angel's Flutter widget catalog will see updates, improvements, and additions, with the hope of making app development with Angel and Flutter just as easy, if not easier than how it would be if Firebase were used as the back-end.

For all we know, a "FANG stack" might see a rise in the near future:

  • Flutter-Angel-NGinx
  • Flutter-Angel-aNGularDart
  • Flutter-Angel-aNy database-GraphQL

Return of the ORM

Those who have been in the Angel Gitter chat for some time will be familiar with package:angel_serialize, and package:angel_orm, the latter of which spent several months without real updates, and never hit an official 1.0.0.

With Angel 2, the ORM, once only for PostgreSQL, will now target both PostgreSQL and MongoDB, the two best-supported databases in Dart server applications. Future updates may see support added for RethinkDB and/or MySQL.

package:angel_orm_generator is powered by package:build and package:source_gen, and generates classes that can easily be injected into a Container and used to interact with a database, with a single layer of abstraction.

The generated ORM classes will also include a custom Service class that can be mounted on an Angel instance, and instantly turned into a RESTful CRUD API, or even broadcasted across WebSockets.

And of course, a revival of package:angel_orm means a revival of package:angel_migration for PostgreSQL and other SQL-based databases.

Better Tools for Deployment and Production

What's the point of a Web application if you never deploy it to the Web?

The Angel CLI already includes simple scaffolding for:

  • nginx - To run a reverse proxy over your application, also routing static files.
  • systemd - To run your Angel app as a daemon, simply by running sudo service start my_app.

In addition to the above, more features will be added to the CLI to facilitate deployment of Angel apps to services like Heroku, AWS, Azure, and the Google Cloud Platform.

In addition, the upcoming package:angel_production will provide more robust infrastructure for running instances in multiple isolates, facilitating message-passing, and more functionality that is useful in deployed applications.

The faster and more reliable it is to deploy an Angel application, the more likely it is that people will continue to use the framework. Therefore, ensuring the functionality of the new code will be a high priority before the official 2.0.0 release.

Conclusion

It's been a long time coming, but Angel version 2.0.0 is right around the corner, and it's not taking any prisoners. This release aims to polish the core framework, and increase the quality of the surrounding ecosystem, in order to make Angel an attractive option for developers looking to build back-ends.

There is no release date as of yet, as there is still much work to do. However, Angel is 100% open-source and community powered, so if you're interested, I highly encourage you to (and would greatly appreciate if you were to) contribute some code, even if it's just a single PR, or documentation assistance.

Feel free to join the Gitter chat for news, or suggestions as to what to help with.

Looking forward to the official release very soon! Thanks to all in the Dart community for believing in Angel, and to all who have offered words of encouragement or pull requests. Your help truly goes a long way, and you are appreciated.