Web Development with Dart is Super Easy
Flutter Web has hit stable support, and is likely that which many people today think of when they hear "using Dart to write web apps." However, not only is it possible to write web apps in Dart without Flutter, it is really easy to get started.
Preliminaries
If somehow you're reading this and you don't yet have the Dart SDK, you can get it here. Follow the instructions for the operating system you have, and come back here when you're done.
Next, you'll need the webdev
and stagehand
tools available globally from your terminal. To do this, run the two following commands.
pub global activate webdev
pub global activate stagehand
The stagehand
package makes it really easy to get started on a Dart project, and webdev
lets you easily do things like serve your web app during development and build for production deployment.
Generate your Project
Stagehand has a variety of generators available for making console apps, packages, web servers and web apps. We just want a simple web app starting point, so make a new folder for your project, and from that new folder run stagehand web-simple
.
mkdir my_new_project
cd my_new_project
stagehand web-simple
After that finishes, make sure to run pub get
to pull in the dependencies that you need. You'll be greeted with a project that looks like this.
Serve and Build your Project
Serving your project locally for development is made very easy by the aforementioned webdev
tool.
Simply run webdev serve
and you'll be able to view your page at http://127.0.0.1:8080
.
When you are ready to build your app for production, run webdev build
. The resulting static site code will be built and saved into the build
folder. That folder then can be uploaded anywhere that you can serve static websites (such as Github Pages or S3).
Getting Stylish with Sass
One of my favorite things about this approach to building small, simple websites is that using scss
is nearly effortless.
First, add the sass_builder package to your project. Go to the linked page, take note of the most recent version, and then add it to your pubspec.yaml
file as one of your dev_dependencies
like so,
dev_dependencies:
build_runner: ^1.10.0
build_web_compilers: ^2.11.0
pedantic: ^1.9.0
sass_builder: ^2.1.3
After this, any scss
or sass
file will be built into a css
file with the corresponding name. So if you have a file called style.scss
in your web
folder, after it is built it will become a style.css
file in your build
folder.
Within your html files, be sure to refer to the style files by their css
name. So for example if you have a file named web/style.scss
, in web/index.html
you would include it like this.
<link rel="stylesheet" href="style.css" />
This is because you're referencing the resulting built file, not the source scss
file.
So let's prepare a little HTML that we can style (and then later use for demonstrating making HTTP requests).
<div id="app">
<main>
<img id="good-boy" />
<button id="get-good-boy">Get Good Boy!</button>
</main>
</div>
And some SCSS
in our styles.scss
file.
#app {
min-height: 100vh;
width: 100vw;
display: flex;
align-items: center;
justify-content: center;
main {
max-width: 500px;
width: 100%;
display: flex;
flex-direction: column;
img,
button {
width: 100%;
}
}
}
Handle Fetch Requests with Dio
Another great thing about making simple web apps with Dart in this way, is that you have access to the vast assortment of Dart libraries.
If, for example, you're familiar with using Dio due to working with Flutter, there's no reason why you can't use Dio to handle your fetch requests here.
First add Dio as a dependency in your pubspec.yaml
file.
dependencies:
dio: ^3.0.10
At the top of your main.dart
file, include these dependenices.
import 'dart:html';
import 'dart:convert';
import 'package:dio/dio.dart';
dart:html
will provide the querySelector
method as well as typing for various elements, dart:covert
will be used for turning JSON responses into maps, and dio
of course provides Dio
.
So within our main
function, let's grab the necessary elements and add an event listener to the button.
void main() async {
ImageElement dogImage = querySelector('#good-boy');
ButtonElement dogButton = querySelector('#get-good-boy');
dogButton.addEventListener('click', (Event event) async {
dogImage.src = await getGoodBoy();
});
}
All of the above is pretty straightforward. From there we need to actually create the getGoodBoy
button for grabbing pictures of the goodest of good boys (from a free API of dog pictures).
Future<String> getGoodBoy() async {
final uri = 'https://dog.ceo/api/breed/akita/images/random';
final response = await Dio().get(uri);
Map<String, dynamic> body = jsonDecode(response.toString());
return body['message'];
}
And there you have it! If everything works you should be greeted with something like this upon pressing the "Get Good Boy" button!
This article was originally published on dev.to.