Focus on front end early chat and follow up 30 world conference | front-end chat early special BFF (GraphQL, unified gateway, API access management, large scale cluster, protocol conversion, security section, high concurrency, visualize, construction layout, unified stability…) 8-14 all day live, 9 lecturers, click to register for live 👉) :

Front end early chat conference, co-hosted with nuggets. Add Codingdreamer into the conference technology group, win in the new starting line, all the past have full recording, one time to unlock all the old year ticket


This article is the 18th session – front end early chat performance optimization special, is also early chat 127, from the Alifei pig – tai share.

To introduce myself

Hello, I’m Hu Hao from Flying Pig. My flower name is Taigo. There is no hurry to start, because I just saw the screenshots shared by the previous mentors in the circle of friends of the little assistant, and I also saw some questions from you. Some people say that I have a corresponding article to share this article in the Nuggets, I believe that there are also a lot of friends may have read that article, I want to say that saw that article should not listen to my side to share, I think or to listen to.

The main role of the article is a spread, and some dry goods must still be in the PPT, so we still do not let go of the front end of the early chat in 2020 the last time to share. The first two are more hardcore: ides and visualizations. We finally return to a traditional performance optimization for H5, which may not be as hardcore as the first two, but hopefully will give you some inspiration.

This PPT was also used for sharing within our group before, so it is a bit lazy. In fact, most of the content is similar, but some external still need some specific explanation. This share is “Flying Pig Double 11 – Web-based Performance Optimization”. One of my responsibilities at that time was the performance PM of Double 11, so I still have a certain understanding of the overall Web performance optimization of Double 11. I hope to bring this understanding to you.

directory

The whole thing is divided into three parts.

  • background
  • Direction of optimization. The main optimization means are the six things you see on the right, which will be explained later.
  • Summary and Planning

background

First, the background. What are the considerations for moving from Weex to the Web?

Technology stack evolution

From the landing of the first H5 page in 2013 to the overall switching of Weex in 2016, both Weex and Rax are mainly Weex rendering in the flying pig end and hand washing end. Until June 2020, we switched back to H5 in accordance with the overall strategy of the group, and unified the technology stack, using a technology stack of Rax1.0 as a whole.

Some of you from Rax may have come to the front and talked about it earlier. How do we switch from Weex to H5 based on such a consideration that we still have better confidence in Weex performance than H5? But why switch from a relatively good Weex technology stack to H5? This is mainly based on the following considerations:

  • First, we believe that THE DEVELOPMENT experience of H5 must be the best, and after upgrading UC U4 kernel and WKWebview in the flying pig end, we believe that the performance gap with Native is gradually narrowing, so we can try to render H5.
  • Second, in view of the previous alipay small program strategy, there are more and more small program development scenarios, and the small program development dynamics it is insufficient, because its traditional development significance and H5 system is relatively separate, is the need to develop two sets of code. If a page to invest in small programs and H5, it needs double the development cost, we are more unacceptable, after all, manpower is so precious;
  • Third, we still want to unify the solution of the technology, and we want to have a set of code that can be put on multiple ends, supporting H5, small programs, and future Flutter. It’s actually the current Flutter;
  • Fourth, Rax1.0 can also support Weex. Why is it not compiled into Weex? Because Weex and small programs have their own compatibility to develop, it is a subset of the traditional apis as well as some individual apis. So if we had to adapt Weex and small programs at the same time, it would be disastrous for development. There is a simple comparison of development difficulty, simple development of H5 is not limited, I believe many partners are happy to develop, but small program it has certain restrictions. If the development of Weex and small programs at the same time, both ends of the compatible, it will be unacceptable. And if it is H5 plus small program, also only need to go to a simple adaptation of a small program can be completed. This is relatively acceptable.

This is the overall context.

Difficulties faced

In this context, the performance of H5 must be less than that of Weex. Before just switched H5, two big promotion (618 big promotion of National Day), flying pig’s performance in IOS is about 1.5 seconds, Android is about 2 seconds. Compared to the tao department 618 venue performance 1.4 seconds and 2.1 seconds, is relatively similar. You basically ran out of common optimizations and needed to go into a deep water zone. For Flying Pig Double 11, the target is IOS 1.2 seconds, Android 1.6 seconds, the overall level is to improve about 20%. It is also a very big challenge to increase it by 20% when the general means have been exhausted.

