03 Deep Understanding of the Historical Development of Cross Platform Solutions

03 Deep Understanding of the Historical Development of Cross-platform Solutions #

Hello, I am Chen Hang.

Today, I will discuss with you the background, principles, and historical development of cross-platform development solutions, and how we should choose the corresponding solutions for different scenarios.

Introduction to Cross-Platform Development #

In the current era of mobile internet, it has brought us speed, economy, security, and convenience, changing various aspects of our lives in its unique transformative way. For enterprises, mobile applications have become essential business cards on various mobile devices.

In the wave of mobile internet, in order to succeed in developing applications, both development efficiency and user experience are equally important. However, developing apps using native methods requires separate development for the iOS and Android platforms, which is a hidden risk and additional burden for small and medium-sized teams.

This means that we not only need to try different languages to implement the same functionality in different projects but also bear the maintenance tasks that come with it. If we want to expand to other platforms (such as Web, Mac, or Windows), the cost and time required will increase exponentially. This is obviously unacceptable. As a result, the concept of cross-platform development has entered our sight.

Therefore, fundamentally, cross-platform development is to increase the reuse of business code, reduce the workload of adapting to multiple platforms, and thus reduce development costs. While improving business focus, it can provide users with a consistent user experience. To summarize these benefits in one word, it is “fast, good, and cost-effective.”

“One code, run everywhere.” Over twenty years ago, Java emerged victorious over its many competitors with its slogan of cross-platform capability. This slogan meant that Java could be developed on any platform, and after being compiled into standard bytecode, it could run on any device with a Java Virtual Machine (JVM) installed. Although cross-platform is no longer Java’s biggest advantage now (its thriving ecosystem is), it is undeniable that it was unstoppable when it emerged under the banner of cross-platform.

For mobile development, if we can achieve “one code, run on multiple platforms,” such technology will undoubtedly trigger new productivity changes. In the current era of multiple terminals, it can save enterprises human resources, thereby directly bringing economic benefits.

With the birth and prosperity of mobile platforms, various cross-platform development solutions have emerged like mushrooms to meet people’s relentless pursuit of development efficiency and user experience. In addition to React Native and Flutter, there have been many other solutions in recent years. Next, I will analyze these solutions one by one for you. In this way, when you choose the right mobile development framework for yourself, you will have a guide to follow.

Here, I want to emphasize that when I mention cross-platform development solutions in the following text, unless otherwise specified, I am referring to development that spans iOS and Android platforms.

Three Eras of Cross-Platform Development Solutions #

According to different implementation methods, the mainstream cross-platform solutions can be divided into three eras.

  • Web Container Era: Based on web-related technologies, the interface and functionality are implemented through browser components. Typical frameworks include Cordova (PhoneGap), Ionic, and WeChat Mini Programs.
  • Generic Web Container Era: Development is done using web-like standards, but the drawing and rendering are taken over by the native system at runtime. Representative frameworks include React Native, Weex, and Quick Apps. In a broader sense, it also includes Tmall’s Virtual View.
  • Self-Rendering Engine Era: Comes with a rendering engine, where the client only needs to provide a canvas to achieve a highly consistent rendering experience across multiple platforms from business logic to functionality presentation. Flutter is one of the few representatives.

Next, let’s take a look at the most widely used web container solution.

Web Container Era #

In the web era, the main approach is to use the WebView control (UIWebView or WKWebView for iOS, WebView for Android) to render HTML5 pages within a native application. It also defines the interaction protocol between HTML5 and native code, exposing some native capabilities to HTML5 to expand its boundaries. This interaction protocol is commonly known as JS Bridge.

This development model includes both native application code and web application code, thus it is also known as hybrid development. Since HTML5 code only needs to be developed once and can run simultaneously on multiple systems, it greatly reduces development costs.

Due to the use of web development technologies, the community and resources are abundant, and the development efficiency is high. However, displaying a complete HTML5 page requires going through three major processes: loading, parsing, and rendering, which increases performance consumption by several orders of magnitude compared to native development.

