Heim >Web-Frontend >js-Tutorial >Zusammenfassung der Js-Front-End-Leistungsoptimierung
Die beste Ressourcenoptimierung besteht darin, Ressourcen nicht zu belasten. Caching ist auch die effektivste Optimierungsmethode. Um ehrlich zu sein: Obwohl das clientseitige Caching auf der Browserseite erfolgt, wird das Caching hauptsächlich vom Server gesteuert und hat wenig mit unserem Front-End zu tun. Aber es ist immer noch notwendig, es zu verstehen.
Caching umfasst serverseitiges Caching und clientseitiges Caching. In diesem Artikel geht es nur um clientseitiges Caching. Der sogenannte Client-Cache ist hauptsächlich http-Cache. HTTP-Caching wird hauptsächlich in erzwungenes Caching und ausgehandeltes Caching unterteilt.
Expires (http1.0)
Verwenden Sie Expires in http1.0, um erzwungenes Caching durchzuführen. Der Wert von Exprires ist die Ablaufzeit der vom Server zurückgegebenen Daten. Wenn die Anforderungszeit bei erneuter Anforderung kürzer als die zurückgegebene Zeit ist, werden die zwischengespeicherten Daten direkt verwendet. Da jedoch die Serverzeit und die Clientzeit unterschiedlich sein können, führt dies auch zu Cache-Trefferfehlern.
Cache-Control
Cache-Control hat viele Attribute und verschiedene Attribute haben unterschiedliche Bedeutungen.
privat: Client kann zwischenspeichern
öffentlich: Sowohl Client als auch Proxyserver können zwischenspeichern
max-age=t: Der zwischengespeicherte Inhalt läuft nach t Sekunden ab
no-cache: Ausgehandelter Cache muss verwendet werden, um die zwischengespeicherten Daten zu überprüfen
no-store: Alle Inhalte werden nicht zwischengespeichert.
Wenn der Browser zum ersten Mal Daten anfordert, antwortet der Server dem Client mit der Cache-ID und den Daten, und der Client sichert sie in der Cache. Bei einer erneuten Anfrage sendet der Client die Kennung im Cache an den Server, und der Server beurteilt anhand dieser Kennung. Wenn dieser nicht abgelaufen ist, wird ein 304-Statuscode zurückgegeben. Der Browser kann die zwischengespeicherten Daten direkt nach Erhalt dieses Statuscodes verwenden.
Zuletzt geändert
Wenn der Server auf die Anfrage antwortet, teilt er dem Browser den Zeitpunkt der letzten Änderung der Ressource mit
if-Modified-Since
Wenn der Browser den Server erneut anfordert, enthält der Anforderungsheader dieses Feld, gefolgt von der Last-Modified (last Änderungszeit) im Cache abgerufen). Wenn der Server diesen Anforderungsheader empfängt und if-Modified-Since vorliegt, vergleicht er ihn mit der letzten Änderungszeit der angeforderten Ressource. Wenn er größer als die letzte Änderungszeit der angeforderten Ressource ist, gibt er 304 und den Browser zurück ruft die Ressource aus dem Cache ab. Wenn es kleiner als die letzte Änderungszeit der angeforderten Ressource ist, wird 200 zurückgegeben und die neueste Ressource wird zurückgegeben. Der Browser ruft die neueste Ressource vom Server ab und speichert sie zwischen.
Etag
Eine eindeutige identifizierende Zeichenfolge, die vom Server für jede Ressource generiert wird
Wenn - Keine Übereinstimmung
Wenn Sie den Server erneut anfordern, enthält der Anforderungsnachrichtenheader des Browsers dieses Feld und der nachfolgende Wert ist die im Cache erhaltene Kennung. Nach dem Empfang der Nachricht findet der Server If-None-Match und vergleicht es mit der eindeutigen Kennung der angeforderten Ressource. Wenn sie gleich sind, bedeutet dies, dass die Ressource nicht geändert wurde, geben Sie 304 zurück und der Browser ruft die Ressource aus dem Cache ab. Wenn sie unterschiedlich sind, bedeutet dies, dass die Ressource geändert wurde, und geben Sie 200 zurück Neueste Ressource: Der Browser ruft die neueste Ressource vom Server ab und speichert sie im Cache.
Last-Modified und ETag können zusammen verwendet werden. Wenn sie konsistent sind, vergleicht er weiterhin Last-Modified und entscheidet schließlich, ob 304 zurückgegeben wird.
Wenn Sie ein Front-End-Paketierungstool verwenden, können Sie der Datei beim Packen eine Versionsnummer oder einen Hash-Wert hinzufügen und außerdem erkennen, ob die Ressource abgelaufen ist.
CDN zum Hosten statischer Ressourcen verwenden
Sie können dazu Verpackungstools wie gulp und webpack verwenden Paket js und css Warten Sie, bis die Dateien zusammengeführt und komprimiert werden
Bilder werden träge und bei Bedarf geladen, und Bilder werden nur geladen, wenn zum sichtbaren Bereich des Bildes gescrollt wird
Kleine Bilder und Bilder, die sich im Grunde nicht ändern, werden mit Base64-Kodierung übertragen. Missbrauchen Sie base64 nicht. Selbst kleine Bilder erzeugen nach der Base64-Codierung sehr lange Zeichenfolgen. Wenn Sie base64 missbrauchen, ist dies kontraproduktiv, da bei Verwendung eines Bildes das gesamte Sprite-Bild neu generiert wird wahllos wird es kontraproduktiv sein.
Reduzieren Sie die Größe der HTTP-Anfrageressourcen
Aktivieren Sie die gzip-Komprimierung auf dem Server (die Komprimierungsrate ist sehr beeindruckend, normalerweise über 30 %).
Wenn Sie Verpackungstools verwenden, muss die Verpackungsoptimierung gut durchgeführt werden, öffentliche Ressourcen , Codeextraktion von Drittanbietern, Es werden keine gepackten Bibliotheken benötigt...
Rendering-Optimierung
FPS 16 ms, weniger als 10 ms ist am besten, verwenden Sie Google Devtool, um die Bildrate zu überprüfen
Wenn der Browser FPS 60 erreicht, erscheint er flüssiger. Die Aktualisierungsfrequenz der meisten Monitore beträgt 60 Hz und der Browser aktualisiert Animationen automatisch mit dieser Frequenz.
Berechnet auf der Grundlage von FPS von 60 beträgt die durchschnittliche Frame-Zeit 1000 ms/60 = 16,7 ms, sodass jede Renderzeit 16 ms nicht überschreiten darf. Wenn diese Zeit überschritten wird, kommt es zu Frame-Verlusten und Verzögerungen.
Sie können die Aktualisierungsrate in der Timeline in den Chrome-Browser-Entwicklertools überprüfen und den Zeitverbrauch aller Bildraten und die Ausführung eines bestimmten Frames überprüfen. Tutorial zur Timeline-Nutzung: https://segmentfault.com/a/11...
Um normale FPS zu gewährleisten, ist noch eine gewisse Optimierung der Rendering-Leistung erforderlich. Im Folgenden sind alle Strategien im Zusammenhang mit der Rendering-Optimierung aufgeführt.
Versuchen Sie, CSS3 für Animationen zu verwenden
Wie wir alle wissen, ist die Leistung von CSS schneller als die von JS, sodass Sie CSS und verwenden können Versuchen Sie, js nicht zu verwenden. Um
zu implementieren, vermeiden Sie die Verwendung von setTimeout oder setInterval und versuchen Sie, requestAnimationFrame für Animationen oder hochfrequente Dom-Operationen zu verwenden.
Da setTimeout und setInterval den Ausführungszeitpunkt der Rückruffunktion nicht garantieren können, wird sie wahrscheinlich am Ende des Frames ausgeführt, was zu einem Frameverlust führt. requestAnimationFrame kann dies jedoch garantieren Die Rückruffunktion wird zu Beginn jedes Animationsframes ausgeführt. Bei der Ausführung
requestAnimationFrame Chinesische MDN-Adresse: https://developer.mozilla.org...
Komplexe Berechnung Operationen verwenden Web Worker
Wenn Sie komplexe Datenoperationen benötigen, wie z. B. das Durchlaufen und Summieren eines Arrays von Elementen, dann sind Web Worker perfekt.
Web Worker können die Ausführung von JavaScript-Skripten in Hintergrundthreads zulassen (ähnlich wie beim Erstellen eines untergeordneten Threads), und der Hintergrundthread hat keine Auswirkungen auf die Seite im Hauptthread. Allerdings können Threads, die mit Web Workern erstellt wurden, den DOM-Baum nicht bedienen.
Weitere Informationen zu Web Workern finden Sie in der ausführlichen MDN-Erklärung: https://developer.mozilla.org...
css steht an der Spitze und js wird am Schwanz platziert.
Wer den vorherigen js-Ausführungsmechanismus gelesen hat, sollte den Prozess des Seitenrenderings kennen, daher werde ich nicht auf Details eingehen. Durch das Platzieren von CSS am Kopf wird das Phänomen des Neulayouts des Begrüßungsbildschirms nach dem Generieren des HTML-Baums vermieden. JS hat im Allgemeinen einen größeren Einfluss auf die Seite und wird im Allgemeinen für die letzte Ausführung am Ende platziert.
Ereignisentprellung und -drosselung
Bei hochfrequent ausgelösten Ereignissen (Mausbewegung, Scrollen) und anderen Ereignissen kann es, wenn es nicht kontrolliert wird, viele auslösen Ereignisse in kurzer Zeit.
Funktion Anti-Shake bedeutet, dass der Code bei häufiger Auslösung nur einmal ausgeführt wird, wenn genügend freie Zeit vorhanden ist. Szenario: Im E-Mail-Eingabefeld wird während der Registrierung in Echtzeit beurteilt, ob das E-Mail-Format korrekt ist. Wenn das erste Eingabeereignis ausgelöst wird, legen Sie den Zeitpunkt fest: Führen Sie die Prüfung nach 800 ms durch. Wenn nur 100 ms vergangen sind und der letzte Timer nicht ausgeführt wurde, löschen Sie den Timer und stellen Sie ihn erneut auf 800 ms ein. Bis zur letzten Eingabe gibt es keine benachbarte Eingabe, das Timing dieser letzten Eingabe endet und der Prüfcode wird schließlich ausgeführt.
const filter = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/; $("#email").on("keyup",checkEmail()); function checkEmail(){ let timer=null; return function (){ clearTimeout(timer); timer=setTimeout(function(){ console.log('执行检查'); },800); } }
Funktionsdrosselung bedeutet, dass die js-Methode innerhalb eines bestimmten Zeitraums nur einmal ausgeführt wird. Das heißt, was ursprünglich 100 Mal pro Sekunde ausgeführt wurde, wird 10 Mal pro Sekunde.
Szenario: Das tatsächliche Szenario der Funktionseinschränkungsanwendung, das größtenteils bei der Überwachung der Bildlaufereignisse von Seitenelementen verwendet wird.
var canRun = true; document.getElementById("throttle").onscroll = function(){ if(!canRun){ // 判断是否已空闲,如果在执行中,则直接return return; } canRun = false; setTimeout(function(){ console.log("函数节流"); canRun = true; }, 300); };
Dom-Betrieb
Front-End-Entwickler wissen alle, dass der Do-Betrieb sehr zeitaufwändig ist (ich habe persönlich 30* getestet) 30 Tabellendurchläufe zum Hinzufügen von Stilen). Versuchen Sie also, häufige Dom-Operationen zu vermeiden. Wenn Sie dies nicht vermeiden können, versuchen Sie, die DOm-Operationen zu optimieren.
1.:缓存Dom查询,比如通过getElementByTagName('p')获取Dom集,而不是逐个获取。 2: 合并Dom操作,使用createDocumentFragment()
var frag = document.createDocumentFragment() for (i<10) { var li = document.createElement('li') frag.appendChild(li) } document.body.appendChild(frag)
3: 使用React、Vue等框架的虚拟dom(原理目前还不明白),可以更快的实现dom操作。
Vermeiden Sie Repaint (rePaint) und Reflow (reFlow)
Wenn Sie js verwenden, um Elemente ändern Die Farbe oder Hintergrundfarbe löst ein Neuzeichnen aus, und die Kosten für das Neuzeichnen sind immer noch relativ hoch, da der Browser alle Knoten innerhalb eines DOM-Elements überprüft, nachdem sich der visuelle Effekt des DOM-Elements geändert hat.
Wenn die Größe und Position des Elements geändert wird, ist der Reflow teurer. Er wird ausgelöst, nachdem sich die Position eines bestimmten DOM-Elements geändert hat, und die Position aller Elemente wird neu berechnet Ihre Platzierung auf der Seite führt dazu, dass ein bestimmter Teil der Seite oder sogar die gesamte Seite neu gerendert wird.
CSS3-Hardwarebeschleunigung
Wenn der Browser rendert, wird er in zwei Ebenen unterteilt: eine normale Ebene und eine zusammengesetzte Ebene.
Der normale Dokumentenfluss kann als zusammengesetzte Ebene verstanden werden. Obwohl das absolute und feste Layout vom normalen Dokumentenfluss getrennt werden kann, gehört er dennoch zur gewöhnlichen Ebene und die Hardwarebeschleunigung wird nicht aktiviert. Das oben erwähnte Neuzeichnen und Neufließen bezieht sich auf das Neuzeichnen und Neufließen auf gewöhnlichen Ebenen.
Verbundschichten ermöglichen eine Hardwarebeschleunigung. Es befindet sich nicht auf derselben Ebene wie die normale Ebene, daher hat die zusammengesetzte Ebene keinen Einfluss auf die normale Ebene. Wenn ein Element in die zusammengesetzte Ebene heraufgestuft wird und das Element dann bearbeitet wird, wird die normale Ebene nicht neu gezeichnet und reflowed Dies verbessert die Rendering-Leistung.
So starten Sie die Hardwarebeschleunigung:
1. Verwenden Sie Translate3d und TranslateZ
webkit-transform: translateZ(0); -moz-transform: translateZ(0); -ms-transform: translateZ(0); -o-transform: translateZ(0); transform: translateZ(0); webkit-transform: translate3d(0,0,0); -moz-transform: translate3d(0,0,0); -ms-transform: translate3d(0,0,0); -o-transform: translate3d(0,0,0); transform: translate3d(0,0,0);
2.使用opacity
需要动画执行的过程中才会创建合成层,动画没有开始或结束后元素还会回到之前的状态
3.使用will-chang属性
这个属性比较不常用,一般配合opacity与translate使用
针对webkit浏览器,启用硬件加速有些时候可能会导致浏览器频繁闪烁或抖动,可以使用下面方法消除:
-webkit-backface-visibility:hidden; -webkit-perspective:1000;
如果使用硬件加速,请使用z-index配合使用, 因为如果这个元素添加了硬件加速,并且index层级比较低, 那么在这个元素的后面其它元素(层级比这个元素高的,或者相同的,并且releative或absolute属性相同的), 会默认变为复合层渲染,如果处理不当会极大的影响性能
避免强制同步布局和布局抖动
浏览器渲染过程为:js/css(javascript) > 计算样式(style) > 布局(layout) > 绘制(paint) > 渲染合并图层(Composite)
JavaScript:JavaScript实现动画效果,DOM元素操作等。
Style(计算样式):确定每个DOM元素应该应用什么CSS规则。
Layout(布局):计算每个DOM元素在最终屏幕上显示的大小和位置。
Paint(绘制):在多个层上绘制DOM元素的的文字、颜色、图像、边框和阴影等。
Composite(渲染层合并):按照合理的顺序合并图层然后显示到屏幕上。
在js中如果读取style属性的某些值就会让浏览器强行进行一次布局、计算,然后再返回值,比如:
offsetTop, offsetLeft, offsetWidth, offsetHeight scrollTop/Left/Width/Height clientTop/Left/Width/Height width,height 请求了getComputedStyle(), 或者 IE的 currentStyle
所以,如果强制浏览器在执行JavaScript脚本之前先执行布局过程,这就是所谓的强制同步布局。
比如下面代码:
requestAnimationFrame(logBoxHeight); // 先写后读,触发强制布局 function logBoxHeight() { // 更新box样式 box.classList.add('super-big'); // 为了返回box的offersetHeight值 // 浏览器必须先应用属性修改,接着执行布局过程 console.log(box.offsetHeight); } // 先读后写,避免强制布局 function logBoxHeight() { // 获取box.offsetHeight console.log(box.offsetHeight); // 更新box样式 box.classList.add('super-big'); }
在JavaScript脚本运行的时候,它能获取到的元素样式属性值都是上一帧画面的,都是旧的值。因此,如果你在当前帧获取属性之前又对元素节点有改动,那就会导致浏览器必须先应用属性修改,结果执行布局过程,最后再执行JavaScript逻辑。
如果连续多次强制同步布局,就会导致布局抖动
比如下面代码:
function resizeAllParagraphsToMatchBlockWidth() { for (var i = 0; i < paragraphs.length; i++) { paragraphs[i].style.width = box.offsetWidth + 'px'; } } 作者:SylvanasSun 链接:https://juejin.im/post/59da456951882525ed2b706d 来源:掘金 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
我们知道浏览器是一帧一帧的刷新页面的,对于每一帧,上一帧的布局信息都是已知的。
强制布局就是使用js强制浏览器提前布局,比如下面代码:
// bed 每次循环都要去获取left ,就会发生一次回流 function logBoxHeight() { box.style.left += 10 console.log(box.style.left) } // goog var width = box.offsetWidth; function resizeAllParagraphsToMatchBlockWidth() { for (var i = 0; i < paragraphs.length; i++) { // Now write. paragraphs[i].style.width = width + 'px'; } }
DOMContentLoaded与Load
DOMContentLoaded 事件触发时,仅当DOM加载完成才触发DOMContentLoaded,此时样式表,图片,外部引入资源都还没加载。而load是等所有的资源加载完毕才会触发。
1. 解析HTML结构。 2. 加载外部脚本和样式表文件。 3. 解析并执行脚本代码。 4. DOM树构建完成。//DOMContentLoaded 5. 加载图片等外部文件。 页面加载完毕。//load
视觉优化
等待加载时间可以合理使用loading gif动图一定程度上消除用户等待时间的烦躁感
代码对性能的影响可大可小,但是养成一个良好的写代码习惯和高质量的代码,会潜移默化的提高性能,同时也能提高自己的水平。废话不多说,直接看我总结的部分要点(因为这一部分知识点太多,需要大家写代码的时候多多总结)。
避免全局查找
访问局部变量会比访问全局变量快,因为js查找变量的时候现在局部作用局查找,找不到在逐级向上找。
// bad function f () { for (...){ console.log(window.location.href) } } //good function f () { var href = window.location.href for (...){ console.log(href) } }
循环技巧
// bed for(var i = 0; i < array.length; i++){ .... } // good for(var i = 0, len = array.length; i < len; i++){ .... } // 不用每次查询长度
不要使用for in 遍历数组
for in是最慢的,其他的都差不多,其中直接使用for循环是最快的。for in只是适合用来遍历对象。
使用+''代替String()吧变量转化为字符串
var a = 12 //bad a = String(a) // good var a = 12 a = a + ''
这个还有很多类似的,比如使用*1代替parseInt()等都是利用js的弱类型,其实这样对性能提升不是很大,网上有人测试过,进行十几万次变量转换,才快了零点几秒。
删除dom
删除dom元素要删除注册在该节点上的事件,否则就会产生无法回收的内存,在选择removeChild和innerHTML=''二者之间尽量选择后者,据说removeChild有时候无法有效的释放节点(具体原因不明)
使用事件代理处理事件
任何可以冒泡的事件都可以在节点的祖先节点上处理,这样对于子节点需要绑定相同事件的情况就不用分别给每个子节点添加事件监听,而是都提升到祖先节点处理。
通过js生成的dom对象必须append到页面中
在IE下,js创建的额dom如果没有添加到页面,这部分内存是不会被回收的
避免与null比较
可以使用下面方法替换与null比较
1.如果该值为引用类型,则使用instanceof检查其构造函数
2.如果该值为基本类型,使用typeof检查类型
尽量使用三目运算符代替if else
if(a>b){num = a} else{num = b} // 可以替换为 num = a > b ? a : b
当判断条件大于3中情况时,使用switch代替if
因为switch的执行速度比if要快,也别是在IE下,速度大约是if的两倍。
相关推荐:
Das obige ist der detaillierte Inhalt vonZusammenfassung der Js-Front-End-Leistungsoptimierung. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!