And in the case of the flying pig:

  • The modules of the Flying Pig conference are complex. Business operators have many ideas for the tourism scene. For example, there must be a video in the head picture to attract others to play. And the interactive animation module of the flying pig side. There is also the flying pig list type, and there are some list aggregation modules, which are quite complex. Some are front-end time consuming, some are algorithm time consuming.
  • The INTERFACE RT is relatively high. And there is no way to optimize the server. Similar to the list this scenario, it is the aggregation of multiple lists, there are personalized lists, and the algorithm wants to add a variety of models, to more pull up its RT, the theory can bring a certain click through rate, you can’t refuting others. So you just have to let it raise RT as much as it wants, and there’s nothing you can do about it.
  • Some characteristics of the travel industry. Some of our personalization or some modules are more dependent on location information and user information to push some corresponding products to you, location information and user information will more slow down the time of a first screen, so this is the whole optimization faced with some difficulties.

To optimize the direction

In view of these difficulties, the vision from the front end is separated from the side, standing in a direction of multi-functional synergy, mainly with the help of some of the client and server capabilities, to carry out an overall optimization.

Optimization idea

An overall optimization idea, first say a general optimization idea:

  • The first stage is white screen. The whole, for example, is similar to a page, which opens at such a pace, from the beginning of the white screen, is mainly a Webview initialization and main document download, basic JS download. The previous lecturers basically mentioned these processes, and the front-end optimization approach certainly relies on client-side caching, as well as the general approach of reducing the size of resource bundles;
  • Loading condition of the second stage. This is basically a stage where data requests occur. In this stage, common approaches can be used, such as server optimization, request splitting, and the idea that a page’s data can be split into first and non-first screens. First screen rendering, minimal DOM, minimal modules and some data preloading. The data parallelism that we talked about earlier and the way that the client makes data requests in parallel. I’m not going to go into the details of that, as mentioned by several previous lecturers;
  • Last stage module on screen. Slowly elements can be loaded onto the screen. The main thing that happens during this time is module JS loading and module rendering. Here the general means is basically for the module JS simplification and is for the module cache. Here to mention a point, our venue is basically the scene of construction, construction is a concept? It is a Layout at the bottom of the page. You can think of it as getting the modules needed for a certain page from the server according to the parameters, and then pulling down those modules asynchronously, filling the data into those modules and displaying them. This is the idea. Similar to what you would do if you took a generic page and split it up into several modules to render, which modules are determined by the server data, similar to building a scene like this.

Based on these general means we have thought of, we are sure that will be used up, and after the use of the effect as mentioned before like 618, National Day promotion is already a peak, and then want to optimize, will be separated from these further optimization. Enhancement methods include the following:

  • Pre-rendered. This is the key to ensure the opening effect of a main venue. The implementation will be mentioned later;
  • SSR. As mentioned by the previous lecturers, we may mention less SSR in the C-terminal scene now, and use less. But now we’re back to SSR. Why is that? Also to improve the second opening rate. Weex before the case, in fact has always been to raise the second rate, but after switching to H5, may indeed not Weex at that time so good, so we need to use some SSR such things to improve our page second rate;
  • The Snapshot. Similar to the page snapshot mentioned by previous lecturers, some of the page data or page HTML directly stored. Before the arrival of real data, show a page structure in advance, can greatly advance the user’s visual time, so that users are not so anxious to wait;
  • SPA. One page applies such a thing. The aggregation of multiple pages to ensure a smooth jump between pages, to enhance the user’s sense of body.

It is mainly these four points to guarantee the scene of a double 11 big promotion.

In terms of the overall idea of the rendering process, the block bar corresponds to the part of the above rendering process that can be streamlined. You can see that the SSR, Snapshop, and pre-render effects are getting better and better from top to bottom, but it’s definitely getting less and less applicable to the scene. We’ll talk more about that later. Things like client preloading, offline caching of resources, morphing requests for data, and caching of modules are common methods that have long been integrated with clients.

The main idea of the whole is to transfer the pressure from the client to the server. Some caching, client-dependent capabilities, phase morphing, and finally some motion optimization for the user to give the user the best possible experience.

pre-rendered

