In this article, we’ll explore the real capacity of Flutter in compiling to different platforms, mobile, web and desktop with the same source code.
This post was originally posted on blog.juliobitencourt.com.
The famous GitHub stars ⭐️ on open-source projects are considered by many people a popularity meter, and although a project having more stars than others doesn’t mean anything, at least it shows that the community is enjoying and supporting the technology.
So through a simple application, we’ll measure the stars run of the main technologies capable to build mobile multi-platform apps. The layout has nothing extraordinarily different from what a normal Flutter app doesn’t have. That’s why I won’t explain how does the source code or resources work (only some key points).
The app contains:
- Flare animation
- HTTP requests
- Json parsing with
- Simple adaptable layout
- Hyperlinks (external urls)
The image below shows the final result, and you can access the app on GitHubPages at jhbitencourt.github.io/stars-race to give it a look. Now let’s explore the different platforms.
Everybody is already used to how to create a mobile Flutter project, and independent of the channel you are in, the resources will work fine on both Android and iOS.
The idea is based on making requests to the GitHub API to gather information about the open-source projects, and their stargazers count. The repositories I’m using are listed below, feel free to send a PR and add a different mobile tech.
You can try accessing https://api.github.com/repos/flutter/flutter for example. The API will bring lots of data about the project, but I’ll use only a few, as like
json_serializable is used to parse the json result. And the app state is managed with
rxdart. So, based on the current stream state, we can show a loading, an error message, or the result data.
For the loading, we can show a stars animation built with Flare and available here.
And in case of any error, this is the message shown:
This is because the GitHub API has a limit of 60 requests per hour to a single IP, so the limit can be reached. More about this. Some places of the app can have a hyperlink to an external page, this is a common task and easily done on mobile (Android and iOS) with the help of url_launcher, from the Google team.
With all setup, we can run to mobile (smartphone and tablet) and it will work as expected:
Flutter for the web, also known as Hummingbird, is currently in tech preview (not even in alpha), so definitely you must not use it in production. But nothing can hold us from testing it and being amazed.
Initially, the web part was separated on a different project flutter_web, which needed a more complex setup, besides problems with conflicts of package naming. But since September 10, all the source code was unified into the original SDK, and available in the master channel, once it is not stable.
So to use it, you must be at the master channel, and preferably updated with the last release.
flutter channel master && upgrade
flutter config --enable-web will enable the web configuration. After that, to enable flutter web on a created project you can just go to the folder and run
flutter create ..
This will create a
web folder with a file
index.html, responsible to link the
main.dart with the final
Now when running
flutter devices two new devices are listed:
web-server will create a local server, configured to a given port by Flutter, this same port can be accessed by any browser to try the app.
flutter run -d web-server
On the other hand, the
chrome device will obviously run on Chrome an open a bridge to allow debugging the app.
flutter run -d chrome
This is enough to see the same app running on web! Even the initial Flare animation worked out-of-the-box (although some animations may not work properly). Definitely, many things still have a mobile-like look and feel, and there is much work to be done. An example is the mouse pointer, that when hovers a clickable object, is expected to change its visual.
Currently, we don’t have this kind of behavior out-of-the-box, and to do so is necessary a kind of a hack. For that, inside
index.html we can define an id to the body of the page:
Now it is possible to reference the
body inside a widget called
Listener already provides many callbacks to mouse actions, notice that
onPointerExit are listed as deprecated, which will change in the future, see the issue. Now when using this custom widget and hovering the specific areas, our cursor type will change through the
body element reference.
This works perfectly when compiling to the web, but it will break our mobile code since when compiling to mobile we’re not allowed to use the package
dart:html. The current solution is to use the package universal_html, which works as an embed of the real
Now we create another widget called
InkWellPlatformAware that extends from
InkWell and inserts
HoverAware in case we’re running on web, validated through the
By using it, we have the expected behavior:
When clicking though, the external link won’t be opened, because the
url_launcher plugin doesn’t work for the web. And for our feature to work, is necessary make use of
Now everything is perfectly ready to run on the web:
The GitHub Pages is a good option to host our flutter web page. And for that, we first need to build for the web:
flutter build web
The generated files are in
So all we need is to create a folder called /stars-race inside this repo and put all the generated files there, like this. And that’s it , go ahead and access jhbitencourt.github.io/stars-race, so easy, isn’t it?
The mission now is to run the same app on Desktop. And if flutter web is in tech preview, the desktop embed is even more immature by the time I’m writing this. The most part of the source code are still being kept in a separate repository called flutter-desktop-embedding.
To integrate it with our project is also necessary to be on the last release of the master channel. The steps I’ll follow bellow are valid to windows as example, but can easily be adapted to linux/mac, to more information you can see at the readme from the original repo or the desktop page.
To avoid any troubles, run the prompt from windows on admin mode. And once in the master, is also possible to enable the desktop config running
flutter config --enable-windows-desktop. Now with
flutter doctor -v it will show up some warnings asking for the installation of Visual Studio and some of its components, to be able to compile apps for windows with C++.
It is necessary to download it from the website and install what is solicited by the flutter doctor. Notice, Visual Studio != VS Code.
With everything installed, the warnings from
flutter doctor should be gone. Maybe it is necessary to restart the computer for it to take effect. Now we need to clone the repo
flutter-desktop-embedding into our local files because we’ll need to copy come scripts and runners from the platform.
At the directory
\flutter-desktop-embedding\example\windows, copy the folders
scripts along with all the files. Pasting them on our project, it should look like here.
For the app to run, it is needed to define the
TargetPlatform before calling the function
runApp(), this is because currently the desktop platform is not automatically recognized, and with the
TargetPlatform null, errors will occur.
Here there is a detail for the app to continue running on 3 different platforms. The flutter desktop documentation says to define the
TargetPlatform according to the following method:
However, flutter web doesn’t have access to
dart:io, just like the mobile doesn’t access
dart:html. And as
Platform is defined in
dart:io, the above code breaks the web version. That’s why the first code is more appropriate to ensure the app running on all platforms. With that is possible to run the app,
flutter devices will list windows as a device.
flutter run -d windows results on the app magically running, how amazing is it?
Even the Flare animation, the API calls, the Json parsing, none of that were necessary to change. But there is only one last detail. The hyperlinks aren’t working, because when in desktop we can’t launch a link through
universal_html or the default
Currently, the plugins support on desktop are not well defined as how they will be treated, because of that the existing plugins are not published at pub.dev. But are published at flutter-desktop-embedding/plugins. These plugins are on early-stage and probably will be integrated into the current ones, or changed places.
To open an url we’ll use the
url_launcher_fde, an embed to the original one
url_launcher, see more. So it can be added on pubspec:
You can read more about desktop plugins here. But this isn’t enough, we still need to add the plugin manually at the Runner from windows.
For that we open the file
/windows/Runner.sln with Visual Studio. In File > Add > Existing project.. add the file
.vcxproj from the plugin. The file is downloaded to the local directory at
Now at Project > Project dependencies.. it is necessary to define the project Runner as dependent on url_launcher_fde, and the project url_launcher_fde dependent on Flutter Build. The compilation order must be like this:
Now the file can be saved and Visual Studio closed. The plugin will be correctly configurated and when running the project again the external urls will be working. o/
- Should I use flutter web or desktop in a production environment? Not yet.
- Should I use flutter web or desktop? Definitely yeah!
Of course, we needed to do some boring setup, mostly to the desktop part. But with this simple application is possible to feel a little taste of what the real flutter multiplatform is capable of.
And after all, you can answer in the comments, how long do you think it will take for flutter to get the first position on this run? :D
The source code is available on GitHub, access it and drop a ⭐️ if you enjoyed ;)