前端长列表渲染优化_用于前端开发的浏览器渲染优化

前端长列表渲染优化

介绍 ( Introduction )

We live in an age where the importance of delivering web services at optimal speed can't be overemphasized. As the payload transmitted by web applications increase, developers must adopt best practices to ensure that data packets are delivered almost instantaneously, hence providing users with an overall exemplary experience.

我们生活在一个时代,以最佳速度交付Web服务的重要性不可过分强调。 随着Web应用程序传输的有效负载的增加,开发人员必须采用最佳实践以确保几乎立即发送数据包,从而为用户提供了总体的体验。

Some of the widely adopted best practices in web development today are image compression, code minification, code bundling (with tools such as Webpack) etc. These practices already have the effect of improving user satisfaction, but it is possible to achieve more when the developer understands the underlying steps that guide the rendering of web applications to the DOM.

当今Web开发中广泛采用的一些最佳实践包括图像压缩,代码压缩,代码捆绑(使用Webpack等工具)等。这些实践已经具有提高用户满意度的效果,但是当开发人员使用时可以实现更多了解指导将Web应用程序呈现到DOM的基本步骤。

When playing a GPU intensive game on a low-end computing device, we may experience some juddering — shaking or vibrating — of the game characters and environment. This behaviour (though not as obvious) is also possible in web applications; users may notice when the application stops for a second or two and delays in responding to an interactive activity such as a click or scroll.

在低端计算设备上玩GPU密集型游戏时,我们可能会感觉到游戏角色和环境的某些抖动(抖动或振动)。 在Web应用程序中,这种行为(尽管不那么明显)也是可能的。 用户可能会注意到应用程序何时停止一两秒钟,并且在响应诸如单击或滚动之类的交互式活动时出现延迟。

In this article, we will discuss the conditions that can enable (and prevent) a web application to run (optimally) at 60 frames per second.

在本文中,我们将讨论可以使(并阻止)Web应用程序以每秒60帧(最佳)运行的条件。

框架是什么? ( What goes into a frame? )

Whenever there’s a visual change in a web application, what happens under the hood is: the browser puts up a new frame for the user to see and interact with. The rate at which these frames appear (and are updated) is measured in frames per second (fps). If the browser takes too long to create and render a frame, the fps drops and the user may notice the juddering of the application.

每当Web应用程序发生视觉变化时,其幕后工作就是:浏览器为用户提供一个新的框架,供用户查看和交互。 这些帧出现(和更新)的速率以每秒帧数(fps)为单位。 如果浏览器花费太长时间来创建和渲染帧,则fps会下降,并且用户可能会注意到应用程序的抖动。

In order to create web applications with high performance that run at 60 frames per second, the developer needs to understand the contents of a frame. Here’s a breakdown (in 5 steps) of how a frame is created:

为了创建以每秒60帧的速度运行的高性能Web应用程序,开发人员需要了解一帧的内容。 以下是创建框架的方式(分为5个步骤):

  1. The browser makes a GET request to a remote server.

    浏览器向远程服务器发出GET请求。
  2. The server responds with some HTML and CSS.

    服务器以一些HTML和CSS响应。
  3. The HTML is parsed into the DOM.

    HTML被解析为DOM。
  4. The CSS is parsed into a CSS object model (CSSOM) and integrated with the DOM to create a new tree called the Render tree.

    CSS被解析为CSS对象模型(CSSOM),并与DOM集成在一起以创建一个称为“渲染树”的新树。
  5. The Render tree essentially consists of the elements that are displayed on the page and make up a frame.

    渲染树本质上由页面上显示并组成框架的元素组成。

Note: step 4 is shown in Chrome dev tools as Recalculate Styles

注意:第4步在Chrome 开发者工具中显示为“重新计算样式”

应用生命周期 ( App Lifecycle )

Before we go on to explore the browser’s rendering path and the optimizations that can be plugged into it, we need to learn about the app lifecycle as it would enable us to make smart choices in determining when an application should do the “heavy work,” hence creating smooth user experience and augmenting user satisfaction.

在继续探索浏览器的渲染路径以及可以插入其中的优化之前,我们需要了解应用程序的生命周期,因为它可以使我们在确定应用程序何时应执行“繁重的工作”时做出明智的选择,从而创造流畅的用户体验并提高用户满意度。

The app lifecycle is split into four stages:

应用程序生命周期分为四个阶段:

  1. Load

    加载
  2. Idle

  3. Animation

    动画
  4. Response

    响应

加载 (Load)

Before a user can interact with a web application, it has to be loaded first. This is the first stage in the app lifecycle and it is important to aim at reducing (ideally at 1s) the load time to the smallest number possible.

在用户可以与Web应用程序交互之前,必须先加载它。 这是应用程序生命周期的第一阶段,重要的是将加载时间(最好是1s)减少到最小。

