Note: Think of this article as an accident record, an online accident. Now I can sit here and write this article, thanks to our company did not fire me, or I solved this performance problem, so I have the opportunity to write this article.
The cause of
Our company’s global purchase business has been revised to adopt Hybird mode to develop the original global purchase page. This is the first time that our COMPANY’s H5 page appears in the entrance position. As a developer, I feel very excited.
Stage 1 – Problem first
The problem
According to the design draft, the work was completed as scheduled and the test was ready. Some low-end Android machines showed the stalling phenomenon. Out of the affirmation of my own skills, I mistook it as a hardware performance problem and did not attract too much attention.
plan
Not taken seriously and not dealt with accordingly.
Stage two – Getting attention
The problem
After the pre environment was uploaded, some iPhone models were found to crash. Preliminary investigation showed that the crash rate of DOM node height above 10000px on iOS 8.4 system was 100%. For other system versions between 8 and 9, when the DOM was above 10000px due to pagination data and rapid scrolling, there would be lag. IOS 9 above and Android4.4 above both performed well. After locating the problem, I quickly tested more special models and corresponding systems. During this period, I borrowed the mobile phones of hundreds of my friends in the company. I would like to express my gratitude to them.
You ask me why, I can only say that the test environment does not have such data, and why not? Ha ha, you know!
plan
-
IOS will switch UIWebview to WKWebview, WKWebview is a high-performance Webview newly added by iOS in the system above 8. You can click here, here and here for details. Since iOS has been released (yes, when the H5 page is still tested in the pre environment, IOS has been released) this solution is only available as the next version
-
Temporarily reduce the total amount of data displayed while looking for performance bottlenecks (sorry to the operation students here)
The implementation of
Automatically degrade iOS 8 or Android 4.4 or later.
Some experience
-
Testing can not only do functional testing, but also performance testing
-
Developers often use chrome, Firefox and other browser development tools for development. It is important to note that browser development tools can only simulate mobile UI and interaction, and their performance is much better than mobile environment.
-
During the development process, commonly used wechat, QQ, mobile phone browser for testing, which is not desirable, because the final environment is different, easy to give yourself the illusion that there is no problem in the wechat QQ Webview, it is OK
-
I really need a deadline. Many people believe that the H5 is flexible and doesn’t depend on the iOS release and can be tested on the same days as the iOS release. This was a huge mistake, as I’ll explain later.
Stage 3 – Full upgrade
After the downgrade, there are still many problems, and we are also working on the follow-up upgrade plan. After coordination, the system was cut back to the old version and temporarily replaced with native H5.
The problem
-
Insufficient amount of data has a great impact on operations
-
The experience of the degraded models is very poor, and statistics show that the affected models still have a certain share
-
Since H5 exists in and directory this time, it is designed to be resident in memory to ensure experience. The memory of UIWebview has not been released, and other pages in the system also use UIWebview, which will still crash if used for a long time.
-
It’s still a while before the next iOS and Android release, and it can’t be downgraded forever
No matter how you solve the performance problem, that’s the only goal!
After a week of boring and long efforts and experiments, the performance bottleneck was completely solved from the following aspects;
plan
1. Remove the iScroll
IScroll is a third-party component introduced in our internal framework. The official description is “Smooth scrolling for the Web”, but the performance is really worrying in the face of large data volume. If the amount of data is small, it is recommended.
2. High-performance DOM rendering
After comparing competing products, and tmall, JD and other well-known manufacturers H5 implementation, really depressed for a period of time, the same amount of data why others can do? Finally, two conclusions were drawn:
-
Others DOM nodes are not as complex as ours. Because we use the m-Fast framework developed internally, the top layer of the framework determines the complexity of THE DOM structure. For example, the framework presets the entire layout as up, down, left, right and middle, even though my page is just a streaming layout.
-
Others H5 page without picture rotation! Yes, you read that right, a picture rotation can have such a huge impact on performance
With these two points in mind, I began my DOM performance research
M-fast framework adopts template precompilation technology, which compiles the page template into JS files and loads them in the way of asynchronous loading. Therefore, the rendering of the web page roughly conforms to the above five steps
-
JavaScript. In general, we will use JavaScript to achieve some visual changes. Do an animation, sort a data set, or add DOM elements to a page using jQuery’s Animate function. Of course, in addition to JavaScript, there are other common ways to achieve visual changes, such as CSS Animations, Transitions, and the Web Animation API.
-
Computing style. The process is to match the corresponding CSS style for each DOM element based on a CSS selector, such as.headline or.nav >.nav_item. Once you’ve done this, you’ve determined what CSS style rules to apply to each DOM element.
-
Layout. The previous step determines the style rules for each DOM element by calculating the final size and position of each DOM element on the screen. The layout of elements on a Web page is relative, so a change in the layout of one element triggers a change in the layout of other elements. For example, a change in the width of an element affects the width of its children, and a change in the width of its children continues to affect its grandchildren. So for browsers, the layout process happens all the time.
-
To draw. Drawing is essentially the process of filling pixels. This includes drawing text, colors, images, borders, and shadows, which are all visual effects of a DOM element. Typically, this drawing process is done on multiple layers.
-
Render layer merge. As you can see from the previous step, the drawing of DOM elements in the page is done on multiple layers. Once the drawing process is complete on each layer, the browser merges all layers into one layer in a reasonable order and displays them on the screen. This process is especially important for pages with overlapping elements, because if the layers are merged in the wrong order, the elements will display incorrectly.
If you change the “paint only” properties of a DOM element, such as the background image, text color, or shadow, these properties do not affect the layout of the page, so the browser skips the layout process after calculating the style and just does the drawing and rendering layer merging.
If you modify a CSS property that is not styled and not drawn, the browser will skip the layout and drawing process after the style calculation and go straight to the render layer merge. This approach is optimal in terms of performance, and we strive to use this rendering process for heavy rendering like animation and scrolling.
Finally, the following improvements are made:
1. Simplify browser redraw
Drawing, is the process of filling pixels that will eventually appear on the user’s screen. This process is usually the most time-consuming part of the rendering pipeline, and therefore the one that needs to be avoided the most.
-
Any changes to CSS properties other than transform and opacity trigger drawing
-
If the layout is triggered, the next drawing must be triggered. Because changing an element’s geometry means that all of its pixels need to be rerendered!
-
Drawing can also be triggered if you change non-geometric attributes of an element, such as background, text color, or shadow effects, although changes to these attributes do not trigger layout.
2. Reduce the browser redraw area
Drawing is not always done in a single layer of memory. In effect, the browser will draw a frame into multiple layers when necessary, and then combine those layers into a single image for display on the screen.
The advantage of this method of drawing is that elements that use TranForms to move will be drawn normally without triggering the drawing of other elements.
The best way to create a new rendering layer on a page is to use the CSS property will-change, which is supported by Chrome/Opera/Firefox. When used with the transform property, a new composition layer is created:
.moving-element {
will-change: transform;
}Copy the code
For browsers that don’t currently support will-change but do support creating a rendering layer, such as Safari and Mobile Safari, you can use a 3D Transform property to force the browser to create a new rendering layer:
.moving-element {
transform: translateZ(0);
}Copy the code
One caveat: don’t create too many render layers. Because each new rendering layer created means new memory allocation and more complex layer management.
3. Avoid large, complex layouts
As mentioned above, due to the limitations of the framework, the page layout is much more complex than the requirements. Complex DOM structures should be avoided as much as possible in development, as they are more likely to cause large redraws.
4. Use render layers to merge attributes in preference
The merging of rendering layers is the merging of the parts of the page that have been drawn into one layer and then displayed on the screen.
Transforms and opacity properties are used to implement animation effects. Currently, only transforms and opacity properties do not trigger layout and rendering of the browser. Changes to these two properties of web elements directly trigger layer merging.
5. Optimize JavaScript execution efficiency
-
For animation effects, avoid using setTimeout or setInterval and use requestAnimationFrame instead.
-
Put the time-consuming JavaScript code into Web Workers.
Here you can use Chrome DevTools Timeline and JavaScript Profiler to analyze JavaScript performance.
Write in the last
Performance optimization is the art of subtraction. We first try to simplify the page rendering process and then try to make every step of the rendering process as efficient as possible.
THKS Google
CSS Triggers
render performance
simplify paint