- Reduce http requests
Avoid multiple requests for small resources. You can combine multiple resources into one resource, such as js, because sending network requests is time-consuming - css is placed at the head and js is placed at the bottom of the body
It helps to render the page faster. css will block the execution of js, because js will be executed only after cssom is created, and js will block the whole rendering process
However, js can also be placed in the header, but to avoid blocking rendering, you can add the defer or async attribute - Use font icon instead of picture Icon
Font icons are much smaller than picture icons, saving transmission overhead - Reduce redraw rearrangement
Avoid using js to frequently manipulate styles. You can use class substitution
Multiple dom operations can be added to or displayed with the help of documentFragment or elements of display:none
Using transform and opacity to implement animation can reduce redrawing and rearrangement, which are attributes handled separately from compositor. - When judging that there are many statements, avoid using if else. You can use switch case or strategist mode, which is easy to read and maintain
- Avoid animating with timers
The timer animation needs to specify the time, and the improper control of the time will cause the page animation to jam.
You can use requestAnimationFrame to animate. We have also introduced this api to execute logic for frames - Static resources can be placed on CDNs
cdn is a group of servers distributed in various regions, so it can serve users according to which server and which server users recently use - You can use web workers
For long-time logic, you can use web workers to start additional threads to execute, which will not block the execution of js code of the main thread.
be careful:- Homology restriction
- Without a window object, its global object or this is itself
- Unable to access the dom node
- Data is transferred with the main thread by copying
Simple use
// Main thread var worker = new Worker('worker.js') // URI of the work thread worker.postMessage([10, 24]) worker.onmessage = function(e) { console.log(e.data) } // Worker thread, worker js onmessage = function (e) { if (e.data.length > 1) { postMessage(e.data[1] - e.data[0]) } } // Stopping the worker thread can call the instance in the main thread close method worker.terminate() // Or the worker calls its own close() this.close()
-
Event related
-
Event delegation
Binding the same event to multiple child elements is not as good as directly binding the event to the parent element. The memory overhead of binding events can be saved by means of event delegation -
Anti shake
When an event is triggered frequently, such as form input check, the check will be performed only after a short period of time after the input is stopped or suspended, instead of always checking
Note that this needs to be boundfunction debounce(callback, delay) { let timer = null return function(){ // Here, you need to clear the last timer. It is always triggered and cleared. Only when the trigger stops can the timer be bound for execution clearTimeout(timer) let context = this timer = setTimeOut(()=> { callback.call(context) }) } }
-
throttle
Anti shake is only for operations that are triggered frequently and will pause and stop. If some operations are triggered all the time and need to respond when they do not stop, for example, when judging the mouse rolling distance to realize lazy loading, throttling can be used for mouse rolling
Implementation mode
timer
When the timer is timed, it will end before the time when it is triggered, that is, the timer still exists. Otherwise, the logic will be executed and the timer will be cleared for re timing next time./* If the timer still exists, exit and do not execute. If it does not exist, bind a timer The bound function will be executed after the delay time arrives. After execution, you need to set timer = null Note that the timer is not cleared and is set to null because the timer saves the id value of the timer The timer is cleared, but the id value is still */ function throttle(callback){ let timer = null return function(){ if(timer) return let context = this timer = setTimeout(() => { callback.call(context) timer = null }) } } ```
time stamp
The time stamp method does not need to use a timer to judge whether the difference between the current time and the last execution time is > the reference value. If it is greater than the reference value, execute and set the reference value as the current time, otherwise it ends.function throttle(callback, delay){ let pre = 0 return function(){ let now = Date.now() if(now - pre > delay) { callback.call(this) pre = now } } }
-
-
Lazy loading of pictures
First, give the picture a resource occupancy attribute and wait until the picture appears in the viewport before loading. Otherwise, loading all pictures at the same time will consume a lot of network resources.
There are two main ways to implement lazy loading. One is to judge whether to reach the viewport by using the style attribute of the element, and the other is to use the api encapsulated by js.
Implementation of clientHeight, offsetTop and scrollTop
Principle:
clientHeight is the height of the container viewport, and scrollTop is the height of the scroll bar. The sum of the two is the actual distance from the element to the top of the container viewport if it is not in the scroll bar, while offscttop is the offset distance from the element to the parent node. If clientHeight + scrollTop ≤ offscttop, it means that the element appears in the viewport and can be displayed.
Note: use an n to save the position of the currently loaded picture, so that you don't have to cycle through it from the beginning every time<style> #div{ border: 2px solid black; height: 500px; overflow: auto; } .div { margin-bottom: 5px; background-color: aquamarine; width: 200px; height: 300px; } </style> <body> <ul id="list"> <li><img data-src="./images/iu.jpg" src='./images/lazy.png' alt=""></li> <li><img data-src="./images/iu1.jpg" src='./images/lazy.png' alt=""></li> <li><img data-src="./images/iu2.png" src='./images/lazy.png' alt=""></li> <li><img data-src="./images/iu3.jpg" src='./images/lazy.png' alt=""></li> <li><img data-src="./images/iu4.jpg" src='./images/lazy.png' alt=""></li> <li><img data-src="./images/iu5.jpg" src='./images/lazy.png' alt=""></li> <li><img data-src="./images/iu6.jpg" src='./images/lazy.png' alt=""></li> <li><img data-src="./images/iu7.jpg" src='./images/lazy.png' alt=""></li> <li><img data-src="./images/iu8.jpg" src='./images/lazy.png' alt=""></li> <li><img data-src="./images/iu9.jpg" src='./images/lazy.png' alt=""></li> <li><img data-src="./images/iu10.jpg" src='./images/lazy.png' alt=""></li> <li><img data-src="./images/zzf_01.jpg" src='./images/lazy.png' alt=""></li> </ul> </body> let list = document.getElementById('list') let imgs = document.getElementsByTagName('img') let len = imgs.length let n = 0 function lazyLoad(){ let clientHeight = list.clientHeight let scrollTop = list.scrollTop for(let i = n; i < len; i++) { let tempSrc = imgs[i].getAttrbute('data-src') if(imgs[i].offset <= clientHeight + scrollTop ) { imgs[i].src = tempSrc n = i // Where is the cache currently loaded } } } // Use anti shake optimization list.addEventListenr('scroll', throttle(lazyLoad, 500))
The above can be implemented normally. After n = i optimization, it will not execute the loaded before repetition, but for round-trip scrolling, the for loop will still be executed for judgment
You can use the IntersectionObserver of js api. If an element is passed in, it can observe whether the corresponding event will be triggered when it is displayed or moved out of the viewport
/* First, create an observation object. The parameters received in the callback are the observed object, which can be multiple, and bind each event The intersectionratio of the observed object is a value, which is > 0 when it appears in the viewport, and vice versa It can be set that when the loading has been triggered, it will be removed from the observed object */ let obser = new IntersectionObserver((imgs) => { for(let i = 0; i < imgs.length; i++) { let img = imgs[i] if(img.inersectionRatio > 0) { img.src = img.getAttrbute('data-src') obser.unobserve(img) } } }) obser.observe(Array.from(imgs))
- webpack related
Use cache
-
When the resource is not changed, go to the cache directly, and splice the file name with the contentHash value to prevent the content from going to the cache when the content is changed.
-
During babel processing, many compatibility processing codes do not need to be rebuilt. You can turn on babel's cache cacheDirectory: true
Code compressioncss compression uses the optimizecssasassetswebpackplugin plug-in
html compression uses html webpack plugin
js automatic compression in production environment