Next, I will explain the complexity of this process using the loading process as an example.

  1. The browser control loads the main HTML document of the HTML5 page.
  2. During the loading process, if there are external CSS files, the browser sends another request to retrieve the CSS files.
  3. When encountering image resources, the browser also sends another request to retrieve the image resources. This is an asynchronous request and does not affect the loading of the HTML document.
  4. When encountering JavaScript files, since JavaScript code may modify the DOM tree, the HTML document’s rendering thread is suspended until the JavaScript file is loaded, parsed, and executed before the rendering thread can resume.
  5. If the JavaScript code uses properties or styles from the CSS file, it blocks and waits for the CSS file to finish loading before it can continue executing.

And this is just the most basic loading process for rendering an HTML5 page. The loading, parsing, and rendering processes are not completely independent during actual runtime; there will be overlapping. In other words, loading, parsing, and rendering can happen simultaneously. This makes displaying a page not as easy as imagined.

From the analysis above, you can see how complex it is to display an HTML5 page! This is in stark contrast to native development, where the rendering of a page can be achieved simply by creating controls and setting attributes. Web and native each have their own responsibilities in UI rendering and system function calls, so the frameworks of this era still have visible, or even obvious boundaries between web and native systems.

Figure 1: Hybrid Development Framework I have also encountered many people who think that cross-platform development is unreliable. However, in fact, the web container solution is the most successful example in the history of cross-platform development. It is so successful that many people have ignored the fact that it is also a cross-platform solution.

The Era of Generic Web Containers #

Although the web container solution has advantages such as a thriving ecosystem, friendly development experience, high production efficiency, and strong cross-platform compatibility, its biggest problem is that the web container carrying a large number of web standards is too heavy. As a result, its performance and user experience cannot reach the same level as native, making it difficult to achieve excellent user experience in complex interactions and animations.

In actual product development, we usually only use a small part of the web standards. Faced with this reality, we quickly came up with the idea: can we trim down the heavy web container, leaving only the necessary web standards and rendering capabilities, to maintain a balance between friendly development experience and stable rendering performance?

The answer is yes.

The solution in the era of generic web containers optimizes the three major processes of loading, parsing, and rendering in the web container era, and trims down the web standards that affect them, supporting the necessary web standards for building mobile web pages in a relatively simple way (such as Flexbox), while ensuring a convenient front-end development experience. At the same time, the solution in this era basically abandons browser control rendering and instead uses native UI components to implement the core rendering engine, only retaining the essential control rendering capabilities, simplifying the rendering process and ensuring good rendering performance.

In other words, in the era of generic web containers, we still use front-end friendly JavaScript for development, greatly simplify the overall loading and rendering mechanism, and use the native system as the rendering backend, treating the native system as the backend for rendering, providing the necessary UI controls for JavaScript code running on the JavaScript virtual machine. This is also the thinking behind most cross-platform frameworks today, and React Native and Weex are outstanding examples.

Figure 2: Generic Web Container Framework

For the pursuit of extreme performance and further maintenance of the simplicity and scalability of the solution, some lightweight cross-platform solutions even completely abandon web standards and the dynamic execution capability of JavaScript, and create their own native DSL. VirtualView, a framework used by Tmall, is an example of this approach. Broadly speaking, these solutions are also generic web container solutions.

Self-Drawing Engine Era #

The generic web container era, which uses native controls for rendering, has solved many performance problems, but it has also brought new problems. Apart from the framework itself needing to handle a large amount of platform-specific logic, as system versions and APIs change, we also need to deal with the differences in native control rendering capabilities on different platforms and fix various strange bugs. Always needing to follow the mindset of native development significantly undermines the cross-platform characteristics of generic web container frameworks.

In this period, Flutter, as a representative, has opened up a completely new approach, which is to rewrite a cross-platform UI framework from scratch, including rendering logic, and even the development language.

  • The rendering engine depends on the cross-platform Skia graphics library. The Skia engine processes the abstracted view structure data built using Dart into GPU data and then provides it to the GPU for rendering through OpenGL, thus completing the rendering loop. This ensures the consistency of user experience for an application across different platforms and devices to the greatest extent.
  • The development language chosen is Dart, which supports both Just-in-Time (JIT) and Ahead-of-Time (AOT) compilation. This not only guarantees development efficiency but also improves execution efficiency (much higher than generic web container solutions developed using JavaScript).