First, pre-render. The lecturer also mentioned preloading before, maybe the flying pig side is a little more radical, you can look at the effect on the right first. After opening the pre-render on the left, click on a capsule like the main venue, jump to the past and open almost seconds, without any rendering process that kind of feeling. On the right side, if pre-render is not enabled, there will be a white screen, Loading and Loading of the module, which is an obvious contrast.

What is pre-render? The client initializes the container and LoadUrl “off screen”, rasterizing the page before going on screen. So the client just loads the URL in the background through the Webview, and when we need it, it just loads the Webview into an up-screen operation, so it’s a little bit more aggressive. However, in order to guarantee the key of the main venue, or in the end side of the side to do such a capability, the experience is better.

What features does pre-render it?

  • No feeling straight out. An obvious experience;
  • End – side customization. This may be due to the coupling with the end side, perhaps only the flying pig end can use such a capability now;
  • A few pages. At present, it is only used for the main venue, because if you think about an APP background to continuously launch such a Webview, it will definitely consume a lot of memory and may cause some crash risks. Therefore, it can only be configured with a small number of pages, and the crash rate will definitely be higher and higher.

However, after such a pre-rendering scheme, the FCP (first screen first rendering time) from 1~2 seconds, up to 100 milliseconds on the front side, in the client side of the dot is basically 50~60 milliseconds, can complete a page display, quite fast.

The project design

For the overall design of a scheme, we will have a dynamic delivery platform like Orange to configure a URL that we want to pre-render, and it will be dynamically delivered to a user’s APP. After obtaining these configurations, the APP will load such a URL in the background and parse the page. After the rasterization of the page is completed, it is put into the cache pool. We will also start a memory warning monitoring to ensure the stable operation of the APP. If there is a risk of crash, we will automatically release the page in the cache pool.

When the user actually visits the H5 page, we will check whether the user matches the pre-rendered URL configuration. We’re going to have a URL domain name, and we’re going to have some specialized parameters of the URL Query, to compare the key. If it hits, the URL will be used as the key to find the Webview in the cache pool and directly perform an operation on the screen. The GPU will directly perform the display on the screen. Since the client has rendered the page in the background, there must be some logic that does not match the front end, so we need to send a document event to H5 after the actual screen, after the client has rendered the page, after the front end listens for this event, We’ll do some handling of performance burials, page burials, and finally some of the events that are dynamically dropped, all of which need to be compatible on the front end.

Once this is done, the overall presentation logic for the page is complete. After the user exits the page, we will clear the corresponding Webview cache, and restart the new Webview in the background to load the page immediately after 300 milliseconds, and start the whole process again.

Prerendering is a more radical approach than preloading, which only loads a Webview container and does not request real data. But the effect will be relatively better.

SSR

The second solution is SSR. What is the purpose of restarting SSR? Generally, the definition of SSR in the group is gradually transferred from the original server-side-render to serverless-side-render, conforming to the tide of Serverless, anyway, the useful place of SSR is gradually discovered. This is not the traditional sense of SSR, as the traditional sense of SSR is similar to the PC era of the main document, directly return to the HTML main document of the kind of SSR.

The difference between us is the comparison of the following two rendering processes. The above is the traditional CSR rendering process. With the help of the document cache on the client side and the pre-loading of data, the JS module and the rendering module are carried out. In our case, you can see from this diagram that our SSR is the HTML returned from the interface, and after the interface returns HTML, we are sending the HTML async hydrate to the page. We are essentially avoiding loading the JS module and rendering module later. Because the HTML is returned in the interface, the interface may be a little slower than usual. We thought it would take about 10 milliseconds to shove the HTML directly into the page. In this way, we can save 700ms ~ 800ms on the side of JS loading and rendering time of the latter module, which is a comparison between SSR and CSR.

The project design

The whole rendering process was changed based on this consideration, instead of returning the entire page structure directly in the main text in the traditional sense, it returned the HTML when the interface returned for another rendering.

The thinking behind this is mainly based on the following consideration: before the hantao side also did such a scheme, they did synchronous SSR put in the main document to return. They discovered at the time that with synchronous SSR, one is that the white screen time becomes longer because it does not use some of the client’s capabilities, such as offline packages and data preloading, which both clients provide a good capability. We followed up with an asynchronous SSR scheme that returned HTML in an interface.

