Processes and threads

  • A process is the basic unit of resource allocation in an operating system and contains threads.
  • Threads are managed by processes. In order to improve the stability and security of the browser, the browser adopts the multi-process model.

(5) processes in the browser

  • Browser process: responsible for interface display, user interaction, sub-process management, storage, etc.

  • Render process: Each card also has a separate render process, with the core used to render the page.

  • Network process: mainly handle the loading of network resources (HTML, CSS, JS, etc.)

  • GPU process: 3D drawing, improve performance

  • Plugin processes: Plugins installed in Chrome

What happens between entering the URL and the browser displaying the page?

Did the user enter a keyword or a URL? If it is a keyword, the default search engine is used to produce the URL

1. Browser processes call each other

  • Enter the URL address in the browser process to start the navigation. And prepare the rendering process
  • The request is sent in the network process and the response is sent to the renderer for processing
  • Parse the page and load the required resources in the page
  • After rendering, show the result

We started to refine each step of the process and extract points from the process that we could optimize.

2.URL request process

  • The browser looks up whether the current URL is cached, and returns it directly from the cache if it is, and the cache has not expired.

  • Check whether the domain name has been resolved. If no, perform DNS resolution. Resolve the domain name to an IP address and add a port number

  • If the request is HTTPS, SSL negotiation is performed

  • Address using IP address, request queuing. A domain name cannot contain more than six requests.

  • Server creates TCP connection after queuing (three-way handshake)

  • TCP protocol is used to divide large files into packets for transmission (orderly transmission), and reliable transmission to the server (packet loss and retransmission). After receiving the packets, the server rearranges the packets according to the serial number (adding TCP header and IP header).

  • Sending an HTTP request (request line, request header, request body)

  • The KEEP-alive attribute is supported in HTTP 1.1. The TCP connection is not closed immediately and the time for establishing a connection is saved for subsequent requests.

  • Server response result (response row, response header, response body)

  • If the status code is 301 or 302, the browser redirects the browser. (Re-navigate)

  • If 304 is returned, the cache is searched. (Server can set mandatory cache)

  • Observe the flow of the request through Network Timing:

  • Queuing: Before sending requests, a maximum of six TCP links are processed for each domain name. If the number of TCP links exceeds the Queuing value, disk space allocation takes a certain time.

  • 例 句 : Time to wait before a request is issued (processing agents, link reuse)

  • DNS lookup: Lookup DNS time

  • Initial Connection: indicates the time when the TCP Connection is established

  • SSL: SSL handshake time (SSL negotiation)

  • Request Sent: Time when the Request is Sent (negligible)

  • Waiting(TTFB) : time to wait for a response, to return the first character

  • Content Dowloaded: The response time for downloading

Blue: DOMContentLoaded: the time when the DOM build is complete

Red: Load: All browser resources are loaded

Essentially, a browser is software that allows the average Internet user to parse and send the HTTP protocol through an interface

3.HTTP development history

  • HTTP/0.9 has no request header and request body in the transmission process. The server does not return header information in response, and the content adopts ASCII character stream to transmit HTML

  • HTTP/1.0 added request headers and response headers to achieve multiple types of data transfer

  • HTTP/1.1 enables persistent links by default. Multiple HTTP requests can be transmitted on a TCP link. The pipeline method is adopted (each domain name maintains a maximum of six TCP persistent links) to prevent queue congestion (the server processes requests in sequence). It perfectly supports chunk transfer of data, and introduces client cookie mechanism and security mechanism.

  • HTTP/2.0 addresses low network bandwidth usage (TCP slow start, multiple TCP competing for bandwidth, queue blocking) by using multiplexing mechanisms (one domain name uses one TCP long link, implemented through the binary framing layer). Header compression (HPACK), and server push

  • HTTP/3.0 to solve the problem of TCP queue header blocking, using QUIC protocol. The QUIC protocol is based on UDP (for now: support and deployment is the biggest issue)

  • HTTP plaintext transmission. During transmission, data may be stolen or tampered with by routers and carriers.

Compare HTTP/1.1 with HTTP/2

