Follow the video to knock again, strengthen memory, collation, convenient copy manual move brick, there is wrong place welcome big guy pointed out
1. Have you done any work related to front-end loading optimization? What efforts have been made.
What is the purpose of performance tuning?
- The first screen time
- First interaction time
- First meaningful content rendering time
Common optimization methods?
- Request only the resources you currently need
- Asynchronous loading, lazy loading, polyfill optimization
- Reduce resource volume
- Pack and compress WebPack 4
- gzip
- Image format optimization, compression, according to the screen resolution of the display of different resolution of the picture
- Try to control the size of cookies
- Timing optimization
- Js promise.all Sends the request concurrently
- SSR package on the server, by the server to do rendering output, convenient to do different caching; Not on the CDN; Convenient to seo
- prefetch, prerender, preload
// Perform DNS pre-resolution immediately when xxx.com is encountered<link rel="dns-prefetch" href="xxx1.com" />
<link rel="dns-prefetch" href="xxx2.com" />
<link rel="preconnect" href="xxx1.com" />// Preload image resources<link rel="preload" as="image" href="https://aaa.com/xxx.png" />
Copy the code
- Use caching wisely
- CDN CDN preheat CDN refresh
- HTTP cache
- localStorage, sessionStorage
🤔 : If a section of JS execution time is long, how to analyze? (Decorator calculates function execution time)
// a decorator
export function measure(target: any, name: string, descriptor: any) {
const oldValue = descriptor.value;
descriptor.value = async function () {
console.time(name);
const ret = await oldValue.apply(this.arguments);
console.timeEnd(name);
return ret;
}
return descriptor;
}
/ / verification
export default class Home extends Vue {
public longTimefn(){
return new Promise((resolve) = > setTimeout(resove, 3000));
}
Measure lets you know how long the console created output takes to execute
@measure
public async created(){
await this.longTimefn(); }}Copy the code
🤔 : Ali cloud OSS supports image format conversion through the link behind the spelling parameter, try to write, any image format conversion to webP, need to pay attention to what?
- Determine whether the browser is compatible with web: caniuse.com/ & WebP format conversion
- Pay attention to some boundary problems
function checkWebp() {
try {
return (
document.createElement('canvas')// Create a Canvas element to convert the image to base64 format.
.toDataURL('image/webp')
.indexOf('data:image/webp') = = =0
) // Check whether the browser supports Webp
} catch (e) {
return false; }}const supportWebp = checkWebp();
export function getWebpImageUrl(url) {
if(! url){throw Error('URL cannot be empty')}// Whether it is base64 format
if(url.startsWith('data:')) {return url;
}
// Whether webP is supported
if(! supportWebp) {return url;
}
return url + '? x-oss-processxxxx';// String concatenation
}
Copy the code
- toDataURL
🤔 : If you have a large number of images to display, other than lazy loading, is there any other way to limit the number of images loaded at the same time? (Essence: code problem, realize promise concurrency control)
- Promise.race() returns the first completed result, which can be high or low? Or rejects
function limitLoad(urls, handler, limit){
const sequence = [].concat(urls);
let promises = [];
promises = sequence.splice(0, limit).map((url, index) = > {
return handler(url).then(() = >{ retuen index; })});let p = Promise.race(promises);
for (let i = 0; i < sequence.length; i++) {
p = p.then((res) = > {
promises[res] = handler(sequence[i]).then(() = > {
return res;
});
return Promise.race(promises);
})// Do the sequential push}}Copy the code
Have you ever paid attention to the memory processing of the front end?
1. Do you know about memory management in JS? What can cause a memory leak?
-
Memory life cycle
- Memory allocation: When declaring variables, functions, and objects, the system automatically allocates memory.
- Memory usage: reading and writing memory, that is, when calling, using variables, functions, etc.
- Memory reclamation: The garbage collection mechanism reclaims unused memory.
-
Memory allocation in Js
const n = 123; // Allocate memory for numeric variables constS = "azerty" scored with;// Allocate memory to the string const o = { a: 1.b: null }; // Allocate memory for objects and their contained values Copy the code
-
The process of using a value is actually reading and writing the allocated memory. Reading and writing may be writing the value of a variable or an object property, or even passing the parameters of a function.
var a = 10; // Allocate memory console.log(a); // Memory usage Copy the code
-
Garbage collection mechanism in js
Garbage collection algorithms rely heavily on the concept of references.
In a memory-managed environment, an object that has access to another object (implicitly or explicitly) is said to reference another object.
For example, a Javascript object has a reference to its stereotype (implicit reference) and a reference to its attributes (explicit reference). Here, the concept of “object” refers not only specifically to Javascript objects, but also to function scopes (or global lexical scopes).
- 4.1 Reference Counting Algorithm. Recycling. Defects: circular references, memory leaks
- Reference counting algorithms define “memory out of use” simply by looking at whether an object has a reference to it. If no other object points to it, it is no longer needed.
- But it has a fatal problem: circular references.
- If two objects refer to each other, even though they are no longer in use, garbage collection does not collect, resulting in a memory leak.
- 4.2 Mark clearing algorithm.
- The tag clearing algorithm defines “no longer used object” as “unreachable object”. In simple terms, it periodically scans objects in memory from the root (in JS, global objects). Anything that can be reached from the root is still needed. Objects that cannot be reached from the root are marked as unused and recycled later.
- Tag all variables stored in memory at run time
- Trigger from the root, can touch the object, remove the mark;
- Those that still have tags are considered variables to be deleted;
- Finally, the garbage collector performs the final step of memory cleaning, destroying the tagged values and reclaiming the memory they occupy.
- The tag clearing algorithm defines “no longer used object” as “unreachable object”. In simple terms, it periodically scans objects in memory from the root (in JS, global objects). Anything that can be reached from the root is still needed. Objects that cannot be reached from the root are marked as unused and recycled later.
-
What are the common memory leaks in js?
- The global variable
function foo() {bar1 = 'some text';// No declared variable is actually a global variable => window.bar1 thisThe bar2 = 'some text'// Global variable => window.bar2 } foo(); window.bar1 = null;// Free the memory Copy the code
- Uncleared timers and callbacks
If the subsequent renderer element is removed, the entire timer actually does nothing. However, if you do not recycle the timer, the entire timer is still valid. Not only can the timer not be recycled, but also the dependencies in the timer function can not be recycled. ServerData in this case also cannot be recycled.
var serverData = loadData(); setInterval(function() { var renderer = documentDocument.getelementbyid (" the renderer ");if(renderer) { renderer.innerHTML = JSON.stringify(serverData); }},5000); // call every 5 seconds // Clear the timer clearTimeout(a);clearInterval(a);Copy the code
- closure
An inner function that has access to variables in the enclosing function. Closures can also cause memory leaks in the following cases
var theThing = null; var replaceThing = function () { var originalThing = theThing; var unused = function () { if (originalThing) // Reference to 'originalThing' console.log (" hi "); }; theThing = {longStr: new Array(1000000). The join (' * '),someMethod: function () { console.log (" message "); }}; };setInterval(replaceThing, 1000); Copy the code
This code, each time replaceThing is called, theThing gets an object containing a large array and an object for the new closure someMethod. Unused is also a closure that references originalThing. The key to this example is that closures are shared in scope, and while unused may never be called, someMethod may be called, making it impossible to reclaim its memory. As this code is executed repeatedly, memory continues to grow.
- DOM references
Most of the time, when we operate on the DOM, we store references to the DOM in an array or Map. In the following case, even though we have removed the image element, there is still a reference to the image element and it cannot be garbage collected. Elements. Image = null; Is very necessary
constElements = {image:document.getElementById('image')} document. Body. RemoveChild (document. GetElementById ('The image ")); elements.image =null;// The attributes of the object still exist, remember to release Copy the code
-
How to avoid memory leaks
- Reduce unnecessary global variables and use strict patterns to avoid accidentally creating global variables.
- Dereference (variables in closures, DOM references, timer cleanup) when data is used
- Organize your logic to avoid endless loops that cause your browser to freeze and crash.
🤔 : Implement the sizeOf function, passing in an object argument and counting how many bytes this object takes up.
Investigation: 1. Investigation on the basis of computer and JS memory; 2. Recursion; 3. Carefulness
- Number: 64-bit storage, 8 bytes
- String: Each string contains 2 bytes
- Boolean: 4 bytes
const xxx = {};
const testData = {
a: 111.// 8 bytes + key:2 bytes = 10
b: 'aaa'.// 6 bytes + key:2 bytes = 8
2222: false.// 4 bytes + key:2 bytes = 6
c: xxx,// Note: the same memory reference is 2+2 = 4 without occupying additional memory space
d: xxx // 2 bytes + 2 = 4
}// Total 32 bytes
const seen = new WeakSet(a);// Processing of objects
function sizeOfObject(object) {
if(object === null) {return 0;
}
let bytes = 0;
// Note that the key in the object also occupies memory space!
const properties = Object.keys(object);
for(let i = 0; i < properties.length; i++){
const key = properties[i];
bytes += calculator(key);// No matter what type, the key should be counted!
if(typeof object[key] === 'object'&& object[key] ! = =null) {
if(seen.has(object[key])){
continue;/ / a pit
}
seen.add(object[key]);
}
// bytes += calculator(key); / / a pitbytes += calculator(object[key]); }}function calculator(object) {
/ / type, also can: Object. The prototype. ToString. Call (Object) = = = '[Object Object]'
const objectType = typeof object;
switch(objectType){
case 'string': {return object.length * 2;
}
case 'boolean': {return 4;
}
case 'number': {return 8;
}
case 'object': {if(Array.isArray(object)) {
// Handle the array recursively
/ / [1, 2, 3, 4]
// [{a:1},{b:2}]
// Use Map to process each element through Calculator again, recursively until it is not of object type, and then use Reduce to do addition.
return object.map(calculator).reduce((res,current) = > res + current,0)}else{
// Processing of objects
returnsizeOfObject(object); }}}}console.log(calculator(testData));/ / 32
Copy the code
Refer to the object – sizeof