How Critical Rendering Path (CRP) works internally?

How Critical Rendering Path (CRP) works internally?

The Critical Rendering Path (CRP) is a sequence of steps that the browser follows to render a web page. It’s crucial for optimizing page load times and improving user experience.


Here's a breakdown of how it works internally:

1. HTML Parsing: When the browser receives an HTML document, it starts parsing it. The HTML is converted into the Document Object Model (DOM), a tree structure that represents the content and structure of the web page.

2. CSS Parsing: Concurrently, the browser downloads and parses CSS files to construct the CSS Object Model (CSSOM). The CSSOM represents the styling rules applied to the elements in the DOM.

3. Render Tree Construction: The browser combines the DOM and CSSOM to build the Render Tree. This tree contains only the nodes required for rendering the page, including their styles. Nodes that are not visible or that are irrelevant for rendering (like <script> tags) are omitted.

4. Layout (Reflow): The browser computes the size and position of each element in the Render Tree. This process, known as layout or reflow, determines where each element should be placed on the screen based on its dimensions and the dimensions of its parent and sibling elements.

5. Painting: Once the layout is complete, the browser paints the pixels to the screen. This involves filling in the visual details of each element, such as colors, borders, and text. The browser typically uses a series of layers to manage this process efficiently.

6. Compositing: Finally, the browser combines the painted layers to produce the final visible page. This step can involve optimizing the rendering of complex pages with multiple layers and effects.


Optimization Techniques:

1. Network Requests: The browser requests resources like HTML, CSS, JavaScript, images, etc., in parallel. Efficiently managing these requests is crucial for minimizing load times.

2. Blocking Resources: Certain resources can block the rendering process. For example, CSS files are blocking, meaning the browser will not proceed to render until they are fully loaded and parsed. JavaScript can also be blocking if it modifies the DOM or CSSOM.

3. Render-Blocking Resources: These are resources that prevent the browser from proceeding to the next step in the rendering process. Common examples are external CSS files and JavaScript files that manipulate the DOM.

4. Optimization Strategies: To improve CRP performance, strategies such as minifying CSS and JavaScript, deferring non-essential JavaScript, using asynchronous loading for resources, and leveraging caching can be applied.

5. Critical CSS: Identifying and inlining critical CSS can help reduce render-blocking CSS. This technique involves extracting the essential CSS needed for initial rendering and embedding it directly in the HTML.


JavaScript and the Critical Rendering Path

In a typical JavaScript application, the critical rendering path might be influenced by:

1. Blocking JavaScript: JavaScript that blocks the parsing of HTML

2. Async and Deferred Scripts: Scripts that don't block HTML parsing but are executed differently

3. Dynamic DOM Manipulation: JavaScript that alters the DOM after the initial load


Example:

<!DOCTYPE html>
<html>
<head>
  <title>Example</title>
  <script src="main.js"></script>
  <link rel="stylesheet" href="styles.css">
</head>
<body>
  <h1>Hello World</h1>
  <div id="root"></div>
</body>
</html>        
// main.js
document.addEventListener('DOMContentLoaded', function() {
  const root = document.getElementById('root');
  root.innerHTML = '<p>Content added by JavaScript</p>';
});        

In this example:

1. The browser starts parsing HTML and encounters the <script src="main.js"></script> tag

2. HTML parsing is paused while main.js is fetched and executed

3. main.js adds content to the DOM after the initial HTML is parsed

To optimize, you could use the defer attribute:

<script src="main.js" defer></script>        

With defer, the script is fetched in parallel and executed after the HTML is fully parsed, minimizing blocking.


React and the Critical Rendering Path

React, a popular JavaScript library for building user interfaces, also follows the critical rendering path but adds its own layer of complexity.

1. Initial Rendering: React components are converted to a virtual DOM.

2. Reconciliation: React compares the virtual DOM with the real DOM and applies changes.

3. Rendering: Changes are rendered to the real DOM.