4. Rendering process

  • 1. The browser cannot use HTML directly. It needs to convert HTML into a DOM tree. (document)
  • 2. Browsers cannot parse plain text CSS styles. Instead, parse CSS styles into styleSheets. CSSOM (document. StyleSeets)
  • 3. Calculate the specific style of each node in DOM tree (Attachment)
  • 4. Create a render (layout) tree and add visible nodes from the DOM tree to the layout tree. And compute the coordinate position of the node rendering to the page. (layout)
  • 5. Through the layout tree, layer the tree (according to the positioning property, transparent property, transform property, clip property, etc.)
  • 6. Draw different layers and transfer them to the composition thread. Final production of the page and Display to the browser (Painting,Display)

View the list of layers and draw them

Simulate the request -> render process

Request message format

  • Start line: [method][space][request URL][HTTP version][newline]
  • Header: [header name][:][space][header content][newline]
  • End of header: [newline]
  • entity

Response message format

  • Start line: [HTTP version][space][status code][space][reason phrase][newline]
  • Header: [header name][:][space][header content][newline]
  • End of header: [newline]
  • entity

1. Send HTTP requests based on TCP

const net = require('net')
class HTTPRequest {
    constructor(options) {
        this.method = options.method || 'GET';
        this.host = options.host || '127.0.0.1';
        this.port = options.port || 80;
        this.path = options.path || '/';
        this.headers = options.headers || {}
    }
    send(body) {
        return new Promise((resolve, reject) = > {
            body = Object.keys(body).map(key= > (`${key}=The ${encodeURIComponent(body[key])}`)).join('&');
            if (body) {
                this.headers['Content-Length'] = body.length;
            };

            const socket = net.createConnection({
                host:this.host,
                port:this.port
            },() = >{
                const rows = [];
                rows.push(`The ${this.method} The ${this.path}HTTP / 1.1 `);
                Object.keys(this.headers).forEach(key= >{
                    rows.push(`${key}: The ${this.headers[key]}`);
                });
                let request = rows.join('\r\n') + '\r\n\r\n' + body;
                socket.write(request)
            });

            socket.on('data'.function(data){
                // data is the result returned after the request is sent}}})})async function request() {
    const request = new HTTPRequest({
        method: 'POST'.host: '127.0.0.1'.port: 3000.path: '/'.headers: {
            name: 'zhufeng'.age: 11}});let { responseLine, headers, body } = await request.send({ address: 'Beijing' });
}

request();
Copy the code

2. Parse the response results

const parser = new HTTPParser()
socket.on('data'.function(data){
    // data is the result returned after the request is sent
    parser.parse(data);
    if(parser.result){
        resolve(parser.result)
    }
});
Copy the code

3. Parse HTML

let stack = [{ type: 'document'.children: []}];const parser = new htmlparser2.Parser({
    onopentag(name, attributes) {
        let parent = stack[stack.length - 1];
        let element = {
            tagName: name,
            type: 'element'.children: [],
            attributes,
            parent
        }
        parent.children.push(element);
        element.parent = parent;
        stack.push(element);
    },
    ontext(text) {
        let parent = stack[stack.length - 1];
        let textNode = {
            type: 'text',
            text
        }
        parent.children.push(textNode)
    },
    onclosetag(tagname){ stack.pop(); }}); parser.end(body)Copy the code

4. Parse the CSS

const cssRules = [];
const css = require('css');
function parserCss(text) {
    constast = css.parse(text); cssRules.push(... ast.stylesheet.rules); }const parser = new htmlparser2.Parser({
    onclosetag(tagname) {
        let parent = stack[stack.length - 1];
        if (tagname == 'style') {
            parserCss(parent.children[0].text); } stack.pop(); }});Copy the code

5. Calculation style

function computedCss(element) {
    let attrs = element.attributes; // Get element attributes
    element.computedStyle = {}; // Compute style
    Object.entries(attrs).forEach(([key, value]) = > {
        cssRules.forEach(rule= > {
            let selector = rule.selectors[0];
            if ((selector == The '#'+value && key == 'id') || (selector == '. '+value && key == 'class')) {
                rule.declarations.forEach(({ property, value }) = >{ element.computedStyle[property] = value; })}})}); }Copy the code

6. Layout drawing

function layout(element) {
    // Calculate the position -> draw
    if (Object.keys(element.computedStyle).length ! =0) {
        let { background, width, height, top, left } = element.computedStyle
        let code = `
            let canvas = document.getElementById('canvas');
            canvas.width = window.innerWidth;
            canvas.height = window.innerHeight ;
            let context = canvas.getContext("2d")
            context.fillStyle = "${background}";
            context.fillRect(${top}.${left}.The ${parseInt(width)}.The ${parseInt(height)});
            `
        fs.writeFileSync('./code.js', code); }}Copy the code

Summary: How is the DOM generated

  • If the server returns text/ HTML, the browser will parse the data through HTMLParser (parsing while downloading).

  • Before parsing, the system preloads JS and CSS files

  • Byte streams -> word dividers -> Tokens -> generate nodes based on Tokens -> insert into the DOM tree

  • Encountering JS: If a script tag is encountered during parsing, HTMLParser stops parsing and executes the corresponding script (download).

  • Wait for all CSS loads on the current script to be parsed before executing js.

  • The CSS style file should be placed at the head of the page as far as possible. CSS loading will not block DOM Tree parsing, and the browser will use the DOM Tree and CSSOM to render, without flickering problems. If the CSS is placed at the bottom, browsing will render as it is parsed, and the rendered result will not contain the style and will be redrawn later.
  • The JS file is placed at the bottom of the HTML to prevent JS loading, parsing, and execution from blocking the normal rendering of the page later

Monitor the rendering process through the PerformanceAPI

4. Perfomance API

Critical time node describe meaning
TTFB Time to first byte The elapsed time between the request and the return of the first byte of data
TTI Time to Interactive When the DOM tree is built, events can be bound
DCL DOMContentLoaded (Event time) When the HTML document is fully loaded and parsed, the DOMContentLoaded event is fired
L OnLoad (Event time) This alarm is triggered when all dependent resources are loaded
FP First Paint The time when the first pixel is drawn to the screen
FCP First Contentful Paint The first time to draw any text, images, non-blank nodes
FMP First Meaningful paint The first meaningful drawing is a measure of page usability
LCP Largest Contentful Paint The maximum page element loading time in viewPort
FID First Input Delay The time between the user’s first interaction with the page (clicking a link, clicking a button, etc.) and the page’s response to the interaction

<div style="background:red; height:100px; width:100px"></div>
<h1 elementtiming="meaningful">meaningful text</h1>
<script>
    window.onload = function () {
        let ele = document.createElement('h1');
        ele.innerHTML = 'zf';
        document.body.appendChild(ele)
    }
    setTimeout(() = > {
        const {
            fetchStart,
            requestStart,
            responseStart,
            domInteractive,
            domContentLoadedEventEnd,
            loadEventStart
        } = performance.timing;


        let TTFB = responseStart - requestStart; // ttfb
        let TTI = domInteractive - fetchStart; // tti
        let DCL = domContentLoadedEventEnd - fetchStart // dcl
        let L = loadEventStart - fetchStart;
        console.log(TTFB, TTI, DCL, L)

        const paint = performance.getEntriesByType('paint');
        const FP = paint[0].startTime;
        const FCP = paint[1].startTime; // 2s~4s
    }, 2000);

    let FMP;
    new PerformanceObserver((entryList, observer) = > {
        let entries = entryList.getEntries();
        FMP = entries[0];
        observer.disconnect();
        console.log(FMP)
    }).observe({ entryTypes: ['element']});let LCP;
    new PerformanceObserver((entryList, observer) = > {
        let entries = entryList.getEntries();
        LCP = entries[entries.length - 1];
        observer.disconnect();
        console.log(LCP); / / 2.5 s - 4 s
    }).observe({ entryTypes: ['largest-contentful-paint']});let FID;
    new PerformanceObserver((entryList, observer) = > {
        let firstInput = entryList.getEntries()[0];
        if (firstInput) {
            FID = firstInput.processingStart - firstInput.startTime;
            observer.disconnect();
            console.log(FID)
        }
    }).observe({ type: 'first-input'.buffered: true });
</script>
Copy the code

Five. Network optimization strategy

  • Reduce the number of HTTP requests, merge JS and CSS, and reasonably embed CSS and JS

  • Reasonably set server cache to improve server processing speed. (Mandatory cache, comparison cache)

// Expires/Cache-Control   Etag/if-none-match/last-modified/if-modified-since
Copy the code
  • Avoid redirection, redirection slows response time (301,302)

  • Use dns-prefetch to perform DNS prefetch

  • Domain name sharding is used to store resources under different domain names. A maximum of six TCP connections can be processed in the same domain name.

  • CDN acceleration is used to speed up access. (Assign nearest, highly available)

  • Gzip compression optimization for volume compression of transmitted resources (HTML, JS, CSS)

// Content-Encoding: gzip
Copy the code
  • Load data priority: preload (prerequest resources needed for the current page) Prefetch (resources to be used in the future page) caches data into the HTTP cache
<link rel="preload" href="style.css" as="style">
Copy the code

Key render paths

  • Reflow: Add elements, delete elements, modify the size, move the location of an element, and obtain location information

  • Repaint: Changes in the style of an element on a page do not affect its position in the document flow.

Redraw and backflow should be minimized

1. Forcibly synchronize the layout

JavaScript forces computing style and layout operations to be brought forward to the current task

<div id="app"></div>
<script>
    function reflow() {
        let el = document.getElementById('app');
        let node = document.createElement('h1');
        node.innerHTML = 'hello';
        el.appendChild(node);
        // Force layout synchronization
        console.log(app.offsetHeight);
    }
    requestAnimationFrame(reflow)
</script>
Copy the code

2. Layout thrashing

In a piece of JS code, repeated layout operations are called layout jitter

function reflow(){
    let el = document.getElementById('app');
    let node = document.createElement('h1');
    node.innerHTML = 'hello';
    el.appendChild(node);
    // Force layout synchronization
    console.log(app.offsetHeight);
}
window.addEventListener('load'.function(){
    for(let i = 0 ; i<100;i++){
        reflow();
    }
});
Copy the code

3. Reduce backflow and redraw

  • Out of document flow

  • Add a fixed width and height to the image while rendering

  • Use CSS3 animations whenever possible

  • It can be extracted into a separate layer using will-change

Static file optimization

1. Image optimization

Image format:

  • JPG: suitable for colorful photos and banners; Does not work with graphics, text, ICONS (texture edges are jagged), transparency is not supported
  • PNG: suitable for solid color, transparent, icon, translucent support; Not suitable for colorful pictures, as lossless storage can result in large storage volume
  • GIF: animated, movable icon; Does not support translucency, discomfort and storage of color pictures
  • Webp: suitable for semi-transparent pictures, can ensure the image quality and small volume
  • SVG images: Smaller and more expensive to render than JPG and JPG, suitable for small, monochromatic ICONS;

Picture optimization:

  • Avoid empty SRC images

  • Reduce image size to save user traffic

  • The IMG tag sets the Alt attribute to improve the user experience when an image fails to load

  • Native loading:lazy image loading

<img loading="lazy" src="./images/1.jpg" width="300" height="450" />
Copy the code
  • Load images of different sizes and pixels in different environments
<img src="./images/1.jpg" sizes="(max-width:500px) 100px,(max-width:600px) 200px"  srcset="./images/1.jpg 100w, ./images/3.jpg 200w">
Copy the code
  • Consider using progressive images for larger images

  • Base64URL is used to reduce image requests

  • Use Sprite image to merge icon pictures, etc

2. HTML optimization

  • Semantic HTML: the code is concise and clear, which is conducive to search engines and team development
  • Declare character encoding up front so the browser can quickly determine how to render web content
  • Reduce HTML nesting and DOM nodes
  • Remove unnecessary Spaces, empty lines, comments, and useless attributes
  • HTML reduces iframes (iframes block onLoad events that can load iframes dynamically)
  • Avoid table layouts

3. The CSS optimization

  • Fewer pseudo-class selectors, fewer style layers, and fewer wildcards

  • Avoid CSS expressions, which are frequently evaluated and recalculated when scrolling or moving the mouse (IE6,7)

background-color: expression( (new Date()).getHours()%2 ? "red" : "yellow" );
Copy the code
  • Remove empty lines, comments, reduce meaningless units, and CSS compression

  • Using external linked CSS, you can cache CSS

  • Add media fields and load only valid CSS files

<link href="index.css" rel="stylesheet" media="screen and (min-width:1024px)" /> 
Copy the code
  • The CSS contain property isolates elements

  • Reduce the use of @import, which is serialized

4. JS optimization

  • Load files asynchronously via Async, defer

  • Reduce DOM manipulation and cache accessed elements

  • Operations are not applied directly to the DOM, but to the virtual DOM. The last one is applied to the DOM.

  • Use webworker to solve application blocking problems

  • IntersectionObserver

const observer = new IntersectionObserver(function(changes) { 
    changes.forEach(function(element, index) {
        if (element.intersectionRatio > 0) { observer.unobserve(element.target); element.target.src = element.target.dataset.src; }}); });function initObserver() {
    const listItems = document.querySelectorAll('img');
    listItems.forEach(function(item) {
        observer.observe(item);
    });
}
initObserver();
Copy the code
  • Virtual scroll vertual-scroll-list

  • RequestAnimationFrame, requestIdleCallback

  • Try not to use eval as it takes too long

  • Reduce the number of event bindings by using event delegates.

  • Use Canvas animation and CSS animation as much as possible

5. Font optimization

@font-face {
    font-family: "Bmy";
    src: url("./HelloQuincy.ttf");
    font-display: block;
    /* block 3s does not display, if not complete load default */
    /* swap displays the old font in place of */
    /* Fallback shortensthe display time, if not complete to use the default, similar to block */
    /* optional may be used instead of */
}
body {
    font-family: "Bmy"
}
Copy the code

FOUT(Flash Of Unstyled Text) waits for a period Of time, and displays the default first if the loading is not complete. Switch after loading.

FOIT(Flash Of Invisible Text) font displayed after loading, system font degraded due to loading timeout (white screen)

Eight. Optimization strategy

  • The more critical resources there are, the longer the first page load time will be

  • The size of the key resource, the smaller the content, the shorter the download time

  • Optimized white screen: Inline CSS and JS to remove file downloads, smaller file size

  • Prerender, prerender when packing

  • Using SSR to speed up the first screen loading (consuming server resources) is conducive to SEO optimization. The first screen is rendered on the server side and subsequent interactions are rendered on the client side

9. Browser storage

  • Cookie: Cookie is valid within the expiration time. The storage size is about 4K and the number of fields is limited. It is not suitable for large amounts of data storage.

    • Setting the cookie validity Period
    • Fewer cookies are transmitted according to different subdomains
    • The static resource domain name and cookie domain name must be different to avoid cookies during static resource access
  • LocalStorage: the maximum storage capacity in chrome is 5M. It exists all the time unless manually cleared. Use localStorage to store static resources

function cacheFile(url) {
    let fileContent = localStorage.getItem(url);
    if (fileContent) {
        eval(fileContent)
    } else {
        let xhr = new XMLHttpRequest();
        xhr.open('GET', url, true);
        xhr.onload = function () {
            let reponseText = xhr.responseText
            eval(reponseText);
            localStorage.setItem(url, reponseText)
        }
        xhr.send()
    }
}
cacheFile('/index.js');
Copy the code
  • SessionStorage: session-level storage for transferring values between pages

  • IndexDB: Local database for the browser (basically unlimited)

let request = window.indexedDB.open('myDatabase');
request.onsuccess = function(event){
    let db = event.target.result;
    let ts = db.transaction(['student'].'readwrite')
    ts.objectStore('student').add({name:'zf'})
    let r = ts.objectStore('student').get(5);
    r.onsuccess = function(e){
        console.log(e.target.result)
    }
}
request.onupgradeneeded  = function (event) {
    let db = event.target.result;
    if(! db.objectStoreNames.contains('student')) {
        let store = db.createObjectStore('student', { autoIncrement: true}); }}Copy the code

X. Experience PWA (Progressive Web App)

Webapp has poor user experience (unable to access offline) and low user stickiness (unable to save entry). Pwa aims to solve these problems and make WebApp fast, reliable and safe

  • Web App Manifest: Add websites to the desktop for a more native like experience
  • Service Worker: Offline cache content, with cache API
  • Push Api & Notification Api: Message Push and Notification
  • App Shell & App Skeleton

11.LightHouse usage

npm install lighthouse -g lighthouse www.taobao.com

You can optimize your pages based on the recommendations in Lighthouse