Dart, primarily known for powering Flutter, has been steadily gaining traction on the server side. Inspired by the many Reddit threads with people asking about the state of server-side Dart, I decided to check out the latest state of server-side Dart.
Here, I'll dive into the capabilities and potential of these technologies, providing insights for developers interested in building Dart server applications.
This article is split into 3 sections. The first section is all about already established players like Serverpod and DartFrog. The second section covers less-used frameworks, active forks of abandoned frameworks like Aqueduct and Angel, and some new frameworks. The third and last section is reserved for real projects which are using Dart on the backend in production.
Let's start!
Serverpod
Labeled as "The missing server for Flutter", Serverpod is a powerhouse of this list. It allows you to write your server-side code in Dart, automatically generate your APIs, and hook up your database with minimal effort.
The list of features is extensive:
Postgres database
Migrations and relations tooling
Code generation for your protocol and client-side code
Logging
Built-in caching
ORM
Out-of-the-box social logins and file upload
Data streaming
Task scheduling
Health checks
VS Code extension
To use Serverpod in your app, define endpoints:
import 'package:serverpod/serverpod.dart';
class HelloEndpoint extends Endpoint {
Future<String> hello(Session session, String name) async {
return 'Hello $name';
}
}
And then use them in your Flutter app:
var client = Client('http://$localhost:8080/')
..connectivityMonitor = FlutterConnectivityMonitor();
var result = await client.example.hello('World');
That's it. Everything else is taken care of by the framework using code generation. Serverpod is the most powerful on this list in terms of what you get out of the box and the available tooling. It's still in active development and there is a lot more to come.
Shelf
A minimal, modular, and adaptable web framework inspired by Connect(for Node.js) and Rack(for Ruby). It's developed and maintained by the Flutter team.
A Shelf application is composed of a sequence of handlers and middleware. Handlers are functions that handle requests and return responses, while middleware functions wrap handlers and add additional functionality to them. The Pipeline class is used to create a chain of middleware and handlers.
Because it was designed with extensibility in mind, there are many plugins available to complement its functions. The most popular are:
Router(shelf_router)
Proxy(shelf_proxy)
Serving static files(shelf_static)
CORS support(shelf_cors_headers)
WebSockets(shelf_web_socket)
Hot Reload support(shelf_hotreload)
Shelf is very easy to get started with a provides and there is a lot of documentation online to help you get started and resolve issues. An example of a shelf server might look like this:
import 'dart:io';
import 'package:shelf/shelf.dart';
import 'package:shelf/shelf_io.dart';
import 'package:shelf_router/shelf_router.dart';
final _router = Router()
..get('/', _rootHandler)
..get('/echo/<message>', _echoHandler);
Response _rootHandler(Request req) => Response.ok('Hello, World!\n');
Response _echoHandler(Request req) => Response.ok('${req.params['message']}\n');
void main(List<String> args) async {
final handler = Pipeline().addMiddleware(logRequests()).addHandler(_router);
final server = await serve(handler, InternetAddress.anyIPv4, 8080);
print('Server listening on port ${server.port}');
}
DartFrog
Dart Frog is a wrapper around shelf
with the addition of mason
built by Very Good Ventures. Mason is a tool for creating and consuming reusable code templates.
The focus of this framework is on optimizing the process of building backends that aggregate, compose, and normalize data from multiple sources.
It comes with a prebuilt routing system which relies on folder structure to generate the router using mason
. Other features include:
Built-in dependency injection
Hot Reload
Static files & Websocket support
DevTools & VS Code plugin
Docker support
The same echo request can be written in DartFrog like:
import 'package:dart_frog/dart_frog.dart';
Response onRequest(RequestContext context) {
final params = context.request.uri.queryParameters;
return Response(body: '${params['message']}\n');
}
In the future, the VGV plans to include API client code generation, Open API specs generation, a testing library, and a CLI tool for deployment.
Alfred
Alfred is designed to be a simple and easy-to-use framework that allows developers to focus on writing their app logic without getting bogged down in boilerplate code. It's well known for its express.js-like syntax, making it familiar to developers coming from a Node.js background.
Key Features include:
Simple routing with route parameters and body parsing
Middleware for handling authentication, error handling, and other tasks
Static file serving
File uploads and downloads
WebSocket support
Custom type handlers for returning non-standard data types
Logging and debugging tools
Multiple Isolates support
By checking out the code you can very easily spot the express.js style syntax:
import 'package:alfred/alfred.dart';
void main() async {
final app = Alfred();
app.get('/example', (req, res) => 'Hello world');
await app.listen();
}
The author was so nice to provide a 6-part Youtube playlist explaining how to use the library and an article explaining how to deploy your Alfred server on Google Cloud Run.
Overall, Serverpod is the most complete framework available, while others focus on providing a bare-bones structure and leave it to the developer to combine the parts needed. The table below summarizes all the features of the covered frameworks.
Others
Apart from the previously mentioned frameworks, there are also less known and less used frameworks and tools that are available. The list is presented in no particular order.
-
The Dart implementation of gRPC which puts mobile and HTTP/2 first. It's built and maintained by the Dart team. gRPC is a high-performance RPC (remote procedure call) framework that is optimized for efficient data transfer.
In gRPC, a client application can directly call a method on a server application on a different machine as if it were a local object, making it easier for you to create distributed applications and services.
Companies like Square, Netflix, and About You use it extensively to simplify development and increase performance.
-
The continuation of the legacy of the Aqueduct deserves a special mention. Aqueduct is a powerful HTTP framework for building REST APIs built by Stable Kernel with the support of the Dart team.
Robust and extensible features included are multi-threaded architecture, fluid routing, statically-typed ORM, OAuth 2.0 server, productive request bindings, integrated test library, and OpenAPI 3 integration. It was shut down due to the team's inability to keep up with the Dart changes (mainly null safety) and a lack of funding to support the team maintaining it.
-
The fork of the archived Angel framework migrated to support null safety. The goal is to streamline development by providing many common features out of the box. A comprehensive set of features offers authentication, ORM, GraphQL, dynamic web page rendering, caching, NoSQL support, WebSockets, and hot reloading.
Dartness is a Spring Boot and Nest.js-inspired framework powered by
shelf
.Pharaoh is another Express.js-inspired framework compatible with
shelf
middleware
Server-side Dart in Production
No ecosystem is complete without examples of real-world apps and websites in production which use a backend powered by Dart. The most notable examples are pub.dev
and MyOpNotes.
Conclusion
As server-side Dart continues to mature, these technologies offer a glimpse into a future where Dart is a first-class citizen not just in mobile app development. Companies have already started to figure out the advantages that single language stacks can provide.
Flutter and Serverpod form a very powerful combination for startups because you can use the same language and the same people who can fully emerge into product creation without the hassle of managing multiple stacks and teams. I think we will start to see more of this in the future.
If you have enjoyed this deep dive into the current state of server-side Dart, make sure to like and follow for more content like this.