Figure 3: Self-Drawing Engine Development Framework

With this approach, Flutter minimizes the differences between different platforms while maintaining the high performance of native development. Therefore, Flutter is the most flexible among the three types of cross-platform mobile development solutions and is currently the most widely recognized framework in the industry.

Now, we have understood the three types of cross-platform solutions. So, when developing an application, how should we choose the most suitable framework for ourselves?

Which cross-platform development solution should I choose? #

From different perspectives, the representatives of cross-platform frameworks in three eras have their own advantages and disadvantages in terms of development efficiency, rendering performance, maintenance cost, and community ecology, as shown in the figure below:

Figure 4 Comparison of mainstream cross-platform frameworks

When making technical choices, we can refer to the above dimensions and consider them comprehensively from the perspectives of development efficiency, technology stack, performance, maintenance cost, and community ecology. For example, is it necessary to support dynamism? Is it just to solve the cross-platform problem of Android and iOS, or does it also include the web? What are the performance requirements? Is there a strong demand for absolute consistency of multi-platform experience and maintenance cost?

Considering all these aspects, React Native and Flutter are undoubtedly the most balanced cross-platform development solutions, while other solutions are more or less “lopsided”.

  • React Native, relying on Facebook, has developed for more than 4 years and has become the practical leader in cross-platform development solutions, with a wealth of third-party libraries and development communities.
  • Flutter, appearing in front of us as a challenger, can provide a more thorough cross-platform technology solution. Although Flutter has not been launched for a long time, it has already had many commercial cases. With a clear product roadmap and the strong appeal of Google, the future development of Flutter is very promising.

So, the question is, should I choose React Native or Flutter?

Here, let me give you my advice.

For the sake of learning, it is best to learn both of these application-level frameworks. In the process of learning, the most important thing is to lay a solid foundation, deeply understand the principles and design ideas of the frameworks, and focus on the choices made in their API design, and discover their commonalities and differences.

As a latecomer, Flutter has also learned and borrowed many excellent designs from the React Native community. Many concepts have corresponding counterparts in both frameworks, such as React Native’s Component and Flutter’s Widget, Flex layout thinking, state management, and functional programming, etc. This knowledge is common to both frameworks. In the future, new solutions may appear, and old frameworks will continue to update. Only by mastering the core principles can we truly stand unbeaten.

For practical projects, both of these frameworks have reached the standard of large-scale commercial applications. In terms of maturity and ecology, React Native slightly outperforms Flutter at the moment. Therefore, if it is a short-term or medium-term project, I recommend using React Native. However, as a technology choice, we need to look further. Flutter’s design concept is more advanced and its solutions are relatively thorough. In terms of rendering performance consistency and performance, it has a significant advantage compared to React Native.

In addition, Flutter’s ambition is not only on the mobile side. Recently, the Google team has completed Hummingbird, the official demo of Flutter Web, and has also made progress in exploring desktop operating systems. Whether Flutter will complete the unification of the frontend technology stack in the future is worth looking forward to.

Summary #

That’s all for today’s sharing.

The cost of developing and maintaining the same product on different platforms has always been a headache, so various cross-platform development solutions have emerged. From the era of web containers to the era of web containers represented by React Native and Weex, and finally to the era of self-painting engines represented by Flutter, these excellent cross-platform development frameworks gradually eliminate the differences between various platforms, making the boundaries of operating systems increasingly blurred.

At the same time, this era has also put forward new requirements for developers, and the era of embracing the big front-end has come to us. In this column, I will assume that you have a certain foundation in front-end (Android, iOS, or web) development. For example, you know what a view is, what a route is, how to implement a basic page layout, and so on. I will let enthusiasts who want to quickly master Flutter development learn Flutter-related code and programs, as well as the principles and design thoughts behind them, through a familiar and friendly path.

Thought Question #

What are your experiences in using cross-platform development frameworks?

Feel free to leave a comment in the comment section to share your experiences and opinions. I will be waiting for you in the next article! Thank you for listening, and please feel free to share this article with more friends to read together.