preface

Since many people are confused about cross-end technology, ALTHOUGH I haven’t actually written cross-end framework from 0 to 1, I did some simple cross-end things with Yoga(React-Native layout engine) and later used Weex. I studied cross-end for a while, so here are some tips.

Before we do that, first of all, why do we need cross-end technology? Do Weex and React-Native count as cross-terminal technologies (excluding Flutter)?

Why do you need straddles?

One set of code, multi-terminal operation, reduced labor costs?

Not really. It looks like Android/iOS was supposed to be two people, but it ended up being one person. I’ve cut my manpower by half!

But the premise is that the manpower needs to be able to both Android and iOS, but also to write JavaScript, and also better understand, otherwise there is a problem, how to repair?

So it’s very difficult to recruit such a person in China’s Internet environment. Everyone is studying PPT architecture technology, workplace survival theory, how to be rich and free at the age of 30, which time to expand their own technology stack?

Dynamic capability (which I think is the point)

On the end of the development is miserable, often Crash(app Crash, flash back) and can not be fixed remotely, can only wait for the next version of the app market to promote a new bug-fixing version.

But if you launch a new version, users don’t necessarily upgrade. Therefore, many companies have studied various hot repair frameworks, especially on the Android platform, there are many hot repair frameworks, mainly relying on DexClassLoader.

The dynamic ability of H5

Therefore, a lot of active pages often use H5 to do, H5 do as long as the update js, CSS and other front-end resources to the server, then everything is OK. And it can also run on the browser, the browser itself is a cross-app, front-end development is not difficult to recruit, how happy.

Therefore, until today, many apps are still developed in a Hybrid way, also known as Hybrid apps (that is, a web page is loaded through the WebView provided by each platform, and the source code of the web page is updated to make it dynamic).

However, WebView was problematic in the early days, especially for Android. And loading web pages, it certainly takes time, the process will be blank ah and so on. So a lot of people have made a lot of optimizations around this, and the one that I personally find most useful is actually an offline package. At the same time, each generation of WebView is also updated and upgraded. Then some powerful companies have developed their own so-called browser kernel, all kinds of black technology, how to speed up ah, a variety of features support ah, but it seems that there is no open source 🐶.

Weex, RN, Hippy, MLN, etc.

It doesn’t count. It just crosses Android and iOS and doesn’t treat me as a PC?

In fact, browsers are cross-ends, and you can use Chrome on every platform (other browsers are mostly optional)! But there are problems of their own, as each has its own browser with a different kernel that is increasingly fragmented, Chrome(Blink)/Safari(Webkit)/Firefox(Gecko?). And so on, especially CSS support.

Developer.mozilla.org/zh-CN/docs/… This site can be viewed for some browser compatibility. For example, the compatibility of border-width is as follows:

So the question is, why not just use the browser’s rendering technology for cross-ends?

Actually I don’t see why not, but doing so is equivalent to directly to OpenGL programming or other graphics engine, and rolled all the way from the bottom to the top, yourself a rendering mechanism, and also to encapsulate various basic UI components for developers to use, or leave a lot of cut, the custom UI for developers, is very complicated. This is exactly what Flutter does, so Flutter2.0 is moving to the desktop again, not just Android/iOS, but how far it will go I don’t know. Some people do react-native Skia and use JS code to call Skia directly? (Not really)

What is JavaScript Engine

Why does your JavaScript code work? JavaScript Engine.

Throw it a piece of JS code (essentially a text string) and it will do the math and the logic for you.

Common Weex, RN, and Hippy also rely on this (MLN uses Lua) for logic processing.

At this point, there are many concepts