Example:

<!DOCTYPE html>
<html>
<head>
  <title>React Example</title>
  <script src="https://unpkg.com/react/umd/react.development.js"></script>
  <script src="https://unpkg.com/react-dom/umd/react-dom.development.js"></script>
  <script src="app.js" defer></script>
</head>
<body>
  <div id="root"></div>
</body>
</html>        
// app.js
const { useState } = React;

function App() {
  const [message, setMessage] = useState('Hello World');
  
  return (
    <div>
      <h1>{message}</h1>
      <button onClick={() => setMessage('Hello React')}>Change Message</button>
    </div>
  );
}

ReactDOM.render(<App />, document.getElementById('root'));        

In this example:

1. The browser parses the HTML and encounters the <script src="app.js" defer></script> tag

2. The app.js script is fetched and executed after the HTML is fully parsed due to defer

3. ReactDOM renders the App component, which updates the virtual DOM

4. React reconciles the virtual DOM with the real DOM and applies necessary changes


Internal Working of Critical Rendering Path in React

1. Virtual DOM Creation

When React components are rendered, React creates a virtual DOM, a lightweight representation of the actual DOM.

const { useState } = React;

function App() {
  const [message, setMessage] = useState('Hello World');
  
  return (
    <div>
      <h1>{message}</h1>
      <button onClick={() => setMessage('Hello React')}>Change Message</button>
    </div>
  );
}        

2. Reconciliation

React's reconciliation process involves comparing the new virtual DOM with the previous virtual DOM to determine the minimal number of changes required to update the real DOM. This process is efficient and minimizes expensive DOM manipulations.

3. Rendering

Once the changes are identified, React updates the real DOM. This involves updating only the parts of the DOM that have changed, making the update process fast and efficient.

Optimization Tips

Code Splitting: Split your code into smaller chunks to reduce the initial load time.

Lazy Loading: Load components only when they are needed.

Memoization: Use React.memo and useMemo to prevent unnecessary re-renders.

Defer Non-Critical JavaScript: Use defer and async attributes to prevent blocking HTML parsing

.

Let's focus on how the DOM (Document Object Model) is created from HTML, detailing the process in terms of characters, tokens, nodes, and the DOM tree.

1. HTML Parsing to Create the DOM

Characters to Tokens

When the browser receives the HTML file, it starts reading the HTML as a stream of characters.

For example, consider this HTML:

<!DOCTYPE html>
<html>
<head>
  <title>Example</title>
</head>
<body>
  <h1>Hello World</h1>
  <p>This is a paragraph.</p>
</body>
</html>        

The browser reads this HTML as a sequence of characters: <, !, D, O, C, T, Y, P, E, , h, t, m, l, >, etc.

The browser's HTML parser converts these characters into tokens. Tokens are the building blocks for elements.

Tokens:
- DOCTYPE
- Start tag: <html>
- Start tag: <head>
- Start tag: <title>
- Characters: Example
- End tag: </title>
- End tag: </head>
- Start tag: <body>
- Start tag: <h1>
- Characters: Hello World
- End tag: </h1>
- Start tag: <p>
- Characters: This is a paragraph.
- End tag: </p>
- End tag: </body>
- End tag: </html>
Tokens:
- DOCTYPE
- Start tag: <html>
- Start tag: <head>
- Start tag: <title>
- Characters: Example
- End tag: </title>
- End tag: </head>
- Start tag: <body>
- Start tag: <h1>
- Characters: Hello World
- End tag: </h1>
- Start tag: <p>
- Characters: This is a paragraph.
- End tag: </p>
- End tag: </body>
- End tag: </html>        

Tokens to Nodes

Next, the tokens are converted into nodes. Nodes are objects representing elements, text, and other components in the document.

Nodes:
- Document node (root)
  - Element node: <html>
    - Element node: <head>
      - Element node: <title>
        - Text node: "Example"
    - Element node: <body>
      - Element node: <h1>
        - Text node: "Hello World"
      - Element node: <p>
        - Text node: "This is a paragraph."        

