Web Development with Dart is Super Easy
Tags: dart, webdev, beginners
Published: 2021-04-15 07:53:00

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](https://dart.dev/get-dart). 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.

![A screenshot showing the file structure of a newly created stagehand project.](https://dev-to-uploads.s3.amazonaws.com/i/w6qeziethtte1xqoa4ci.png)

# Serve and Build your Project

Serving your project locally for development is made very easy by the aforementioned `webdev` tool.

![Terminal output from running webdev serve.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/amx636xhlb1mdj533712.png)

Simply run `webdev serve` and you'll be able to view your page at `http://127.0.0.1:8080`.

![Your Dart app is running.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d7l4bn7bgyin4l8693bu.png)

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](https://pub.dev/packages/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,

```yaml
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.

```html
<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).

```html
<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.

```scss
#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](https://pub.dev/packages/dio) as a dependency in your `pubspec.yaml` file. 

```yaml
dependencies:
 dio: ^3.0.10
```

At the top of your `main.dart` file, include these dependenices.

```dart
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.

```dart
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).

```dart
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!


![The Goodest of Good Boys](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jdqc2rf0o5a01zyc2udq.png)