(Idle)

After an application is loaded, it usually becomes idle; waiting on the user to interact with it. The idle block is usually around 50ms long and provides the developer with the opportunity to do the heavy lifting, such as the loading the assets (images, videos, comments section) that a user might access later.

加载应用程序后,它通常变得空闲; 等待用户与其互动。 空闲块通常长约50ms,为开发人员提供了进行繁重工作的机会,例如加载用户以后可以访问的资产(图像,视频,评论部分)。

ProTip: A hack to significantly reduce load time is to load only the basics of the UI first and pull in other elements at the Idle stage.

ProTip:要显着减少加载时间的一种技巧是仅首先加载UI的基础知识,然后在Idle阶段引入其他元素。

动画化 (Animate)

When the user starts interacting with the application and the Idle stage is over, the application has to react properly to user interaction (and input) without any visible delay.

当用户开始与应用程序交互并且闲置阶段结束时,应用程序必须对用户交互(和输入)做出正确React,而没有任何可见的延迟。

Note: Studies have shown that it takes about a tenth of a second (after interacting with a UI element) to notice any lag. Therefore responding to user input within this time range is perfect.

注意:研究表明,大约需要十分之一秒的时间(与UI元素进行交互之后)才能注意到任何延迟。 因此,在此时间范围内响应用户输入是完美的。

A challenge might be posed when the response to user interaction involves animation of some sort. In order to render animations that execute at 60 frames per second, each frame would have a limit of 16ms — this is basically a second divided by 60.

当对用户交互的响应涉及某种形式的动画时,可能会构成挑战。 为了渲染以每秒60帧的速度执行的动画,每帧限制为16毫秒-这基本上是一秒除以60。

In reality, this should be about 10ms - 12ms due to the browser overhead. A way of achieving this would be to perform all animation calculations upfront (during the 100ms after a UI element has been interacted with).

实际上,由于浏览器开销,这应该约为10ms-12ms。 实现此目的的一种方法是预先执行所有动画计算(在与UI元素进行交互之后的100毫秒内)。

浏览器的渲染路径和各种优化 ( The Browser’s Rendering Path and Various Optimizations )

The Browser's rendering path takes the following route:

浏览器的渲染路径采用以下路径:

  • JavaScript

    JavaScript

  • Style calculation

    风格计算

  • Layout creation

    布局创建

  • Painting of screen pixels

    屏幕像素的绘制

  • Layer composition

    层组成

On a web page, when a visual change is made (either by CSS or JavaScript), the browser recalculates the styles of the affected elements. If there are changes to an element’s geometry, the browser checks the other elements, creates a new layout, repaints the affected elements and re-composites these elements together.

在网页上,当进行视觉更改(通过CSS或JavaScript)时,浏览器将重新计算受影响元素的样式。 如果元素的几何形状发生变化,则浏览器将检查其他元素,创建新的布局,重新绘制受影响的元素并将这些元素重新组合在一起。

However, changing certain properties of a page’s elements could change the rendering path of a web page. For instance, If a paint-only property, such as background image or text colour, is changed, the layout is not affected because no changes were made to the element’s geometry. Other property changes could leave layout generation and paint out of the rendering pipeline.

但是,更改页面元素的某些属性可能会更改网页的呈现路径。 例如,如果更改了仅绘制属性(例如背景图像或文本颜色),则布局不会受到影响,因为未对元素的几何形状进行任何更改。 其他属性更改可能会使布局生成和绘制脱离渲染管道。

We will expore some optimizations that can be plugged into the browser’s rendering path next.

我们将研究一些优化,然后可以将其插入浏览器的渲染路径。

JavaScript (JavaScript)

JavaScript allows developers to provide users with awesome animations and visual experiences and is therefore heavily used in web applications. From our discussion on the app lifecycle, we see that the browser has about 10ms - 12ms to render each frame. To ease the burden of JavaScript on the rendering pipeline, it is important to execute all JavaScript code as early as possible in every frame since it could trigger other areas of the rendering pipeline.

JavaScript使开发人员能够为用户提供很棒的动画和视觉体验,因此在Web应用程序中得到大量使用。 从对应用程序生命周期的讨论中,我们可以看到浏览器大约需要10ms-12ms的时间渲染每一帧。 为了减轻JavaScript在呈现管线上的负担,在每个帧中尽早执行所有JavaScript代码非常重要,因为它可能会触发呈现管线的其他区域。

It is possible to achieve this using the window.requesAnimationFrame() method, according to the MDN web docs:

根据MDN网络文档 ,可以使用window.requesAnimationFrame()方法实现此目的:

