The front end early chat conference, and nuggets jointly held. Add Codingdreamer into the conference technology group, win at the new starting line.


27th session | special front-end Flutter, understand the Web rendering engine | | UI framework performance optimization, 6-5 live in the afternoon, six lecturer (taobao, jingdong/idle fish, etc.), point I get on the bus 👉 (registration address) :

All the previous period has the full recording, the beginning of the annual ticket to unlock all at one time


The text is as follows

This article is the seventeenth session of the front-end early chat frame special, but also the 117th early chat, from the flying pig – nanlu share

preface

At present, the front-end technology changes with each passing day, just look at the mobile end of the rendering scheme. From the early H5 Wap, to the Hybrid scheme that improves performance and extends functions through offline package, Prefetch and JSBridge with the help of client capabilities, to the big front-end fusion rendering scheme represented by Weex/ReactNative that was popular a few years ago, And in recent years the major manufacturers have launched more commercial value than technical value of the small program program. The selection of front-end technology has evolved from the pure pursuit of performance to the game between performance and efficiency, and even business value, and the birth of every new technology has its scene value behind.

In this article, the author will share his thoughts On the next generation of high-performance front-end rendering ideas for Flutter, a new client rendering solution. See what a Flutter can do to the Web.

First Flutter

For those of you who aren’t familiar with Flutter, Flutter is a mobile application development framework that Google launched and opened source in 2017. One of its major features is the implementation of a self-drawing engine based on Skia, which can run on mobile terminals, IOT and other platforms at the same time. Flutter is developed using Dart. One of the Dart language features is JIT (just-in-time compilation) and AOT (ahead of time compilation) support. This allows efficient development in JIT mode during development and the high performance of AOT mode during release.

Flutter, Google’s blockbuster product, has been a huge hit since its launch and currently has over 10 million stars on Github, with an average of 1.8 Stable iterations per month (as of 2020). Alibaba, Tencent, Bybyte and Meituan are all developing related layouts and construction of Flutter. Within Ali, several BU, including Taobao, Xianyu, Feizhu and Hema, have launched actual businesses.

The advantage of Flutter

So what makes Flutter so popular? Let’s take a look at the current mobile rendering solutions:

Given the high performance of Flutter Native and the low development cost of WebView, but also the excellent rendering consistency of Flutter due to its self-drawing, it is not hard to explain why everyone has such high expectations for Flutter.

Technical features of Flutter

Let’s briefly review the technical features of Flutter:

  • Graphic engine

Flutter builds its own rendering pipeline based on Skia, a cross-platform graphics library, rather than using native controls of the system (Android, iOS) or WebView rendering pipelines.

The benefits of self-painting are obvious, as it fundamentally solves the cross-end consistency problem (in contrast to Weex, which moved rendering consistency to the container layer, but also made the container more difficult to maintain).

  • Responsive frame

As mentioned earlier, Flutter is essentially a development framework, and in terms of development mode, it is a responsive framework, which is one of the reasons why Flutter development is so effective (let’s forget about its component hell nesting for the moment). Let’s look at an example of a simple “increment by number” component that can be implemented in Flutter:

Is there a familiar feeling for the front-end students? Yes, this writing method is very similar to JSX! This includes component nesting and status updates.

  • All widgets

“Widgets are the basic building blocks of the USER interface of the Flutter application. Each Widget is an immutable declaration that is part of the user interface. Unlike other frameworks that separate views, controllers, layouts, and other properties, Flutter has a consistent unified object model: widgets.” The Widget can be either a structural component such as div or span, a style component such as padding or opacity, or a function component such as dialog……

The Widgets form a hierarchy based on the layout, which is called a Widgets tree, and you’ll remember this for later in the introduction.

Flutter with the Web

In the previous article, we got a glimpse of Flutter and briefly compared its advantages and disadvantages with other mainstream mobile rendering schemes. In this section, we will focus on the impact of Flutter on the Web (or front end) and the possible sparks of Flutter.

The impact and binding of a Flutter to the front end

The advantages of the front-end over the client are as follows:

  • Labor Cost: 1 vs 2 (iOS + Android)
  • Development efficiency: JIT vs AOT
  • Deployment scenario: Cross-terminal vs single-terminal
  • Iteration frequency: anytime vs release

However, compared with Flutter, the “labor cost” and “open efficiency” advantages of the front-end will be greatly reduced, but the advantages of cross-end delivery and high frequency iteration will still be retained. Can we combine the advantages of the two? The answer is Web On Flutter.

Web On Flutter technology ideas

Since it is developed on the Web and rendered with the Flutter engine, this means that the first half of the rendering process is Web and the second half is Flutter. How to bridge the two rendering pipelines has become the focus of solving the problem, there can be three entry points:

  • Entry point A: Simulate the Flutter Widget with the Web DOM. This solution has strong constraints on front-end development and requires page development to follow the component mindset of Flutter. This is the idea behind the current Community MXFlutter.
  • Entry point B: Emulate the DOM of the Web with the Flutter Widget. The difficulty of this solution lies in the precise style mapping, which is suitable for restricted (W3C standard subset) front-end scenarios. At present, the Flugy scheme of flying pigs adopts this idea.
  • Pointcut C: Map the Web DOM tree directly to the RenderObject tree of Flutter. The advantage of this approach is that bridging the DOM tree directly to the RenderObject tree allows for finer operations than bridging the Widgets tree, and theoretically a higher upper limit for style restoration. But because it is extended on the RenderObject inside a Flutter, it will also be more sensitive to the Flutter version. Kraken is this idea.
  • Pointcut C Plus: This pointcut, which is not shown in the figure, is a further modification of Flutter Rendering. It rewrites the Flutter Rendering layer. The advantage is that there is no need to worry about misalignment between the DOM tree and the RenderObject tree, but the corresponding development cost is also huge. Unicorn is currently trying to explore this.