It has several advantages:

  • Reduce the time spent on module Load before rendering. Basically, after the data comes back from the module, we can display a page without waiting for the module to do a pull and render the module;
  • Rendering is placed on the server side to avoid the impact of high and low machine containers. On a high end plane it might be a render or a module pull that doesn’t have much impact. But for low-end machines, for some modules pull and render, this is very time consuming. By putting the render on the server, you can avoid the impact of such a high and low machine container;
  • The ability to reuse a performance optimization from the client. This way we can use the ability of the client to provide offline packages and data preloading without wasting some of the client’s power.

We are based on the principle of minimizing the cost of renovation:

  • Just add one SSR render link based on the existing set up link;
  • Smooth switch from CSR to SSR can be achieved;
  • We can switch to different links for rendering just by judging whether the HTML is returned, and the modules can be reused basically, thus forming a SSR effect with very small retrofit cost.

Difficulties encountered

  • One is how do you do a smooth switch, which is what if something goes wrong with the SSR? How do you downgrade back? Based on this consideration, we only need to judge whether the interface returns HTML on the front end, and then we can go to a different link, which is a more direct way to solve the problem;
  • Front-end stability considerations. Because SSR must have many modules, it may just use some variables, or it may use some asynchronous, may not get the specific data of the module on the server side, so when the return may appear similar error or similar to the module did not show at the beginning, This is then shown when the Web is at Hydrate, with a page flashing. This is an overall upgrade to the business module, one is to do some variables in the SSR layer pocket, and some similar to the module placeholder such a process, to ensure that the page initialization and hydrate update minimum;
  • A support for immersive Titlebars. An immersive TitltBar must depend on some variables on the client side. The height of the navbar on the client side is a necessary parameter of the immersive TitltBar, whereas SSR certainly does not obtain the client side parameters. We later found that there is a gap in the innerHTML to get the height of the titlebar, so we can dynamically set the height of the titlebar through the style at this time to achieve an immersive titlebar support;
  • One last point, because we’re now building this side all by unifying the render page. There is such a thing as a uniform render page whether it is offline, data preloading, or some module caching. And a unified render page like this, when it goes offline, it has the SSR configuration in it, it will be fixed there, it can’t be targeted at a single page, it is equivalent to all your pages to open SSR. Some of our pages certainly do not necessarily fit well, or based on traffic considerations, it is impossible to open all pages SSR. So we have to add a layer of interception to determine whether to use SSR links or normal CSR links. We will intercept a domain name and determine whether it is in the whitelist by judging the following query. In the whitelist, the SSR link is used; otherwise, the CSR link is used.

After completing these considerations, we successfully implemented the SSR scheme and achieved good results, basically reducing the average time to less than 1 second after using SSR from the previous 1 or 2 seconds.

Snapshot

Page snapshot. If Snapshot is enabled, there is no Loading. If Snapshot is enabled, click on the page and the page will have a direct effect like straight out. Snapshot is definitely better than SSR in practice, but why do we need SSR when we have Snapshot?

  • First of all, we are in the marketing page such a scenario, the return rate is relatively low. Only 10% to 30% of a page’s users go back to the page a second time. So Snapshot cache that data, and its hit rate is only 10% to 30%;
  • The second is that Snapshot is suitable for a scenario that is not a thousand faces. Something similar to what previous lecturers have said is that the timeliness of the product is a problem, so some scenarios are not suitable for Snapshot.

For this page snapshot, we have designed two solutions. One is interface caching, and the other is traditional HTML caching. Why the coexistence of these two schemes?

A venue every day will change array, in fact, you see double 11 or double 12, you go to the venue, every day the module order and module data display logic, operation will be modified every day. Therefore, in the case of everyday changes, if the HTML cache is used, there will inevitably be some flashing problems. Yesterday you visited this page, for example, today again to access this page, it may have several modules have no, or a few goods, its pit from four to six, so you go in, it flash, applauded the entire page will clap, disorderly and the flashing process, it can bring a lot of trouble, may be some unpredictable problems. For example, modules may be rendered repeatedly, and for some modules it may be misaligned, a particular metaphysical problem.

So we designed a second way of interface caching, interface caching with module caching, and basically the same performance as direct HTML caching. Because interface caches and module caches are relatively fixed, they avoid flickers, and why do we have such a thing as coexisting, we can see that HTML caches are not completely useless, just like the scene on the right, the whole session scene, which is basically unchanged during the whole event. So the use of HTML cache to bring a higher and faster loading efficiency, is the use of HTML cache.

