In this blog, I'll take you on a quick tour of Flutter for Web, discuss its features and our tests, and give our recommendation on whether you should use Flutter for Web.
11.11 Big Sale for Cloud. Get unbeatable offers with up to 90% off on cloud servers and up to $300 rebate for all products! Click here to learn more.
By Bai Ji.
Google announced Flutter for Web at Google I/O 2019. The aim of this update to solve the problem of code compatibility on different servers. In many ways, Flutter for Web is still in its infancy and therefore generally isn't recommended for production use. However, with all the improvements made, it makes for something rather enticing. So you may be thinking then, how well does it perform anyway?
Well, in this blog, I'll take you on a quick tour of Flutter for Web, and discuss some of its features and our tests, and last provide our recommendation on whether you should use Flutter for Web or not.
How Flutter for Web Works
Source: Flutter.dev
The upper layer of both Flutter for Web and Flutter is Dart. The two of them also have some major differences between the two of them. The Dart code of Flutter runs in Dart VMs and the Flutter engine processes the interface by using the Skia drawing engine to render to the screen using the GPU. However, the Dart code of Flutter for Web is compiled into JavaScript. Some parts of the content on the interface is converted into standard HTML tags, and other parts are converted into custom tags rendered using Canvas, eventually forming a DOM tree.
This principle difference described above is crucial and allows us to come to the following conclusion:
Flutter for Web Has Conflicts in Terms of Both Consistency and Experience
To make Flutter for Web have the same level of consistency that you can achieve with Flutter would require lots of rendering with Canvas. But, the performance of Canvas for these sorts of rendering operations, especially on the mobile end, is nowhere near as optimal as just using HTML tags. And, to add to this, using a large number of HTML tags for better Flutter for Web performance would also lead to even more consistency problems. Interestingly, you can also find these sorts of problems with Weex and RN. Next, all the controls of Flutter are rendered in the drawing engine by using a set of code. However, how can we ensure consistency if Flutter for Web uses a large number of HTML tags? The only solution is a large amount of fine polishing work. So, as you can see, there's definitely some issues here.
But, why is the rendering performance in Canvas not as good as writing HTML manually, anyways? Well, let's analyze this problem from the following perspectives:
- The components rendered by Flutter for Web in Canvas contain many visuals and animations that have the MD characteristic, such as shade and Z axis changes. This requires better performance than ordinary HTML tags.
- Flutter for Web uses Dart DSLs to convert to a DOM tree, which is very complicated and not likely to be simpler than a DOM tree written manually.
- For controls that use Canvas, both the capture and distribution of the gesture events are implemented by the Flutter for Web framework itself.
Although Google may have a chance of doing amazing work, with the same interface and equally efficient developers, using Canvas for drawing cannot perform better than using HTML along with CSS and JS.
In addition, if Flutter for Web involves the conversion of a large number of HTML tags, there will not be any less browser fragmentation than on Android. The reason why Flutter is popular among many developers is that its drawing engine perfectly avoids fragmentation to ensure consistency.
Therefore, to achieve an optimal balance, only a limited number of standard HTML tags can be reused by Flutter for Web. These tags must have the following characteristics:
- The functions of tags are simple and intuitive.
- Ideally, the tags do not have direct graphical display or are only responsible for simple graphical display (for example, rectangles).
Typical tags are <p>
and <div>
.
This is also the official practice of Flutter. Therefore, I can draw the following conclusion:
In general, Flutter for Web will not have consistency problems, but its performance is unlikely to be higher than that of manually written HTML tags.
Status Quo and Official Suggestions
According to the Official website and GitHub repo, we sorted out the following statements:
-
Currently, Flutter for Web and Flutter are two different repositories. According to the official document, they are being merged but no final conclusion has been given. This is of great significance to engineering, because it implies several problems:
- Currently, the company does not have confidence in the maturity of Flutter for Web, and Flutter for Web has a fast iteration rate.
- Currently, Flutter for Web and Flutter can only ensure the same API at most. The implementation principles of Flutter for Web and Flutter may be very different. At the same time, it is not guaranteed that all the controls have been implemented on Flutter for Web.
- Flutter for Web is not recommended for production use.
- Currently Flutter for Web does not have a plugin system, and some system interaction capabilities are missing, for example, taking photos.
- Performance cannot be guaranteed. The code generated by Flutter for Web may run slowly, or demonstrate significant UI "jank".
- At this time, desktop UI interactions are not fully complete.
- The development workflow is only designed to work with Chrome at the moment (what the consequent impact is). The release version can be run on any browser except IE. The oldest version supported is unclear.
Practice
The official website does not provide much content about Flutter for Web, which is relatively new, and it seems that these problems do not matter a lot. To find out whether Flutter for Web can be used or not, we need to conduct a pre-study. To obtain the result as fast as possible, I plan to migrate an existing Flutter page to run on Flutter for Web, evaluate the entire process and see the page results.
The migration details are not described here. For more information about this process, you can see the official document. Generally, this process involves the following steps:
- Install the webdev tool for Flutter for Web.
- Change the SDK dependency and add the Web folder (of the same level as the existing Android and iOS folders) and some other folders (such as index.html and main.dart).
- Change all the Flutter packages that the Flutter code depends on to the flutter_web packages.
- Remove all incompatible code, such as multiple languages, routing, and
Platform.isAndroid
.
- Compile and run the app.
The main goals of this practice are as follows:
- Obtain a comprehensive understanding of the limitations to make it easier to estimate the cost of overcoming these limitations.
- Have a general understanding of the Flutter for Web performance and experience, especially for running our own pages on Flutter for Web.
- Clearly understand the mutual invocation of Flutter for Web and Javascript. If it is feasible, the barriers to reusing existing capabilities (for example, mtop) will be reduced significantly.
After deleting 10,000 lines of code and running the app successfully, I arrived at the following conclusions on engineering, developer experience, and user experience. My conclusions on the developer experience and user experiences are based on my experiment with mix2s.
Engineering
-
It supports the debug and release modes. The latter has much higher performance than the former.
- The debug mode supports automatic re-compilation after the code is modified. This is consistent with other front-end frameworks (I have only used Django).
- It supports hotreload, which I have not tried yet.
- The
webdev build
command can be used to compile index.html and Javascript, and nginx can be used to implement the reverse proxy.
-
Important Note: Before the compiled code is compressed by using gzip, the
main.dart.js
of the simplest helloworld is about 500 KB and the gallery in the sample is about 2 MB. In the simplified version, the order list for only the display purpose is about 1.3 MB. The average compression ratio of gzip for text is 80%. After compression, the code can still be hundreds of KB. In addition, if main.dart.js
is not completely loaded, the interface will not be displayed.
Developer Experience
-
Important Note: Flutter for Web uses the flutter_web library and provides no support for many plug-ins, which will cause several problems.
- In engineering, the co-existence of Flutter and flutter_web can not be solved in an elegant way. The maximum support is the conditional import of dart2 (this feature is not included in the official document).
- Some libraries that depend on the Flutter SDK, especially the multi-language library, cannot be applied to flutter_web. I am also sure that Google will provide support for these libraries during the merge, instead of providing separate adaption to flutter_web. This means that all the existing libraries that depend on the Flutter SDK cannot be used by flutter_web.
-
Debugging is difficult.
- Error logs can be printed to the browser console, but it is difficult to catch the stacks during the "try catch" part.
- Although stacks in the browser are very complicated, but problematic Dart code can still be found.
- Currently, single-step debugging capability is not provided.
-
Platform.isAndroid
and Platform.isIOS return errors. Currently, it is unknown whether the differentiated display can be implemented for Android and iOS.
- Currently, controls are not found to have API inconsistencies. However, some controls behave abnormally, for example, pulling down to refresh often gets stuck or crashes. I assume that interaction-intensive controls have similar problems, though I have not performed a test on these controls due to the high test cost.
- The image control
NetworkImage
can be directly used. However, the image in the test looks like a little blurry. I am not sure whether this problem is caused by the control itself or my CDN URL policy.
- Dart code can invoke javascript and the developer experience is similar to the reflection. In addition, it is required to process the conversion between the JS type and the Dart type. The speed of the interaction between Dart and JS is unknown. Even though FFW does not support the APIs for many browsers, the capability can be extended by using JS.
- The differences between Dart and javascript themselves can increase the cost of the testing and compatibility. Although Dart can be compiled into JS, Dart running on Dart VMs does not have exactly the same performance as running in browsers after compiled into javascript. Example:
Map<String, String> query = null;
val b = query["abc"];
The preceding code can be run on a Dart VM with the result of b=null
; after the code is compiled into javascript and run, a null pointer will be reported because the query is null.
User Experience
After testing the performance of the order list and the official sample-gallery on Chrome, UC, and the built-in browser on MI devices respectively, I arrived at the following conclusions:
- Because the tests are performed in a private network environment, the load speed has no obvious difference.
-
Important Note: The interface is not shown when the unique
main.dart.js
and some other resource files (for example, MaterialIcons
) is not loaded.
- In terms of the frame rate or smoothness, the performance on Chrome is best, followed by UC and the built-in browser on MI devices. Although Chrome provides the most fluent performance, obvious freezes can be observed on animations and transitions in the sample.
- For text display, on the Flutter for Web interface, the majority of the text is shown clear on Chrome. The text on the built-in browser on MI devices is obviously blurry. Click to zoom in the following pictures and you can see that the text on the FFW page is obviously blurry.
Flutter for Web Flutter
- In this comparison test, none of the three browsers support copying, pasting or selecting text. It is likely that Flutter for Web uses Canvas to process text. This explains why text using some fonts and sizes is blurry and text cannot be selected.
-
When Safari and Chrome on iOS are used to access the demo page, the entire TextField is not available and the following problems are encountered:
- The soft keyboard pops up in an abnormal way. Most of the time, the soft keyboard automatically hides itself immediately after it pops out. Occasionally it does pop out normally (the software keyboard works normally on Android), but it cannot automatically hide itself when the focus has changed.
- Words cannot be entered on Safari; words can be entered on Chrome. (Word input is normal on Android.)
- Text can be selected but copy and paste does not work (also true on Android).
- When the focus moves to TextField, the interface automatically zooms in and is hard to zoom out (this works normally on Android).
Summary
Based on the preceding sections, Flutter for Web has several serious problems. If these problems are not solved, Flutter for Web cannot be applied in production:
-
Package size, which will further cause several problems:
- Flutter for Web packages are much larger than normal h5 packages, which poses a great challenge to traffic and page loading speed.
- When Flutter for Web is packaged into a JS package, multiple Flutter for Web pages cannot reuse public components, further causing additional waste.
- If the Flutter for Web JS package is not completely loaded, the page cannot be displayed, providing a very poor user experience. H5 supports gradual loading and the JS package can be loaded later.
-
SDK separation, which will also further cause several problems:
- In engineering, it is difficult to elegantly solve the co-existence of the two SDKs.
- In terms of capabilities, the Flutter for Web SDK does not support the libraries that depend on the Flutter SDK, for example, the multi-language library. A separate multi-language solution is required for the Flutter for Web SDK.
- Do not use FFW in form scenarios. I am not sure whether the aforementioned TextField problem can be solved in the application layer.
- Some interaction-intensive components, for example, the control for pulling down to refresh, have some problems and are almost unusable. Because I have not evaluated the quality of individual components due to the high cost, I do not know the overall component quality.
Conclusions
- Do not use Flutter for Web in production unless it is strongly necessary in your business scenarios or you have mature technologies to deal with the limitations and problems.
- If you really want to overcome the known limitations and are willing to invest in FFW, and you do not care about the package size and the user experience (for example, the frame rate), you can try the current Flutter for Web version.
- I estimate that at least 100 persons are needed every day to solve the problems (the ceiling is unknown). In addition, some problems may not be solved anyhow, for example, the package size.
- When can you make the follow-up action? To min mind, you can pay further attention when Flutter for Web is merged into the Flutter SDK. You may ask Google for the detailed plan.
Guidance on Using Flutter for Web
This section describes required technologies and solutions if we really want to use Flutter for Web.