You can further understand the differences between these four approaches by looking at the following figure:

Implementation principle of Web On Flutter

This section will take the idea of simulating DOM with widgets as an example and analyze the implementation principles. Let’s start with an overview of the overall render link under this idea:

As mentioned above, the key point of the whole link is to bridge the Web rendering link to the Flutter rendering link. The first step of the bridge is to enable bidirectional communication. The key technical point involved here is JS Binding. The next step is to use Widgets to simulate DOM and generate the final Widgets tree for drawing. Key technical points need to pay attention to include DOM tree mapping and CSS style mapping. We also need to pay attention to how events are bound. Next, I will introduce each of the above four key technical points.

  • JS Binding

In WebView, we often use schemes such as rewriting Alert/Prompt, intercepting URL or API injection to communicate with JS and Native. In Web On Flutter, JS and Flutter communication can also use a similar API injection scheme. That is, a Flutter mounts variables, such as a function, to the JS global context via the JS engine, which can then be called to a Flutter method, and vice versa. Flutter can also access variables in the JS global context directly through the JS engine. Two-way communication can then be established. The following diagram illustrates the process visually:

Here is an extension of the C++ glue layer above. Dart code can use the Dart: FFI library to call the native C API, but the JS engine can only be called by C++, so we need to write a C++ glue layer to encapsulate the JAVASCRIPT engine API. Extern C tags are then compiled into C artifacts for Dart calls.

After further analysis of the whole communication link, it can be seen that a major bottleneck is cross-language communication (JS <=> C/C++ <=> Dart). The author has done experiments, and the single time of JS without reference to Dart is about 0.08ms, while the time of JS without reference to Dart is about 0.08ms. However, considering that the number of render instructions in a real page may be at the level of 1000 and carry a large number of parameters, the final time will easily exceed 100ms, so we need to further optimize, and feasible solutions such as caching render instructions for batch calls will not be expanded here.

  • The DOM tree mapping

Let’s look again at how the DOM tree on the Web transforms into the Widgets tree in a Flutter. We know that the Dom tree is created in the front end using the createElement/appendChild Dom API, and the entire creation process is essentially a series of render instructions.

When a Flutter receives the createElement instruction, it combines widgets based on the characteristics of the Element to be created. For the body element, for example, you need a Container Widget to wrap the outer layer of the element so that you can set some generic styles. The children of the body are arranged vertically, so you need a Column Widget, and finally, considering that it’s scrollable, You also need a SingleChildScrollView to support it. Note that the simulated body Widgets combination here is a simple example, but the actual implementation will be much more complicated to consider in many cases.

In the appendChild directive, remember that Flutter is a responsive framework. We can maintain children of a node using setState, like adding and deleting components in React.

The overall process can be seen in the following figure:

  • CSS style mapping

After converting the DOM tree to the Widgets tree, we need to think about how to restore the CSS styles to the Flutter. Remember that the render instructions tell the Flutter what type of Element it needs to create and also carry the attributes of that Element? This includes styles (converting CSS to inline styles via tools such as Webpack). All we need to do is restore these styles to one or more WDigets. Here are two examples: absolute positioning and bottom alignment (such as price and ¥) :

The Flutter provides a Stack Widget that allows the child components to Stack, while the Positioned Widget can locate itself according to the four corners of the Stack, thus mimicking the absolute positioning in the Web.

There are many options for bottom alignment. Let’s talk about Flex. Fortunately, Flutter provides Flex components that can easily emulate flex-direction and align-items styles by setting their properties. As for allocation of elastic space (Flex: 1), Expanded Widgets are also available to emulate.

Other common styles, such as width, height, background color, border, and rounded corners, can be set in the Container Widget. Text colors and font sizes can be set in the Text Widget. Image fill mode can be set in the DecorationImage Widget, and so on.

Let’s take a look at how to style the Flutter using a common commodity card example below:

  • event

Finally, take a look at how event binding is done:

  1. In Web code, we listen for DOM interaction events via Node.addeventListener (event, callback). This listener API translates into addEvent(nodeId, event) instructions to Flutter.
  2. Flutter captures user interaction events, uses the nodeId to find and trigger event callbacks bound to Web layer nodes.

The process is shown in a diagram as follows:

In addition, Flutter has an insideout event bubbling mechanism similar to that of the Web, which makes the event binding between Flutter and the Web more suitable. Unfortunately, Flutter does not have a mechanism to stop bubbling, so we need to code the simulation ourselves.

conclusion

Here’s a quick recap:

  1. Flutter is popular because of its high performance, consistent rendering (self-drawing engine), high development efficiency (Dart JIT + responsive framework), and low labor cost (compared to the client).
  2. With Flutter, some of the traditional advantages of the front-end become weak, but we can try to combine the advantages of the two, that is, Web On Flutter;
  3. There are many technical ideas about Web On Flutter. The main idea is how to bridge the Web rendering process with the Flutter rendering process.
  4. Key technical points include: JS Binding, Dom tree mapping, CSS style mapping, event Binding;

By the way, the author’s “Flying Pig – User Front-end and Digital Management Team” HC Duo Duo, welcome all students who are interested in travel, or Flutter, Serverless, micro front-end, integrated development, end rendering, interactive marketing, recruitment, investment and partner, intelligence, experience technology, data measurement and so on to join us. Mail: [email protected]. Also welcome to follow our flying Pig technology official account: Fliggy F2E, regularly updated with high quality articles.


Don’t forget 6-5 PM live oh, click me on the bus 👉 (registration address) :

All the previous period has the full recording, the beginning of the annual ticket to unlock all at one time


Look forward to more posts. Give it a thumbs up