The project design

The whole scheme design is as follows:

  • * * HTML cache. ** Its advantages are fast display and easy to operate, and its disadvantages are that in the case of uncertain module loop, the page may flash, but it is suitable for scenarios like the whole session. The HTML cache is kind of like you can think of it as after all the pages have been displayed, you save a DOM from the first screen into the cache, and then the next time you go to the page, you take that HTML from the cache, you shove it onto the screen, you put it on the screen first. After the actual data comes back, run a hydrate operation on such an interface;
  • ** Interface cache. ** Why interface caching is related to page snapshots. Because just said to build such a scene, which modules are actually the interface to return, data is also returned by the interface. So as long as we cache the interface, we know the page which modules it has, and what the data of those modules is, as long as we cache the interface, we can directly display the page through this interface. Its advantages is the page display is very stable, but the disadvantage is relative to the HTML cache, it shows relatively more slowly, and cache it a JS, the whole page is to cache the whole interface down, compared with HTML cache, it caches will take up the space is very big, but it’s more applicable scenario. Some of our main sessions, such as Super Baby, List sessions, and Feature sessions, use this interface to cache page snapshots.

Two more points, some design ideas:

  1. The first one is in the HTML cache, like we have a little bit of timelessness, we don’t want to do an HTML save, DOM save, we can customize some class names. To set up those modules, and when it’s time to save, we’ll identify the class name, and either remove it, or save only the parent node, so as to solve the problem in a timely manner. Another thing you can do based on a class name, you can do something like a scroll list, where we save the first few items, or something like a header banner, where we save the first item. Such a reduced HTML cache size and efficiency design;
  2. The second cache master controller. If the cache is unbounded, it will not work. We must design a master of the cache to control the number of caches. We used LRU (algorithm) to slowly remove the least used and furthest accessed cache data, and put the new data into the cache, overall control of a maximum number, we should at that time should have a maximum of 8 cache. After the number exceeds 8, a number of culls are performed to ensure the stability of a cache.

SPA

And finally, SPA. We slowly in the page of some optimization, to the user experience is also very good. But the experience of switching between pages is not very good. Because you actually saw the Tabbar on the bottom. However, it is actually multiple pages. If you switch the Tab at the bottom like the previous way, it is actually a jump to a page, in the replace way, and the whole page will be refreshed, which is a very bad experience.

On Double 11, we made an improvement on it. The bottom bar is the whole package box. When we switch by clicking the bottom bar, we only need to get the data. Or just mentioned that point, our page is through the data to obtain the module, through the module assembly. So we just need to know what the modules are, and we can put the pages together. So when we switch tabs, all we have to do is get the data, get the module, replace the DOM of the page, and we can do a switch to the page without using the whole replace.

Why is it based on a SPA implementation? Again, at that point.

  • A relatively mature system has been formed to build the page, that is, our page frame, which shares a set of solution/core-render. It will not be associated with the page, that is, the business module, and the Layout behind it is the same, but the module above is different, so the pages you see are different. The rest of the Layout behind is always the same;
  • The second point is that each page business module is obtained through data, both of which are necessary conditions to perform such a SPA switch. It through the data acquisition module, we only need to carry out a DOM switch, you can make a jump between a page, jump back, we only need to cache the module, you can form a non-inductive switching effect.

Evolution of optimization

After the first version of our design started SPA, we got the data of that module, replaced the module corresponding to the current TAB, and updated the page. However, we found that there is a problem with this: if the whole to constantly replace the module, it is still relatively slow. There was a little bit of a gap between what we thought of as a single page app in the direct traditional sense, so we upgraded it.

We only cache the DOM on the first screen to reduce the data acquisition process. And on the high end we’ll request that the first TAB is rendered, and then we’ll preload the other TAB. So the next time we switch over there’s no data fetch, we can just grab it. It’s like having multiple pages of data all at the same time, and then we can cut the TAB to create a silky switching effect. All we need to do is hide the DOM in the other Tab containers. Just display the DOM that you want to display.

Resources & data precache

