Writing in the front

In 2018, Airbnb dropped React Native for two reasons:

  • Technology: Maturity, infrastructure/class library construction costs, first screen performance issues, etc. are not well addressed

  • Team organization: high requirements for engineers, cross-stack/cross-team debugging/testing, etc

In fact, cross-end solutions suffer from far more problems than these. Sometimes Write Once and Run Everywhere are just wishful thinking

I. Technical dilemma

In a word, everything in the cross-end scenario is good until the capability boundary is reached

Take React Native as an example:

The Bridge layer connects the JavaScript world to the Native world through message communication

Shadow Tree is used to define UI effects and interaction functions, Native Modules provide Native functions (such as Bluetooth), and they communicate with each other through JSON messages

The React Native architecture is a bit old, but it doesn’t affect how you understand it. The React Native architecture is updated at www.ayqy.net/blog/react-…

In such a technical architecture, JavaScript is written and executed, calling for view rendering capabilities and platform-specific capabilities provided by Native. Facebook calls this Scripting Native solution, let’s just call it containerized Native cross-end solution:

Transform Native apps into standardized containers to allow a set of code to run across multiple standard containers, such as React Native/Weex and Flutter

(From the changes and immutable under the cross-platform technology of mobile)

Container capability is a major determinant of development efficiency, and the ability to happily do many things in one person, inasmuch as the container provides consistent standards support. However, once the capability boundary is reached, there is a high cost of multi-layer joint development (Native layer, JavaScript engine layer, specific business domain layer, business layer…). There is no human advantage. On the other hand, how to maintain multi-endpoint consistency is an extremely complex and technically challenging problem

In addition, related supporting capabilities are also directly related to development efficiency:

  • Debugging: Debugging across technology stacks has always been a challenge, and troubleshooting is increasingly expensive

  • Performance: Difficult to analyze time across threads and pages, missing performance toolchain

  • Engineering link: Due to the particularity of technical solutions, many supporting facilities (including but not limited to IDE, debugging, performance, CI/CD, monitoring) need to be tailored to reduce the cost of each link

In general, the biggest technical dilemma is this:

  • Wipe uneven multi – terminal difference

  • JavaScript hood that won’t lift

  • Unable to keep up with the supporting capacity

Consistency on technology is almost bottomless pit, and at the bottom of the platform architecture differences, event mechanism, system apis (UI rendering), with all kinds of cross side solution current maturity can only cover part of the extremely limited, have very big blank need to expand to fill the container capacity, including the basis of general ability (such as the UI, interaction), And business-domain specific capabilities (e.g., multimedia, location)

The introduction of JavaScript engines, while gaining the ability to execute code dynamically, also introduces technical uncertainty, making it almost impossible to track and resolve crashes or abnormal behavior within JavaScript engines

Most of the general infrastructure cannot be directly used in cross-end scenarios, and efforts are needed to build supporting capabilities at every corner. In order to meet the rapid growth of business, core and key capabilities are always prioritized, and supporting capabilities are usually lagging behind, which also affects efficiency

Can Flutter make a difference?

In fact, Flutter (so far, it seems) faces these same technical dilemmas

According to the findings of Q1 2020, the six most important issues for Flutter developers are:

  • Debug errors and crashes

  • Testing ensures the App runs across multiple platforms

  • Choose state management plan

  • Understand and handle layout issues (e.g., text overflow)

  • Create the UI from the draft

  • Troubleshoot platform-specific problems

Meanwhile, the six most difficult questions are:

  • Troubleshoot platform-specific problems

  • Memory problem diagnosis and repair

  • Diagnose and repair CPU usage problems

  • Access existing Native apis

  • Diagnose and fix UI stutter problem

  • Develop a platform specific plugin for Flutter

Therefore, the debugging and performance pain of the cross-end solution still continues to Flutter, and the dilemma of multi-end differences and supporting capabilities has not changed

Second, the team organization dilemma

Compared with the single-end development mode, the collaboration cost of cross-end solution is higher, which is reflected in:

  • Cross team

  • The link length

  • The container team is under pressure

  • Responsibility boundaries are not clear

Under the cross-end solution, cross-team collaboration has become the most important way of collaboration. Cross-team communication/collaboration is required in many links, such as demand communication, development, joint investigation and problem solving, and the communication cost cannot be ignored

Long links mean that technical details are scattered across multiple layers, each with only a small piece of knowledge:

Surface layer of business logic -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- a specific business domain framework -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- general front-end framework/class library -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- JavaScript engine (extension) -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- Native Module | specific areas of business ability -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- Native generic framework -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- Native View -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- platform operating systemCopy the code

Because each team doesn’t see the big picture, every problem that isn’t obvious for a reason has to be checked down one layer at a time, and even the parts that relate to specific business area capabilities are divided into many layers…

