How to convert Flutter Mobile app to Web App
Tags: Flutterweb, Flutter, Flutter For Web, Flutter App Development

How to convert Flutter Mobile app to Web App

Since last year when Hummingbird was announced, there was a lot of curiosity and excitement about flutters web development project. And in Google I/O’19, Flutter’s vision about the web was made official by releasing flutter_web in technical preview with a future promise that flutter_web eventually will be merging into main flutter repository so that all project may it be for Mobile or Web, will be using the same SDK.

The idea of simply changing your SDK from Flutter to Flutter Web & your application is now web application sounds easy and Awesome!!

So I really wanted to check how to check what it takes and I found it's not that easy! But, trust me, it is not that hard either! (If you know the exact steps to follow)

Set up

First of all, make a copy of your application in a different directory, in which we will be doing this experiment

Clone the flutter_web repository locally using git or you can download it directly from here

Install the webdev package. It is used for building a web app from a flutter. Install using the following command:

flutter pub global activate webdev

Current webdev version is 1.0.0, you can check if its installed & setup properly by running following command

webdev --version

Note: if you have problems configuring webdev to run directly, try:

flutter pub global run webdev [command] .

Application Code Changes

Update your application’s pubspec.yaml file & do following changes:

Change dependency from flutter to flutter_web: any

In dev_dependency section, Change flutter_test dependency to flutter_web_test: any

Add build_runner & build_web_compilers dev dependencies.

Add section dependency_overrides in yaml file which will be providing paths of your local flutter_web repository or you can point to Github repository path

The updated pubspec.yaml should look similar to the below image:

Remember, the path mentioned in dependancy_overrides has to point to your local flutter_web specific folders. Or you can use GitHub repository paths, in that case, your pubspec.yaml should look like below:

Once you change pubspec.yaml your IDE will start showing you thousand of errors in your application because flutter is no longer in your dependencies & your app is using flutter imports throughout your application code.

So do a search & replace in your app’s complete lib folder & find

package:flutter

and replace it with

package:flutter_web

Also, if your application is using dart:ui , then do this search & replace in your app’s complete lib folder & find

dart:ui

and replace it with

package:flutter_web_ui/ui.dart

After this, try running flutter packages get

If console shows no error, great!!! You can simply run webdev serve and if everything compiles with no error you can view your application at

http://localhost:8080

But, in most cases, you will run into some issues, as some other dependency is not yet compatible with flutter_web, you might see error messages similar to one I came across since I had a dependency flutter_redux :

Resolving dependencies... The current Dart SDK version is 2.2.0. Because flutter_redux <0.4.0 requires SDK version <2.0.0 and flutter_redux >=0.4.0 depends on flutter any from sdk, every version of flutter_redux requires flutter any from sdk. So, because flutter from sdk doesn't exist (the Flutter SDK is not available) and recipe_manager depends on flutter_redux any, version solving failed. Flutter users should run `flutter packages get` instead of `pub get`. exit code 69

Resolve Plugin Dependency Issues

If you are facing dependency issues as mentioned above, you can either ask the dependency developer for making changes to be able to use it with flutter_web. But that will require waiting for the dev to address the issue. So, if you are in a hurry like me, you can simply fork the repository or even better make a directory like “local_pub_plugins” or something like that, & download the plugin repository zip into that directory & unzip it.

In the plugin's code, find the pubspec.yaml file & make all the changes we made for our application’s pubspec.yaml After that again do the find & replace in that plugins lib folder for package:flutter & dart:ui and replace it with package:flutter_web & package:flutter_web_ui/ui.dart respectively

You may need to do this step for all packages that are having the above-mentioned issue. (I know its tedious, but worth it)

WEB SPECIFIC FILES

Once all the above steps are done, and your app is showing no error messages in the console you are almost there! Last few changes to make the app run on the browser.

Create a directory with the name “web” in your application’s root folder. In that directory add the following:

- index.html

- main.dart

- assets (directory, to contain your application’s assets such as images, fonts, etc) Inside assets directory, create a file FontManifest.json , it can be an empty json array Inside assets directory, create a file AssetManifest.json , it can have an empty json object.

For the exact content of the files, You can refer to samples given in example directory inside your local flutter_web setup, you can also simply copy the entire “web” folder from some example app, into your app and it will work!

Still, even if you copy the web folder from the sample project, you need to add AssetManifest.json just to avoid any problems later.

RUN YOUR APP

Once you set the web-specific files, you can run:

webdev serve

to run on default port “8080” or you can mention specific port to run your app on using the following command:

webdev serve web:9090

and you should see messages about the application is compiled successfully and running on the port you mentioned on your console as can be seen in below image.

BUILD APP FOR DEPLOYMENT

To generate code for deployment, first, you should create build.yaml file in your application’s root directory. It will be used by webdev to take instructions about how you want to build app and what options to use.

Add the following to your build.yaml file:

targets:

$default:

builders:

build_web_compilers|entrypoint:

generate_for:

- web/**.dart

options:

dart2js_args:

- --no-source-maps

- -O4

- --fast-startup

- --minify

- --trust-primitives

- --trust-type-annotations

Screenshot of my build.yaml

You can add or remove build option flags as per your liking.

Once your build.yaml changes are done, run following command:

webdev build

This Command should generate deployable code inside the build folder in your application’s root. The console should show following or similar messages:

You can simply deploy this build folder’s content to your server or firebase.

If your app has a native dependency

If your application has any native dependency, for example in my application, I was using firebase auth & FireStore. And flutter plugins for these, have native implementations for Android & iOS platforms. So it will not work with flutter_web. Also, for web, firebase has a different plugin developed to be used in web applications.

So to handle this, I created a new flutter package like:

flutter create my_middlewere_package --template=package --org=com.yourapp --description="This is middlewere package"

And moved all my firebase specific code into that package.

Then I kept only business logic in the package as it is, and converted native handler classes into abstract classes. And concrete implementations of these abstract classes are now injected at runtime by the main project. For example, when I use this middleware package in my flutter_web app, I inject the concrete implementation of interfaces using firebase package designed for web, and when I use this middleware package in my Flutter Mobile app, I inject the concrete implementations of interfaces using flutter_firebase, flutter_auth, etc which are native for mobile.

If there are still issues, you can check out the official documentation for the limitations flutter_web has here

And that's it…! Happy coding..!