And finally, two little points that the lecturer and they talked about earlier. Basically every optimization takes advantage of the offline capabilities of the client, parallel requests for offline packages and data, which I think is basically what H5 uses every time.

But for a small design, we have designed a **URL + package ** method for the meeting page. We will input the page that needs to be offline on the carrier pigeon, which is our background, in the meeting scene. Our carrier pigeon will run a puppetter in the background to get the resources of the page, and then through some scrolling operations to get some lazy loaded resources. You type the entire resource into a bundle and then use a hash to match it when you visit the real page.

Secondly, as a part of data parallel request, we have designed an Ongoing state of Memory hit and Miss relative to normal. We think that as long as the client initiates a request, it must be faster and earlier than the actual request from the front end, because it must be in advance, so we will wait for the real request from the client to return, and then we will get the data from the client, rather than re-issuing the request.

Summary and Planning

I’m not going to go into the details here, but it was a goal that we had at the time, based on what we were talking about, whether it was general means, or some enhanced means. The universal tool may also be a great help, and the enhancement tool is a step up from it. At the end of the day, there is a goal, and with these things, we have a sense of what the future holds.

conclusion

Performance optimization will gradually find a way for it to evolve from one function on the front end to a multi-function synergy. And over time, if you optimize, you’re definitely not going to be able to have a perspective on the front end, and over time you’re going to rely on things like NSR and server SSR and we still have ESR which is CDN edge computing and that’s going to be something, Slowly you will find that performance optimization is slowly detached from the front end of such a simple function such a aspect, you have to stand in the way of multi-intelligence coordination performance optimization attempt.

planning

The plan is not so detailed to mention a few:

  • SSR synchronization scheme. We talked earlier about asynchrony the way HTML is returned in the interface, the asynchronous scheme. The synchronous scheme is the way the main document is, the asynchronous scheme is definitely good in the end, because it directly after offline package, through the data prefetch parallel request directly after the HTML, directly to the screen, so it must be very good. But in the end, we will have a lot of, such as alipay, hand Amoy this scenario, it does not use some offline packages and prefetch in the end, so we still need to do some direct master document return;
  • Page Abtest;
  • Client side, to consider the access to NativeTab so switch to the way of multi-tab;
  • Some performance optimizations for call cases, with so many new optimizations, definitely require unified state management.

And so on and so forth a series of internal improvements, and our goal on the flying pig side is to reach 90% of the front end in two seconds. Therefore, simple single business, single business in our end, of course, we need to expand to multiple business. Our idea is to have an optimized means and within the group, we are now across the team performance is a white paper on such a way, to record some optimization methods, slowly to push the business, to carry on the ground, and to collect all the business of some good means of optimization, to precipitate feedback, to improve the overall performance up to slowly.

Recommend a book

Finally, the convention recommends a book, and the one recommended here is the Pyramid Principle, which is a logic similar to writing a POWERPOINT presentation or thinking about expressions and solutions. Writing PPT, writing articles and so on such a logic, is a set of logic is clear, prominent focus, clear hierarchy, simple and easy to understand the way of thinking and expression and standard action. I think this book is very good. After reading for making PPT or writing articles, are by a lot of help. Those of you who are interested can go and have a look.

The team propaganda

Finally, the convention of conventions, of course, needs to be hired. Our team is the user front end and digital management team of Flying Pig. Our business is about tourism. We can try everything. The basics of our team. Before, our team, South Road, also came to share a Web Flutter scheme, our team has Flutter, so now SSR is also our team based on Serverless such a tide to do. There are also some micro front end in the background, as well as integrated development and interaction at the end, as well as intelligent building such a thing, our team’s technical ideas are included. So basically all aspects are covered, so if you are interested in waiting for you, you can email P6, P7, the more the better.

You can also pay attention to the public number of our flying pig technology, Fliggy F2E and nuggets, some before I saw this article in the nuggets on the hair, but also by our flying pig front here column to collect. If you have ideas on the performance of the cross-end side, you can also add my wechat to understand.


Stay tuned for the front end chat early, follow up to learn more about BFF/GraphQL, Please pay attention to 30th | front end early chat end interface before and after the conference special BFF – play (GraphQL, unified gateway, API access, API management, protocol conversion, unified security aspect, stability high concurrent processing, visual layout, unified construction…). 8-14 all day live, 9 lecturers, sign up to watch live 👉) :