Creating the DOM Tree

These nodes are then organized into a tree structure called the DOM tree. The DOM tree represents the structure of the document.

DOM Tree:
Document
 └── html
     ├── head
     │   └── title
     │       └── Example
     └── body
         ├── h1
         │   └── Hello World
         └── p
             └── This is a paragraph.        

2. CSS Parsing to Create the CSSOM

In parallel with the DOM construction, the browser parses the CSS.

body {
  font-family: Arial, sans-serif;
}
h1 {
  color: blue;
}
p {
  color: green;
}        

The browser creates the CSSOM (CSS Object Model), a tree structure representing the styles.

CSSOM Tree:
StyleSheet
 ├── body
 │    └── font-family: Arial, sans-serif
 ├── h1
 │    └── color: blue
 └── p
      └── color: green        

3. Combining DOM and CSSOM to Create the Render Tree

The browser combines the DOM and CSSOM to create the render tree. The render tree contains only the visible elements on the page and their computed styles.

Render Tree:
RenderRoot
 ├── RenderBody (font-family: Arial, sans-serif)
 │    ├── RenderH1 (color: blue)
 │    │    └── Hello World
 │    └── RenderP (color: green)
 │         └── This is a paragraph.        

4. Layout Calculation

The browser calculates the layout, determining the exact position and size of each element.

Layout:
 ├── RenderBody (0,0) [width: 800px, height: 600px]
 │    ├── RenderH1 (0,0) [width: 800px, height: 50px]
 │    └── RenderP (0,60) [width: 800px, height: 20px]        

5. Painting the Pixels on the Screen

Finally, the browser paints the pixels on the screen, rendering the visual representation of the web page.

6. Compositing

Compositing is the process of combining the various painted layers into the final image that is displayed on the screen. Modern browsers often use multiple layers to render complex web pages efficiently. These layers are composited together to create the final visual output.

Example in JavaScript and React

<!DOCTYPE html>
<html>
<head>
  <title>React Example</title>
  <script src="https://unpkg.com/react/umd/react.development.js"></script>
  <script src="https://unpkg.com/react-dom/umd/react-dom.development.js"></script>
  <script src="app.js" defer></script>
</head>
<body>
  <div id="root"></div>
</body>
</html>        
// app.js
const { useState } = React;

function App() {
  const [message, setMessage] = useState('Hello World');
  
  return (
    <div>
      <h1>{message}</h1>
      <button onClick={() => setMessage('Hello React')}>Change Message</button>
    </div>
  );
}

ReactDOM.render(<App />, document.getElementById('root'));        

React and the Critical Rendering Path

JavaScript Execution: The browser fetches and executes app.js after the HTML is parsed (due to defer).

React Component Rendering: React components are converted into a virtual DOM.

Reconciliation: React compares the virtual DOM with the real DOM and updates the real DOM.

Rendering: The updated DOM is rendered, and changes are painted on the screen.

Compositing: The final step involves compositing the various layers to display the final visual representation on the screen.


Internal Steps in React

Characters to Tokens and Nodes: The initial HTML is parsed as described earlier.

Virtual DOM Creation: React creates a virtual DOM representation of the App component.

Reconciliation: React's diffing algorithm determines the minimal changes required.

Real DOM Update: The real DOM is updated with the changes, and the browser re-renders the updated elements.

Compositing: The browser composites the layers to create the final image displayed to the user.


Note:

As the css load time increases, the browser will take longer to load the CSS, causing script.js to be invoked only after the CSS has been fully loaded.

Using the Performance tab in the Inspector window, we can examine the lifecycle methods of the Critical Rendering Path (CRP). By recording the loading functionality and pressing the stop button, we can analyze the performance data.

要查看或添加评论,请登录

?? Sai Ashish的更多文章

社区洞察

其他会员也浏览了