“The window.requestAnimationFrame() method tells the browser that you wish to perform an animation and requests that the browser calls a specified function to update an animation before the next repaint. The method takes a callback as an argument to be invoked before the repaint.”

window.requestAnimationFrame()方法告诉浏览器您希望执行动画,并请求浏览器在下一次重绘之前调用指定的函数来更新动画。 该方法将回调作为要在重绘之前调用的参数。”

The requestAnimationFrame() API enables the browser to bring in JavaScript at the right time and prevent itself from missing a frame. Here’s an example of the method in use:

requestAnimationFrame() API使浏览器可以在正确的时间引入JavaScript,并防止自身丢失框架。 这是使用方法的示例:

function doAnimation() {
    // Some code wizardry
    requestAnimationFrame(doAnimation); //schedule the next frame

}

requestAnimationFrame(doAnimation);

The performance tab in the Chrome dev tools allows developers to record a page while in use and displays an interface that shows how JavaScript performs in the web application.

Chrome开发人员工具中的“ 性能”标签可让开发人员在使用过程中记录页面,并显示一个界面,该界面显示JavaScript在Web应用程序中的执行情况。

While requestAnimationFrame is a very important tool, some JavaScript code could be really resource intensive. Websites run on the main thread of our operating systems hence these scripts could stall the execution of other stages of the rendering pipeline. To solve this problem, we can use web workers.

虽然requestAnimationFrame是一个非常重要的工具,但某些JavaScript代码可能确实占用大量资源。 网站运行在我们操作系统的主线程上,因此这些脚本可能会使渲染管线其他阶段的执行停滞。 为了解决这个问题,我们可以使用网络工作者。

Web workers allow us to spawn new threads for resource-intensive JavaScript code according to the MDN web docs:

网络工作者允许我们根据MDN网络文档为资源密集型JavaScript代码生成新线程:

“Web Workers is a simple means for web content to run scripts in background threads. The worker thread can perform tasks without interfering with the user interface. Once created, a worker can send messages to the JavaScript code that created it by posting messages to an event handler specified by that code (and vice versa).”

“ Web Workers是Web内容在后台线程中运行脚本的一种简单方法。 工作线程可以执行任务,而不会干扰用户界面。 创建后,工作人员可以通过将消息发布到该代码指定的事件处理程序中来向创建该代码JavaScript代码发送消息(反之亦然)。

前端长列表渲染优化_用于前端开发的浏览器渲染优化_第1张图片

To use this feature, you’ll need to create a separate JavaScript file which your main app will spawn into a web worker.

要使用此功能,您需要创建一个单独JavaScript文件,您的主应用程序将该文件生成为网络工作者。

风格计算 (Style Calculation)

Style changes are a key part of any web application’s rendering pipeline as the number of style changes required by its elements is directly proportional to the performance cost of style recalculation. Check out Paul’s website for a pretty decent breakdown of how CSS styles affect the rendering pipeline and therefore performance.

样式更改是任何Web应用程序呈现管道中的关键部分,因为其元素所需的样式更改次数与样式重新计算的性能成本成正比。 在Paul的网站上查看有关CSS样式如何影响渲染管道以及性能的相当不错的细分。

In addition to the number of style changes, selector matching should be factored into our list of rendering optimizations. Selector matching refers to the process of determining which styles should be applied to any given DOM element(s).

除了样式更改的数量外,选择器匹配还应纳入我们的渲染优化列表中。 选择器匹配是指确定应将哪些样式应用于任何给定DOM元素的过程。

Certain styles may take more time to be processed than others and this becomes important as the number of elements affected by one or more style changes increases. A suitable approach to solve this issue is the Block Element Modifier (BEM) methodology. It provides great benefits for performance as class matching, which follows the BEM methodology, is the fastest selector to match for modern browsers.

某些样式可能比其他样式花费更多时间,并且随着受一个或多个样式更改影响的元素数量增加,这一点变得很重要。 解决此问题的合适方法是块元素修改器(BEM)方法 。 遵循BEM方法的类匹配是现代浏览器最快的选择器,它为性能提供了极大的好处。

版面制作 (Layout Creation)

A major performance bottleneck is layout thrashing. This occurs when requests for geometric values interleaved with style changes are made in JavaScript and causes the browser to reflow the layout. This, when done severally in quick successions, leads to a forced synchronous layout. In this article, Googler, Paul Lewis, highlights the various optimizations that can be done to prevent forced synchronous layouts.

一个主要的性能瓶颈是布局混乱。 当在JavaScript中请求与样式更改交织在一起的几何值时,就会发生这种情况,并导致浏览器重排布局。 当快速连续进行多次操作时,将导致强制同步布局。 Googler Paul Lewis在本文中重点介绍了可以进行的各种优化,以防止强制同步布局。

屏幕像素画 (Painting of Screen Pixels)

