Using Flutter for building iOS and Android applications brings with it some advantages over other cross platform solutions such as Xamarin.Forms or React but one of the more interesting developments to keep an eye on is the support for running Flutter apps on the web. In this post we’re going to create a basic Flutter … Continue reading “Create, Build and Publish a Flutter Web App”
Using Flutter for building iOS and Android applications brings with it some advantages over other cross platform solutions such as Xamarin.Forms or React but one of the more interesting developments to keep an eye on is the support for running Flutter apps on the web. In this post we’re going to create a basic Flutter app and show it running locally. We’re then going to publish it out to Azure blob storage (and accessed via the Azure CDN) to demonstrate that a Flutter web app runs purely in the browser and can be hosted on a static endpoint (i.e. no server side code!).
Installation and Setup
Currently support for Flutter on web requires the webdev package but before installing the package it’s important to make sure that you’ve upgraded the Flutter SDK to the latest version. Run the upgrade command either from a command prompt, or from the terminal console within Visual Studio Code.
Next, we need to activate the webdev package using the following command
flutter packages pub global activate webdev
Note there are a couple of things that I ran into. I’m running this all on Windows 10, and I was trying to activate the webdev from within Visual Studio Code. I had opened a new window, which meant I didn’t have a Flutter project open. When I ran the above command I saw an error because apparently there was no pubsec.yaml file.
PS C:\> flutter packages pub global activate webdev
Error: No pubspec.yaml file found.
This command should be run from the root of your Flutter project.
Do not run this command from the root of your git clone of Flutter.
After hunting around a bit I found that you can omit “packages” from the command in order for the webdev package to be retrieved and activated (only required to be done once thanks to the global parameter):
flutter pub global activate webdev
This command might take a minute or so to run. On completion, I saw an interesting notice regarding the cache folder for packages:
Installed executable webdev.
Warning: Pub installs executables into C:\Source\tools\flutter\.pub-cache\bin, which is not on your path.
You can fix that by adding that directory to your system's "Path" environment variable.
A web search for "configure windows path" will show you how.
Activated webdev 2.5.0.
Currently, the only folder that I’ve included in the Path environment variable is the bin folder for where I’d extracted the Flutter SDK (in my case c:\source\tools\flutter\bin). This was the first time I’d seen this warning and it made me wonder what other folders I needed to include. Following the direction of this post, coupled with the above warning I added the following paths to the Path environment variable.
Note: Make sure you restart any command prompt, terminal window and Visual Studio Code after saving the changes to the Path environment variable in order for it to take effect.
At this point you should be good to go ahead and start creating your new Flutter for web project.
Flutter: New Web Project
From the command palette in Visual Studio Code you can select Flutter: New Web Project. This will go ahead and create your new project with a folder structure that will seem familiar if you’ve been building Flutter apps already. What is different is that after creating the project, it opens index.html in the code editor – you can close this as you probably don’t need to mess with this page initially.
You’ll also notice that there are two main.dart files, one in the web folder, and one in the lib folder. If you inspect these individually you’ll notice that the one in the web folder is an entrypoint (you can see main.dart.js being invoked from index.html which is located in the same folder) which initializes the web platform before calling the main() function located in main.dart in the lib folder. Inside the main.dart in the lib folder you’ll see the layout of a very basic “Hello World” Flutter app.
Running Flutter for Web
Of course, the first thing you’ll want to do is to run the Flutter app, which can be done easily in Visual Studio Code by pressing F5. The first time you attempt to run the project you may be prompted to Select Environment. Select Dart & Flutter to proceed.
Unfortunately this then greets me with a dialog saying that there are build errors:
NOTE: If you get build errors on a newly created Flutter web project. Run flutter upgrade from the terminal within Visual Studio Code, or from the command prompt.
After upgrading my Flutter web project, pressing F5 and selecting the environment, builds and runs the project. Your default browser, Chrome in my case, will be launched in order to display your Flutter web project. The first run does take a while, so don’t close Chrome if it just seems to be blocked loading the project the first time.
Publishing a Flutter Web App
This command will generate a build folder, which will include index.html and main.dart.js, along with any other files that your Flutter web app will require in order to run. All you need to do is to copy the contents of the folder to the appropriate folder on your web server.
In my case I didn’t want to spin up a web server, or even a new endpoint in Azure, just for my simple Flutter web app. Instead I decided to copy the necessary files up to a folder in an existing Blob storage account (in fact it’s the very same storage account that serves the images for this blog). In front of this storage account I use an Azure CDN endpoint in order to improve performance and caching of the content. The net result is that any file that’s retrieved from https://blogimages.builttoroam.com is served from the CDN cache, if it exists. If it isn’t already in the CDN cache, it’ll be pulled from https://nicksblog.blob.core.windows.net, which is the underlying blob storage endpoint, added to the CDN cache and then served up. The point I’m making is that the following Flutter web app (it’s not an image – you can click on it to launch it in a separate tab) is being served from a static service, rather than an actual web server.
Whilst Flutter for web is still in preview, the simplicity of using the Flutter layout engine for building apps for the web will be a game changed for those of us who have hated the prospect of developing using CSS and JS. Hopefully as it gets closer to a final release there will be an ability to have a single project that’s able to build for iOS, Android and Web without having to have separate projects.
Just out of interest, here are a couple of other articles worth reading on Flutter for the web:
This post will cover the basics of how to get started with Flutter. It’ll provide you with an overview of your first Flutter app and will give you some pointers on how to get familiar with Flutter, Dart, the tools and ecosystem around building apps using the Flutter SDK. Enough about what you’ll take out … Continue reading “How to Get Started with Flutter”
This post will cover the basics of how to get started with Flutter. It’ll provide you with an overview of your first Flutter app and will give you some pointers on how to get familiar with Flutter, Dart, the tools and ecosystem around building apps using the Flutter SDK. Enough about what you’ll take out of this post, let’s get into it by starting at the beginning.
What is Flutter?
According to the technical overview provide that’s part of the documentation at Flutter.dev, Flutter is a “mobile app SDK for building high-performance, high-fidelity, apps for iOS and Android, from a single codebase”. However, there has been a lot of discussion about Flutter being used for Web and embedded as a solution for desktop apps on MacOS, Windows and Linux.
Before we get too much further into what Flutter is, let’s back up a bit and try to understand why Flutter is needed. A number of years ago it became evident that for a mobile app to be successful it needed to be available on at least iOS and Android. The sheer cost and difficulty of keeping two entirely separate codebases up to date meant that most companies look to some form of cross platform solution. Unfortunately the cross platform, until recently has been a bit hit and miss. On one end you had solutions such as PhoneGap / Cordova that provided a native shell around a web app – these apps typically suffered from poor usability, were often slow and felt like they were a mobile website. Then you had solutions like Xamarin that offered native-like performance but without the ability to share the user interface layer. More recently Xamarin.Forms and ReactNative both offer an abstraction for the user interface that relies heavily on the native platform controls. The abstraction layer is often a point of contention amongst developers who often find themselves spending considerable time adapting the platform controls to get consistency in their apps across the different platforms and devices. In addition, the abstraction layer can become a bottleneck resulting in performance and at times stability issues.
What’s interesting about Flutter is that it takes ownership of the entire page and is solely responsible for rendering each widget that makes up the app using Skia. This approach frees developers up from a lot of the platform idiosyncrasies whilst still giving them the a uniform developer experience for defining the user interface, navigation and behaviour of the app in a consistent manner using Dart.
Before we discuss Dart, it’s worth pointing out a couple of resources that help understand the background of Flutter:
An interesting article, entitled Why Flutter Uses Dart, from back in 2017 provides a number of points as to why Flutter uses Dart:
Dart supports AOT allowing it to optimise down to native code in order to perform well in production.
Dart supports JIT, allowing a fast developer cycle, namely hot reload.
Dart supports the declaration of layout for Flutter apps without the need of a separate markup language (the article Making Dart a Better Language for UI delves into this in more detail).
Dart borrows many existing static and dynamic language features from other languages that developers are already familiar with.
As you get into developing Flutter apps it’s worth spending a bit of time exploring the Dart programming language – there are a number of features that have been added to make it easier to declare the user interface for Flutter apps.
To get familiar with Dart, head over to DartPad where you can experiment with different language features. On the left side you can write out some Dart code; hit the Run button; and see the output displayed in the right pane.
At this point I’m going to jump right in and create an app. I’ll walk you through the process of creating and running an app, highlighting some of the tools and steps you should be aware of. I’ll be doing on a Windows PC using Visual Studio Code (VS Code) but the general process is the same if you’re on a different platform, or using a different IDE.
Talking of IDEs, the Flutter SDK works well with both Android Studio and Visual Studio Code. Rather than step you through getting the tools setup, head over to the installation instructions, pick your platform and work your way through the steps to download and install both your IDE (Android Studio or VS Code) and the Flutter SDK.
Flutter: New Project
Let’s get started with a new Flutter project – I’m going to walk through using VS Code but the process should be similar if you’re working with Android Studio. We’ll get started with Flutter using the VS Code Command Palette (Use Ctrl+Shift+P or from the View menu select Command Palette). Assuming you’ve already got the Flutter and Dart extensions installed (go here if you haven’t set these up) if you type ‘flutter’ you’ll see a list of commands that you can invoke that relate to Flutter.
Select “Flutter:New Project” either using the mouse or since it’s the first item you can just press Enter. Next you’ll be prompted to give you app/project a name. Flutter requires it to be in lowercase and use underscore to separate words (i.e. no spaces). In this case we’re just going to be walking through the default project that the Flutter SDK creates which is a simple counter, so we’ll call our project flutter_counter.
After naming your Flutter project you’ll be prompted for a location on your computer where you want the source code to be located. Once you’ve specified a folder, VS Code will go ahead and create your Flutter project. You’ll see the project structure, including files and folders appear in the Explorer on the left, and you’ll see a progress notification appear in the bottom right corner.
Once your project has been created the notification in the bottom right corner of the screen will update to indicate that “Your Flutter project is ready!”
A couple of things to note here:
The notification also includes instructions on how to run your Flutter app – You can press F5 to start running.
Behind the notification you can see in the Output window that there are some additional instructions. It’s worth scrolling back up through the output and having a read. For example, and we’ll come back to this later, the actual command executed to create the Flutter project was “flutter create –ios-language objc –android-language java” which specifies the use of Objective-C and Java for any platform specific code.
At the end of the create process it also checked to see whether all the Flutter tooling is correctly setup. In the above screenshot you can just see the last of these checks where it indicates that there is no connected device – we’ll resolve this in a second when we launch the Android emulator. These checks are useful for diagnosing if anything is wrong with your setup and you can run Flutter Doctor for more information/assistance.
Show Me It Running
In VS Code you can press F5 to run the Flutter app. As I mentioned in the previous section, currently I don’t have any devices attached. This means that I’ll see the following prompt appear at the top of the screen. If you have a connected physical device you’ll be able to select
that device at this point.
Picking one of the existing emulator images will launch that emulator and will subsequently build and deploy the flutter_counter app to the emulator. Note that this process can take a few minutes the first time you do it, so be patient and keep an eye on both the Debug Console window and the notifications – these will update to let you know what VS Code is doing. Once your application is deployed and running you’ll see a mini toolbar appear at the top of the VS Code window.
The toolbar allows you to perform typical debugging actions such as pausing execution, step over, step into and step out. It also allows you to trigger a hot reload (we’ll come to this shortly), restart the app and stop the debugging session. In addition to the toolbar you might also see a notification to Open DevTools – don’t worry if you miss this, or any, notification as you can access them again from the status bar at the bottom of the VS Code window by clicking on the bell icon on the far right side.
You can click on the Open DevTools button in the notification to bring up the Dart DevTools. At any stage in the future if you want to bring up the Dart DevTools you can just type “devtools” into the Command Palette to find the appropriate command. The Dart DevTools are incredibly useful as they give you an immediate view of all the widgets that make up your app at any given point in time. You can click on widgets in the tree on the left and see various properties of that widget in the right pane.
There are a host of different features of the Dart DevTools that you should explore and will assist you diagnosing and improving your app. Switching back to VS Code, if you look at the editor window you’ll see the code for the flutter_counter app. As this is a very basic Flutter app, all the Dart code is in a single file. However, you’ll want to make sure you establish the structure of your project so that as your application grows it’s easy to navigate the file/folder structure.
A couple of things you’ll notice about the editor window:
The code is coloured to highlight Dart keywords, class and property names
There are vertical lines, making it easy to identify where code blocks start and end
Code is nicely indented to again make it easy to identify code blocks
As you start to write your application, you’ll want to make sure you keep your code nicely formatted. The Flutter extension for VS Code comes with a great code formatter which you can invoke either from the menu/context menu or using the Shift+Alt+F keyboard shortcut.
As with most modern programming languages, Dart/Flutter offers a high fidelity debugging experience. By this I mean that you can set breakpoints where the code execution will be paused, allowing you to inspect variables and the call stack, before stepping forward line by line.
To set a breakpoint in VS Code you simply need to click in the empty space immediately to the left of the line number in the editor window. Alternatively put the cursor on the line where you want to set a breakpoint and press F9 (or set a breakpoint via the Debug menu). In each case a red dot will appear to the left of the line number indicating that a breakpoint has been set. The following image shows the state when a breakpoint has been hit.
The main editor window highlights the line that execution has been paused at (i.e. just prior to that line being executed). At this point you can use the left windows to inspect local variables and observe the call stack. You can then use familiar debugging actions such as Step Over (F10), Step Into (F11) and Step Out (Shift+F11) to progress through the code.
One of the big features that everyone loves to talk about is the ability to make changes and for them to be reflected immediately in the running app. Coming from a Windows/.NET background the big fuss around hot reload seems to be blown out of proportion – we’ve had Edit-and-Continue for as long as I can recall. Admittedly this hasn’t been available, until recently, for Xamarin.Forms developers.
Anyhow, to give you an idea of what’s possible, lets change the text that displays the counter value in our flutter_counter app. Here’s the current code.
With the flutter_counter app running, let’s change the code to the following:
'Current count is $_counter',
When you save the file, you’ll see that the app automatically picks up the changes and updates the running app. On the left is the original app; on the right is the app with the updated Text – updated without having to stop and restart the app. Note that the count, which is part of the state of the app, remains the same.
How Should You Get Started With Flutter?
So far we’ve covered an introduction to Flutter and Dart, and walked through some of the tools as part of creating a simple counter app. The question is where should you go next to learn more about Flutter?
The best way to build skills and familiar is just to get started with Flutter – get the tools and start building an app. Of course, you’ll want some assistance along the way, so here’s just a few resources that you may want to take advantage of.
Online Courses on Flutter
If you want to follow more structured learning, there are a bunch of online courses that cover the basics and will help you get started with Flutter. The following is a selection of some of the more popular courses.
As you can see the world of Flutter is rapidly evolving – there are a ton of great resources produced by Google and the community alike. Now’s the time to get familiar with Flutter and start building amazing cross-platform applications.