Common problems in front-end performance optimization (access URL process, first screen loading, JS memory management)

Table of contents

One: What happened from entering the URL to the completion of the page loading display

Two: First screen loading optimization

Three: JavaScript memory management


One: What happened from entering the URL to the completion of the page loading display

The UI thread will judge whether the input address address is a search keyword or a URL to visit a site

Next, the UI thread will notify the Network thread to initiate a network request

  1. DNS lookup is required first to convert the domain name into an IP address
  2. In the process of establishing a link, it depends on the protocol. If you use HTTPS , you need to establish a TLS connection .
  3. If you encounter 301 (permanently removed), you need to re-initiate the request
  4. The request is processed on the server , and finally it will be organized into a Response and returned to the front end
  5. After reading the first few bytes of the Response, we will start to analyze the data type. Although we will tell the server what the Content-Type is in the header section , this is not necessarily correct, and the browser will judge it ( safety check )

The UI thread and  Network thread  introduced earlier actually belong to the browser process, and the rendering work will be handed over to the rendering process .

The main thread starts text parsing and converts documents into DOM objects

  1. When the main thread parses and constructs the DOM , in order to speed up , it will perform a pre- scan , and first scan out the tags in the HTML. When the HTML parser encounters JS, it will pause the document for further parsing (because JS will modify the DOM). You can use async/defer to prevent JS from blocking HTML parsing
  2. The main thread parses the CSS calculation style , creates the layout tree and determines the size & position of each element
  3. The next task is handed over to the drawing thread and the composite thread . The main thread will create drawing records after traversing the layout tree, because the drawing is in order, and then split the page to build a layer tree , and finally the composite thread creates a layer into a composite frame
     

Two: First screen loading optimization

  • The characteristics of Web incremental loading determine that the performance of the first screen will not be perfect
  • Too long white screen affects user experience and retention
  • above the fold -> first impression

Above the fold - 3 key moments of user loading experience

 measurement standard:

 solution:

Resource size is too large

  • Resource compression for HTML, CSS, JS (compression and obfuscation)
  • Transport Compression Enable Gzip
  • Use splitChunks for code splitting (splitting out third-party libraries, business logic, and public code)
  • Use TreeShaking to shake down unused code (based on ES6 import export)
  • Speed ​​up resource loading with HTTP 2 multiplexing
  • Reasonable use of cache (Cache-Control/Expires)

too much homepage

  • Lazy loading of routes, components, and image lists
  • Use pre-rendering or SSR to generate HTML content in advance to reduce request transmission time
  • Embed the most needed CSS on the first screen into the page Inline CSS

Load order is wrong

  • Use prefetch, preload to improve the loading order
     

Three: JavaScript memory management

  • Memory leaks seriously affect performance
  • High level language  !=  No need to manage memory

Automatically allocate memory when variables are created, and "automatically" release memory when not in use (GC)

  • The main problem with memory deallocation is how to determine the memory that is no longer needed
  • All GC (garbage collection) are approximate implementations, only by judging whether the variable can be accessed again
var number = 123 // 给数分配内存
var string = 'myString' // 给字符串分配内存
var obj = {
  m: 1,
  n: onj2,
} // 给对象和它的属性分配内存
var a = [1, null, 'str'] // 给数组和它包含的值分配内存
function f(a) {
  return a + 3
} // 给函数分配内存

JavaScript has relative scope

  • Local variables, after the function is executed, there is no closure reference, it will be marked for recycling
  • Global variable until released when the browser unloads the page

GC (Garbage Collection) implementation mechanism

  • Reference counting - cannot solve the problem of circular references (a refers to b, b refers to a, even if other variables do not refer to a and b). garbage collected
  • Mark clearing  - will scan from the root node to see if all root nodes can be accessed, if any node cannot be accessed, it will be recycled

// b 属性始终没有用到,但是从根节点始终可以访问到 b 属性,所以 b 属性不能被回收
const object = { a: new Array(1000), b: new Array(2000) }
setInterval(() => console.log(object.a), 1000)

Solution:

  • avoid accidental global variable creation
function accidentalGlobal() {
  leak1 = 'leak1'
  this.leak2 = 'leak2'
}
accidentalGlobal()
window.leak1
window.leak2
  • Avoid repeatedly running references to a large number of closures
// store会持有outer的上下文
var store
function outer() {
  var largeData = new Array(1000)
  var preStore = store
  function inner() {
    if (preStore) return largeData
  }
  return function () {}
}
setInterval(function () {
  store = outer()
}, 10)
  • Avoid breaking out of DOM elements
function createElement() {
  const div = document.createElement('div')
  div.id = 'detached'
  return div
}
const detachedDiv = createElement()
document.body.appendChild(detachedDiv)
function deleteElement() {
  document.body.removeChild(document.getElementById('detached'))
}
// 虽然 DOM 删除了,但是变量还在引用
deleteElement()

Guess you like

Origin blog.csdn.net/qq_42691298/article/details/128574236