A full-stack Dart application using Flutter on the client and
shelf
on the server. The Flutter app
itself is still the counter app, but the actual number is stored on the server
and incremented over HTTP using transport data classes understood by both the
Flutter client and shelf server.
The goal of this sample is to demonstrate the mechanics of sharing business logic between a Flutter client and a Dart server. The sample also includes a slightly modified Dockerfile which is required to build a Docker image from a Dart app containing nested packages.
The sample's project structure is as follows:
code_sharing/
# Flutter app
client/
lib/
...
pubspec.yaml
...
# Shelf
server/
bin/
server.dart
pubspec.yaml
Dockerfile
# Common business logic
shared/
pubspec.yaml
lib/
...
Recreating this introductory project for yourself can be done in several steps.
-
Create a parent directory, likely sharing a name with your project or product, which will contain everything.
-
Within that directory, run
flutter create client
. You may also name this Flutter projectapp
,mobile
,<project-name>-app
or anything else that seems appropriate. At this point, your folder structure should look like this:my_project/ client/ lib/ main.dart pubspec.yaml ...
-
From the same location where you ran
flutter create
, rundart create -t server-shelf server
. You may also name this Shelf project,backend
,api
,<project-name>-server
, or anything else that seems appropriate. At this point, your folder structure should look like this:my_project/ client/ lib/ main.dart pubspec.yaml ... server/ bin/ server.dart Dockerfile pubspec.yaml ...
-
Enter your server directory (
cd server
), and rundart create -t package shared
. You may also name this packagecommon
,domain
,<project-name>-shared
, or anything else that seems appropriate. At this point, your folder structure should resemble the sample:my_project/ client/ lib/ main.dart pubspec.yaml ... server/ bin/ server.dart shared/ lib/ src/ ... shared.dart pubspec.yaml ... Dockerfile pubspec.yaml ...
-
Next, begin granting access to your shared code by making the following edits to your Flutter app's
pubspec.yaml
file. Open that file (client/pubspec.yaml
) and add the following dependency under thedependencies
block:dependencies: # Add these two lines: shared: path: ../server/shared
-
Next, finish granting access to your shared code by making the following edits to your server's
pubspec.yaml
file. Open that file (server/pubspec.yaml
) and add the following dependency under thedependencies
block:dependencies: # Add these two lines: shared: path: ./shared
-
The final step is to adjust your
Dockerfile
, as it can no longer successfully rundart pub get
after only copying over thepubspec.yaml
file (that command now requires the entirety of yourshared
directory to be present.
- Find the line that says
COPY pubspec.* ./
, and change it toCOPY . .
.
With that, you're ready to build and run the app.
To run the sample, or an equivalent you've reconstructed yourself, choose a runtime method below based on your needs.
In one terminal window, run the following commands:
cd my_project/server
dart run bin/server.dart
In a separate terminal window, run the following commands:
cd my_project/client
flutter run
Note: If you named your mobile client and backend servers something other than
client
andserver
, you will need to substitute in those values above.
To build your server's Docker image, run the following commands in a terminal window:
cd my_project/server
docker build . -t my_project_server
To run that image as a Docker container, run the following commands in a terminal window:
docker run -it my_project_server
If you have docker-compose
installed on your machine, you can run the following command to build and
launch your server:
cd my_project
docker-compose up -d
And then later stop the server with:
docker-compose stop