Painting occurs when the browser starts filling in screen pixels. This involves drawing out all visual elements on the screen. This is done on multiple surfaces, called layers. Paint could cause performance problems when it is required by large portions of the page, especially at intervals, as seen during page scrolling.

当浏览器开始填充屏幕像素时,就会进行绘制。 这涉及绘制屏幕上的所有视觉元素。 这是在称为层的多个表面上完成的。 当页面的很大一部分需要绘画时,尤其是在一定间隔时,绘画可能会导致性能问题,如在页面滚动期间看到的那样。

前端长列表渲染优化_用于前端开发的浏览器渲染优化_第2张图片

The paint profiler, as shown above, makes it easy to identify what areas of the page are being painted and when they’re being painted. The paint profiler can be found by pressing the escape key after navigating to Chrome dev tools and selecting the Rendering tab.

如上所示,绘画轮廓分析器使您可以轻松识别要绘画页面的哪些区域以及何时绘画。 导航到Chrome开发者工具并选择“渲染”选项卡后,按退出键可以找到油漆分析器。

The first checkbox, Paint flashing, highlights in green what areas of the page are currently painted and the frequency of this could tell us if painting contributes to the performance issues on the rendering pipeline.

第一个复选框,“ Paint flashing”(绘画闪烁)以绿色突出显示当前正在绘画页面的哪些区域,这种频率可以告诉我们绘画是否会导致渲染管道中的性能问题。

Looking at the image above, we can see that only the scroll bar is painted as the page is scrolled, which indicates great browser paint optimizations on the homepage of the Scotch.io website .

查看上图,可以看到在滚动页面时仅绘制了滚动条,这表明Scotch.io网站the的主页上进行了很棒的浏览器绘制优化。

层组成 (Layer Composition)

This is the final path in the browser rendering pipeline and it involves an important browser structure — Layers. The browser engine does some layer management by first considering the styles and elements and how they are ordered, then tries to figure out what layers are needed for the page and updates the layer tree accordingly.

这是浏览器呈现管道中的最终路径,它涉及重要的浏览器结构-图层。 浏览器引擎通过首先考虑样式和元素以及它们的排序方式来进行一些层管理,然后尝试找出页面需要哪些层并相应地更新层树。

Next, the browser composites these layers and displays them on the screen. Performance bottlenecks due to painting occur when the browser has to paint page elements that overlap one another and also exist in the same layer as one another.

接下来,浏览器将这些图层合成并显示在屏幕上。 当浏览器必须绘制彼此重叠并且也存在于同一层中的页面元素时,就会出现由于绘制而导致的性能瓶颈。

To solve this problem, the elements involved will have to exist in separate layers. This can be achieved with the will-change CSS property and setting its attribute to transform :

为了解决这个问题,所涉及的元素将必须存在于单独的层中。 这可以通过will-change CSS属性并将其属性设置为transform

 {
    will-change: transform;
}

It should, however, be noted that an increase in layers would mean an increase in the time spent on layer management and compositing. With Chrome dev tools, it is possible to see all the layers on a page as shown below:

但是,应该注意的是,层数的增加将意味着花在层管理和合成上的时间增加。 借助Chrome开发者工具,可以查看页面上的所有图层,如下所示:

前端长列表渲染优化_用于前端开发的浏览器渲染优化_第3张图片

To get to the Layers tab, click on the hamburger menu button (three vertical dots) in Chrome dev tools, navigate to more tools, and select Layers.

要进入“图层”标签,请在Chrome开发者工具中点击汉堡菜单按钮(三个垂直点),导航至更多工具,然后选择“图层”。

结论 ( Conclusion )

We have taken a brief tour of the browser’s rendering pipeline, the app lifecycle and the various optimizations that can be plugged into the rendering pipeline during the animate lifecycle of a web application.

我们简要浏览了浏览器的渲染管道,应用程序生命周期以及可以在Web应用程序的动画生命周期中插入渲染管道的各种优化。

When these optimizations are implemented logically, the result is a great user experience and some inner satisfaction for the frontend developer. If reading this article has piqued your interest, you can learn more about browser rendering optimizations from this course.

当这些优化以逻辑方式实现时,结果是出色的用户体验和前端开发人员的内在满足感。 如果阅读本文引起了您的兴趣,您可以从本课程中了解有关浏览器渲染优化的更多信息。

There is a sequel to this article that focuses on using Chrome Dev Tools to find Performance bottlenecks. You can read about it here.

本文的续篇重点介绍如何使用Chrome开发工具来查找性能瓶颈。 您可以在这里阅读。

翻译自: https://scotch.io/tutorials/browser-rendering-optimizations-for-frontend-development

前端长列表渲染优化

你可能感兴趣的:(python,javascript,java,css,html,ViewUI)