1. Introduction to cross-platform technology

There are three main types of cross-platform technologies:

  • H5 + native (Cordova,Ionic,Wechat applets)
  • JavaScript development + Native Rendering (React Native,Weex,Fast application)
  • Self-painted UI+ native (QT for mobile,Flutter)

2. Introduction to Hybrid technology

2.1 H5+ native mixed development

The main principle of this kind of framework is to realize part of the content that needs to be dynamically changed through H5, and load it through the native web page loading control WebView (Android) or WKWebView (iOS) (unless otherwise specified later, We use WebView to refer uniformly to web page loading controls in Android and iOS. In this way, the H5 part can be changed at any time without issuing a version, and dynamic needs can be met; Also, h5 code can be developed once and run on both Android and iOS platforms, which can reduce development costs. In other words, the more features h5 has, the less development costs will be. We call this h5+ native development mode Hybrid development. The APP developed in the Hybrid mode is called Hybrid application or Hybrid APP. If most of the functions of an application are realized by H5, we call it Web APP.

Some of the best examples of hybrid frameworks are Cordova, Ionic, and wechat applets. It’s worth noting that wechat applets are currently rendered in WebView rather than native rendering, but native rendering is possible in the future.

2.2 Technical points of mixed development

As mentioned earlier, native development has access to all platform functionality, while hybrid development has H5 code running in a WebView, which is essentially a browser kernel. Its JavaScript still runs in a restricted sandbox, so it has no access to most system capabilities. For example, the file system cannot be accessed or bluetooth cannot be used. Therefore, for the functions that H5 cannot achieve, we need to do them native. Hybrid frameworks typically pre-implement apis in native code to access system capabilities, and then expose the WebView for JavaScript to call. In this way, the WebView becomes a communication bridge between JavaScript and native apis. Responsible for passing call messages between JavaScript and native language, which must follow a standard protocol that defines the format and meaning of the message. We call the webView-dependent tool for communicating between JavaScript and native and implementing a messaging protocol WebView JavaScript Bridge, or JsBridge for short, the core of the hybrid development framework.

conclusion

The advantage of hybrid application is that dynamic content is H5, web technology stack, community and resource rich, but the disadvantage is poor performance, for complex user interface or animation, WebView can not bear the heavy burden.

React Native, Weex, and Fast applications

3.1 the React – Native

React Native (RN for short) is a cross-platform mobile application development framework launched by Facebook in April 2015. It is an early open source JS framework for Facebook.

3.1.1 DOM tree and Control tree

Document Object Model (DOM) is a standard programming interface recommended by W3C to deal with extensible markup language. It is a platform – and language-independent way to access and modify the content and structure of a Document. In other words, this is the standard interface for representing and processing an HTML or XML document. In the front-end development, it usually refers to the rendering tree corresponding to HTML, but the generalized DOM can also refer to the control tree corresponding to THE XML layout file in Android. And the term DOM operation refers to the direct operation of the rendering tree (or control tree). Therefore, You can see that DOM trees and control trees are equivalent concepts, except that the former is often used in Web development and the latter in native development.

3.1.2 Reactive programming in React

  • Developers only need to focus on state transitions (data), and when the state changes, the React framework automatically reconstructs the UI based on the new state.
  • After receiving notification of user state changes, the React framework uses Diff algorithm to calculate the changed part of the tree based on the current rendering tree and the latest state changes, and then updates only the changed part of the tree (DOM operation), thus avoiding the whole tree reconstruction and improving performance.

Note that in step 2, the React framework does not immediately calculate and render the changed part of the DOM tree after the state changes. Instead, React builds an abstraction layer on top of the DOM, namely the virtual DOM tree. Any changes made to data and state are automatically and efficiently synchronized to the virtual DOM. Finally, batch sync to the real DOM instead of manipulating the DOM with each change. Why can’t we just manipulate the DOM tree every time we change? This is because every DOM operation in the browser can cause the browser to redraw or reflow:

  • Redraw the interface: If the DOM only changes in style, such as color changes, this will cause the browser to redraw the interface.

  • Backflow: If the structure of the DOM tree changes, such as size, layout, node hiding, etc., the browser needs to backflow (and relayout).

Browser redraw and backflow are expensive operations, and if you operate directly on the DOM for every change, it can cause performance problems, whereas batch operations only trigger one DOM update.

3.1.3 React Native rendering

JavaScriptCore is a JavaScript interpreter that has two main functions in React Native:

  • Provides a runtime environment for JavaScript.
  • JsBridge is a bridge between JavaScript and native applications. It acts like JsBridge. In fact, many implementations of JsBridge in iOS are based on JavaScriptCore.

RN maps the virtual DOM to a native control in two steps:

  • Layout messaging; Pass virtual DOM layout information to native;
  • Native renders the control tree through the corresponding native control according to the layout information;

React Native is a Native control rendering, so performance is much better than hybrid H5. React Native is a Web development stack that requires only one piece of code to maintain and is also a cross-platform framework.

3.2 Weex

Weex is a cross-platform mobile terminal development framework released by Alibaba in 2016. The idea and principle are similar to React Native, but the biggest difference is syntax. Weex supports Vue syntax and Rax syntax. Rax’s Domain Specific Language (DSL) syntax is based on the React JSX syntax. Unlike React, JSX is mandatory in Rax, which does not support component creation by other means, so learning JSX is a necessary foundation for using Rax. React Native only supports the JSX syntax.

3.2.1 fast application

Fast application is a lightweight application standard jointly developed by huawei, Xiaomi, OPPO, Meizu and other 9 mainstream mobile phone manufacturers in China, targeting wechat mini programs. It is also developed in JavaScript and renders with Native controls. There are two main differences between React Native and Weex:

  • The app itself does not support Vue or React syntax. It adopts native JavaScript development, and its development framework is similar to wechat applet. It is worth mentioning that applet can use Vue syntax development (MPVUE) at present.

  • React Native and Weex’s rendering/typography engines are integrated into the framework, which requires a large installation package for each APP. The quick application rendering/layout engine is integrated into ROM, no packaging is required, and the installation package is small, so fast applications can be distributed quickly while maintaining performance.

conclusion

The main advantages of JavaScript development + native rendering are as follows:

  • Using Web development stack, the community is large, fast and the development cost is relatively low.

  • Native rendering, performance is much better than H5.

  • Dynamic is good, support hot update.

Inadequate:

  • Communication between JavaScript and native is required for rendering, and in some scenarios such as drags, communication can get stuck.

  • JavaScript is a scripting language, which requires JIT(Just In Time) during execution, and there is still a gap between the execution efficiency and AOT(Ahead Of Time) code.

  • Because rendering relies on native controls, controls for different platforms need to be maintained separately, and community controls may lag when systems are updated; In addition, the control system is also limited by the native UI system. For example, in Android, the rules for gesture collision disambiguation are fixed, which can be tricky when nested with controls written by different people.

4. Self-drawing engine

4.1 QT Mobile

Self-painted UI+ native. The idea is that the UI can be rendered consistently across platforms by a rendering engine that implements a unified interface across platforms, rather than relying on system native controls. Note that the draw engine addresses the cross-platform issue of the UI, and if other system capabilities are involved, native development is still involved. The advantages of this platform technology are as follows:

  • High performance; Since the draw engine calls the system API directly to draw the UI, performance is similar to native controls.

  • Flexible, easy to maintain component library, high fidelity and consistency of UI appearance; Because UI rendering does not rely on native controls, there is no need to maintain a separate set of component libraries for different platform controls, so the code is easy to maintain. Because the component library is the same set of code, the same rendering engine, so in different platforms, the component display appearance can achieve high fidelity and high consistency; In addition, by not relying on native controls, you are not limited by the native layout system, which makes the layout system very flexible.

Inadequate:

  • Lack of dynamic; In order to ensure the performance of UI drawing, self-drawing UI systems generally compile their distribution packages in AOT mode, so when an application is published, it cannot dynamically deliver code like Hybrid and RN frameworks that use JavaScript (JIT) as a development language.
  • Low development efficiency: QT uses C++ as its development language, and the efficiency of programming will directly affect the efficiency of APP development. As a static language, C++ has less flexibility in UI development than dynamic languages such as JavaScript. In addition, C++ requires developers to manually manage memory allocation. There is no garbage collection (GC) mechanism in JavaScript and Java.

Flutter implements a self-drawing engine and has its own UI layout system. However, the idea of a self-drawing engine is not a new one. Flutter is not the first attempt to do this.

4.4.1 QT profile

Qt is a cross-platform C++ graphical user interface application development framework developed by the Qt Company in 1991. In 2008, Qt Company technology was acquired by Nokia, and Qt became a programming language tool under Nokia. Qt was acquired by Digia in 2012. In April 2014, Qt Creator 3.1.0, a cross-platform integrated development environment, was officially released, realizing full support for iOS. Plug-ins such as WinRT and Beautifier were added, GDB debugging support without Python interface was abandoned, and C/C++ code modules based on Clang were integrated. Android support has been tweaked to fully support iOS, Android, and WP, which gives app developers all the functionality they need to build graphical user interfaces. However, although QT in the PC was a brilliant success, and by the community, but its in the mobile terminal is poor performance, in recent years, although sometimes can hear the sound of the QT, but has been very weak, whatever how QT itself technology, design idea, but in fact is lost after all, the reason is that the author thinks that there are four main:

  • QT mobile development community is too small, insufficient learning materials, ecology is not good.

  • Official promotion is not good, support is not enough.

  • Mobile came late, and the market has been dominated by other dynamic frameworks (Hybrid and RN).

  • In mobile development, C++ development has an inherent disadvantage compared to the Web development stack. As a direct result, QT development is inefficient.

Based on these four points, QT has become a martyr despite being a pioneer in developing cross-platform paint engines on mobile.

4.2 Flutter

2 Flutter profile

Flutter is a cross-platform, high-fidelity, high-performance mobile application development framework launched by Google and open source. Dart allows developers to develop apps, a set of code that runs on both iOS and Android. Flutter provides a wealth of components, interfaces, and developers can quickly add native extensions to Flutter. The Flutter also uses a Native engine to render views, which is a great experience for users.

  • At Google I/O 2017, Google debuted a new framework for creating cross-platform, high-performance mobile applications.

  • In February 2018, Flutter released its first Beta. In May 2018, Flutter was updated to Beta 3 at Google I/O 2018.

  • In June 2018, The first preview version of Flutter was released, which meant that Flutter entered its final phase before the official release of Flutter (1.0).

4.2.2 Cross-platform self-drawing engine

Flutter differs from most other frameworks for building mobile applications because Flutter uses neither a WebView nor the native controls of the operating system. Instead, Flutter uses its own high-performance rendering engine to draw widgets. This ensures UI consistency on Both Android and iOS, and avoids the limitations and high maintenance costs associated with native controls dependency.

Flutter uses Skia as its 2D rendering engine. Skia is a Google LIBRARY of 2D graphics processing functions that provide efficient and compact representations of fonts, coordinate transformations, and bitmaps. Skia is cross-platform and provides a very friendly API. Google Chrome and Android both use Skia as their drawing engine.

Flutter currently supports iOS, Android and Fuchsia (Google’s new operating system) by default. However, Flutter also supports Web development and PC development. The examples and descriptions in this book are mainly based on iOS and Android platforms. Readers of other platforms can learn about Flutter.

Holdings of high-performance

The high performance of Flutter is mainly guaranteed by two points. First, Flutter APP is developed with Dart language. Dart is almost as fast as JavaScript in JUST-in-time (JIT) mode. But Dart supports AOT, and when running in AOT mode, JavaScript can’t catch up. The speed increase is helpful for view data calculation at high frame rates. Second, Flutter uses its own rendering engine to draw the UI. Layout data is directly controlled by Dart language, so it does not need to communicate between JavaScript and Native as RN does during the layout process, which has obvious advantages in some sliding and dragging scenarios. Since layout changes are often caused by sliding and dragging, JavaScript needs to constantly synchronize layout information with Native, which is the same problem as frequent DOM manipulation by JavaScript in the browser, which will bring considerable performance overhead.

4.2.3 Use Dart language for development

This is an interesting but controversial question. Before we understand why Flutter chooses Dart over JavaScript we will introduce two concepts: JIT and AOT.

At present, there are two main ways to run a program: static compilation and dynamic interpretation.

  • AOT: Statically compiled programs are translated into machine code before execution. This type is usually called AOT (Ahead of time).

  • JIT: Execution is interpreted sentence by sentence as it is translated, often referred to as just-in-time (JIT) or “just-in-time compilation.”

AOT programs are typically developed in C/C++ applications that must be compiled into machine code before execution, while JIT is widely represented, such as JavaScript, Python, etc. Virtually all scripting languages support JIT mode.

However, it should be noted that JIT and AOT refer to the way a program is run and are not strongly related to the programming language. Some languages can be both JIT and AOT, such as Java and Python, which can be compiled into intermediate bytecode at the first execution and then directly execute bytecode at the later execution. Bytecode among some might say, is not the machine code, the program execution time still need to dynamically change the bytecode into machine code, yes, this is not wrong, but usually we distinguish whether as AOT standard is to see if that need to compile the code before execution, as long as it needs to be compiled, regardless of its compilation product is bytecode or machine code, belong to AOT. Here, the reader need not tangle with concepts, concepts are invented to convey the spirit, as long as the reader can understand its principle, forget its form.

4.3 Dart and JavaScript for comparison

Now why did Flutter choose the Dart language? Based on the official explanation and my own understanding of Flutter, I summarize the following (Dart and JavaScript are mainly compared because other cross-platform frameworks use JavaScript as their development language) :

High development efficiency

The Dart runtime and compiler support a combination of two key features of Flutter:

Rapid DEVELOPMENT cycle based on JIT: Flutter is adopted in the development phase, adopting JIT mode. This saves development time greatly by avoiding compilation for every change.

Aot-based distribution: Flutter generates efficient ARM code via AOT to ensure application performance when it is released. JavaScript does not have this capability.

A high performance

Flutter aims to provide a smooth, hi-fi UI experience. To achieve this, Flutter needs to be able to run a lot of code in each animation frame. That means a language that provides high performance without periodic pauses that drop frames, and Dart supports AOT better than JavaScript at this point.

Fast memory allocation

The Flutter framework uses functional streams, which makes it heavily dependent on the underlying memory allocator. Therefore, it is important to have a memory allocator that can efficiently handle trivial tasks. Flutter will not work effectively in languages without this feature. Of course, Chrome V8’s JavaScript engine does a good job of allocating memory. In fact, many of the Dart team members come from the Chrome team, so Dart is not an advantage over JavaScript in allocating memory. It needs that, and Dart has it.

Type safety

Because Dart is a type-safe language that supports static type detection, some type errors can be found before compilation and potential problems can be ruled out, which may be more attractive to front-end developers. JavaScript, on the other hand, is a weakly typed language, and the front-end community has developed many extension languages and tools that add static typing to JavaScript code, such as Microsoft’S TypeScript and Facebook’s Flow. Dart, by contrast, has built-in support for static typing, which is an important advantage.

The Dart team is at your side

It doesn’t look like much, but it matters. Thanks to the Dart team’s active input, the Flutter team has more and easier access to support. As stated on the Flutter website, “We are working closely with the Dart community to improve Dart use in Flutter. For example, when we first adopted Dart, the language didn’t provide a toolchain to generate native binaries (which is great for achieving predictable performance), but now it does, because the Dart team built it specifically for Flutter. Similarly, the Dart VM was previously optimized for throughput, but the team is now optimizing the VM’s latency time, which is more important for the Flutter workload.”

Technical type UI rendering mode performance development efficiency Dynamic framework represents H5+ native WebView rendering general high support Cordova, Ionic JavaScript+ native rendering native control rendering good support RN, Weex self-drawn UI+ native Call system API render good Flutter high, QT low default does not support QT, Flutter

conclusion

Technology type level UI rendering performance Development efficiency dynamic Framework on behalf of
H5 + native The WebView rendering general high support Cordova, Ionic
JavaScript+ native rendering Native control rendering good In the support RN, Weex
Self-painted UI+ native Call system API render good F high QT is low Not supported by default QT, Flutter

The development languages in the above table mainly refer to the UI development languages. Development efficiency refers to the efficiency of the whole development cycle, including coding time, debugging time, and troubleshooting and compatibility time.

Dynamic: indicates whether dynamic code delivery and hot update are supported.

Note that the Release package of Flutter is compiled using Dart AOT mode by default, so it does not support dynamic behavior.

But Dart also has JIT or SNAPSHOT running modes, which are dynamic.