On the other hand, this multiplicity of layers creates a complexity pile-up as you go down, because the more uncertain variable inputs you have, the harder it is to understand, and the more expensive it is to troubleshoot

Ideally, layer by layer filtering according to the funnel model, each layer only needs to check its own input and output, but the lagging supporting capacity makes it difficult for the surface business to identify the scope of the problem, so the container team becomes the filter valve of the problem flow, connected with complicated JavaScript business, connected with complex domain-specific capabilities. A lot of time was spent trying to figure out what was going on, and container capacity expansion was forced to slow down and iterate over known problems…

From a business perspective, the hierarchy of responsibilities below the business is not very clear, so it is easy to find the wrong layer/person, resulting in ineffective “redirects”. The container layer also does not have a panoramic view, so the problem flow path becomes quite tortuous, and the communication cost is filled in every link, which restricts the development efficiency

3. Individual dilemma

The biggest challenge for individuals is that cross-end solutions are slightly different from Web standards, and those differences are not as clearly written down as W3C standards:

Weex enables developers to use modern web development skills to build Android, iOS, and Web apps with a single codebase.

That said, the generic Web experience is not entirely applicable and the learning curve is not very friendly, for example:

  • Rem, media query, scale/ Zoom and other adaptation experience are not necessarily applicable

  • Routine optimizations such as reducing DOM manipulation, merging JavaScript files, and enabling hardware acceleration do not necessarily result in significant performance optimizations

  • It is not enough to understand standard capabilities on top of browsers (as with the Web). To be truly effective in business development, you need to understand container principles and even some of the implementation details

Just as developers with Native backgrounds learn TypeScript, they learn how to use classes, interfaces, and static typing with ease. However, developers familiar with TypeScript know how odd the details are

What is the real meaning of cross-end?

React Native’s original starting point was:

I hope Native development can Move fast like the Web

  • Rapid Iteration Cycle: The Web releases two times a day, with shorter product iteration cycles
  • Immediate testing feedback: Web release immediately reaches users, A/B test and other experimental results are available immediately, and product evolution is faster
  • Rapid Development Velocity: Refresh the browser to take effect without waiting to recompile the App

(From a Brief History of React Native)

Therefore, from the point of view of demand, development efficiency is secondary, dynamic flexibility and rapid iteration to help business win first is the main meaning of its cross-end, or the pursuit of production efficiency, not only development efficiency, shorter iteration cycle, faster reach users are direct production efficiency progress

However, in the context of the three dilemmas, development efficiency actually affects productivity significantly, but not enough to offset significant advances in rapid iteration and dynamic release, which is a balance and an acceptable compromise

Five. Find a way out of trouble

Ideally, the container should be standardized, providing multi-terminal consistent, rich and stable capability support, and the business stack on top of it rarely touches the container capability boundary, so that the container layer can be constantly optimized and explored to better meet the needs of business development

Across, on the other hand, the complexity of the side solution just bring many inconsistencies sinking to the container layer, platform-independent language environment (JavaScript engine, the Dart vm, etc.) can ensure the consistency of the upper business logic, but the container still need a full in their implementation, how to ensure a full container capacity of consistency, Still a big problem, and not much easier than in the non-cross-end scenario

Therefore, the problem of container capacity richness should be solved first, so as to broaden the boundary and reduce the problem from the root. Instead, focus on the real problems, attacking the most valuable hard parts. At the same time, establish a full-function business support team through virtual architecture to reduce communication costs:

  • Business should have self-research ability: solve the resource bottleneck at the lower level, and jointly enrich the container capacity

  • Focus on the things that you have to put a lot of effort into: commissioning capabilities, standardization, performance analysis and continuous tracking, engineering infrastructure

  • Have a fully functional business support team: the ability to address all issues, truly deliver a package solution, and eliminate meaningless communication redirects

Among them, the business self-research ability should first have a standard expansion mode, requiring the container to be easy to expand, business developers can quickly enter the development without knowing too much details. Debugging capability is critical in the long link technology stack. The lower the cost of problem identification, the higher the accuracy, and the higher the efficiency, the more resources can be released

From a business development perspective, a layer of gateways that request past and respond back may be more needed than a series of routing tables that need to be tracked hop by hop. The full-function business support team formed the LAN, so that the traffic behind the gateway can be quickly transferred, and the happiness of business development can be improved while efficient collaboration

The resources

  • What is Weex?

  • What are the important & difficult tasks for Flutter devs? — Q1 2020 Survey Results

It is good to have gained and confused

Follow the “front end back” wechat official account and you will receive a series of “heart original” high-quality technical articles on topics including but not limited to front-end, Node.js and server-side technologies

This article was originally published on ayqy.net. The original link is www.ayqy.net/blog/cross-…