JavaScript Engine is also known as JavaScriptCore. (I don’t know why, but it’s probably because most of the people who study it are iOS developers. Apple’s JavaScript Engine is called JavaScriptCore, and many people like to call it JSCore or JSC. So when I see these terms, I always have to put them in context to see if they mean JavaScript Engine, or if they mean Apple’S JavaScript Engine — JavaScriptCore(JSCore/JSC).

What is JavaScript Engine?

Yes, there are so many! And of course JavaScriptCore(not here).

The last line is run points, as many as possible. The V8 with the JIT blew everything up with 3W +. QuikJS is small and has a high score, so many people will use QuikJS as a cross-end JavaScript Engine. Hermes was created by Facebook and appears to be the JavaScript Engine RN uses for Android instead of JavaScriptCore. Why hasn’t RN used V8? I don’t know about that

But there are plenty of people working on V8 for Android, and there are open source projects on Github. The second is that iOS doesn’t support JIT and has its own JavaScriptCore, so it doesn’t make sense to switch to V8 without JIT.

Weex/RN cross-terminal principle

The simplest case for a normal cross-end frame looks like this (the problems will be explained later and further enriched) :

  1. Throw a JS file to the end, open the JavaScript Runtime on the end, and pass the JS text to it
  2. The JavaScript Runtime does all the parsing and sends a message to the client via the established messaging mechanism
  3. The client takes the message and parses it to create a view of the platform based on a given format (there are a lot of issues and details about this, described below).

Let’s do a simple example

Let’s say I want to show a red div box in my JS file. First, the JavaScript Runtime will pass this text to the JavaScript Runtime, which parses it into a convention format, such as JSON (the value is described as a 100*100 red square, which I arbitrarily defined).

{
    "name":"div"."width":"100"."height":"100"."background":"red"
}
Copy the code

The JavaScript Runtime communicates with the end (Android/iOS) to send this message back.

When the server gets the message, it needs to create a 100*100 object called div. There is no div. For example, if you have FrameLayout in Android, you will have a similar registration code

/ / pseudo code
register("div", FrameLayout.class);
Copy the code

And then the end knows, oh! I need to create a square that is 100 by 100.

What if I don’t have that div?

First of all, the framework design thought ahead of time about which basic components to support, such as image, text, and so on. Also, there is usually an opening for developers to extend components themselves. For example, if you need a scroll list, what if you don’t provide one? Take a look at how div is registered, and follow its process to register a list. This can also be BLOWN into PPT: extended cross-end frame, in fact, the threshold is lower than custom View.

What is JavaScript Runtime?

JavaScript Engine is a JavaScript Engine.

What does JavaScript Engine do? Do nothing but parse and execute JS code

So the question is, how do I describe the view that MY JS code represents? In fact, there is no need to describe, js code only need to maintain a tree structure in memory, is an Object, because the entity in the concrete end, how to understand?

The left-hand side just maintains this tree structure in memory, and when passed to the client, converts to

{
    "name":"div"."children":[
        {
            "name":"image"
        },
        {
            "name":"div"."children":[]
        }
        / / etc.]}Copy the code

Get the message on the end and create the structure of the view shown on the right.

How do you maintain this model? What JS method is called to send the message? How do you add CSS to these divs to describe their size and shape? And so on more complex a series of front-end problems, all need to write code to achieve.

So there’s usually a bunch of js code like core.js or framework.js that handles these things, and this code also relies on the JavaScript Engine to execute it.

In my opinion, the so-called JavaScript Runtime can be simply understood as the environment after the JavaScript Engine’s own code runs, or the environment after core.js and other front-end codes containing various logic are loaded and run, which are required by cross-end frameworks.

How do I know the location and properties of each view?

When you use these cross-end frameworks, you’ll notice that they only support a subset of CSS, and the layout is mostly flexbox.

So if you write a large square with three small squares across it, your front-end CSS code must say flex-Diretion :row, and the message thrown to the end might look like this:

{
    "name":"div"."attribute": {// Use the layout
        "flex-diretion":"row"
    },
    "children":[
        {
            "name":"div"
        },
        {
            "name":"div"
        },
        {
            "name":"div"}}]Copy the code

I don’t even know what Flex-direction is when I get this message. Of course, you can write your own parsing library to solve it, but Yoga does it for you!

So RN uses the Yoga layout engine (which supports Flexbox, also made by Facebook).

Weex seems to have started with Yoga and then wrote one of its own?

The term Layout Engine helps us to deal with various Layout parameters, and then helps us to calculate the coordinates of each view, and then set the corresponding coordinates of the view on the end of the coordinate, a well-organized view will be displayed. If you think your layout parsing algorithm is better than Yoga and so on, you can write your own.

Other problems

Through some of the above reading probably also have a concept, in fact, cross end, is the process of continuous communication at both ends.

For example, after processing various properties from the JavaScript Runtime, it’s time to render the view! A piece of JSON is passed to the end.

When the user points to the view, it also wraps a message to the JavaScript Runtime, which then triggers the JavaScript listener code you wrote earlier. For example, when a popover is clicked, it wraps a message to the user that calls the popover method.

It goes back and forth.

So each side has its own message queue.

And when you’re doing an animation and you want to listen to the animation, you’re sending a lot of messages in a short amount of time, and these processes need to be optimized.

And!!! According to my personal experience with Weex, some flexbox attributes are not uniform at both ends (it may be a Bug of Weex, after all, KPI projects are not maintained).

I remember joking at the time that Weex had finally taught me the true meaning of cross-ends:

if(platform === 'Andoird') {
    // Differentiation logic
} else if(platform === 'iOS') {
    // Differentiation logic
}
Copy the code

The cost of cross-coding is that you think you can really run both ends of the same code, but it turns out to be a bit of a dream (even H5 sometimes has Andoird/iOS inconsistency because it uses different kernels), and there are a lot of if-else in the code.

conclusion

So after the above series of popular science, a cross-end frame looks like this:

This generally requires a client, a front-end, a JavaScript Engine will be C/C++ to develop respectively.

I haven’t developed it yet, but I feel like there are a lot of problems.

Like JavaScript Runtime in another process, cross-process communication?

For example, if message communication is too frequent, there will be all kinds of chain reaction, such as frame drop, event response is not timely, animation is not smooth, how to optimize?

Like the details of Hippy JS Binding?

conclusion

In fact, I have been proud of myself like the principle of research, but until today I have not really a line of cross-end framework source code, I know these may not be right, but before doing Weex some work a little research, or quite ashamed.

Since you claim to enjoy studying principles, why not?

So, I have time to look at the source code a little bit later, if there are mistakes, update at any time.