Heim >Web-Frontend >js-Tutorial >Eine ausführliche Erklärung der Leistungsoptimierung in JavaScript

Eine ausführliche Erklärung der Leistungsoptimierung in JavaScript

亚连
亚连Original
2018-06-21 16:10:081343Durchsuche

Jetzt werde ich einen Artikel über JavaScript-basierte Leistungsoptimierungstechniken mit Ihnen teilen. Er hat einen guten Referenzwert und ich hoffe, dass er für alle hilfreich sein wird. Folgen wir dem Editor, um einen Blick darauf zu werfen

JavaScript ist derzeit die gebräuchlichste wörtliche Skriptsprache und wird häufig in der Entwicklung von Webanwendungen verwendet. Um die Leistung von Webanwendungen zu verbessern, wäre es eine gute Wahl, mit der JavaScript-Leistungsoptimierung zu beginnen.

In diesem Artikel werden JavaScript-Leistungsoptimierungstechniken unter verschiedenen Aspekten wie Laden, Kontext, Analyse, Kompilierung, Ausführung und Bündelung erläutert, damit mehr Front-End-Entwickler dieses Wissen beherrschen können.

Was ist Hochleistungs-JavaScript-Code?

Obwohl es derzeit keine absolute Definition von Hochleistungscode gibt, gibt es ein benutzerzentriertes Leistungsmodell, das als Referenz verwendet werden kann: das RAIL-Modell.

Antwort

Wenn Ihre Anwendung innerhalb von 100 Millisekunden auf die Aktion des Benutzers reagieren kann, betrachtet der Benutzer die Antwort als echt Zeit. Dies gilt für anklickbare Elemente, nicht für Scroll- oder Ziehvorgänge.

Animation

Auf einem 60-Hz-Monitor hätten wir gerne 60 Bilder pro Sekunde für Animation und Scrollen, in diesem Fall wäre jedes Bild etwa 16 ms lang. Von diesen 16 ms stehen eigentlich nur 8–10 ms für die gesamte Arbeit zur Verfügung, der Rest der Zeit wird von Browser-Interna und anderen Unterschieden in Anspruch genommen.

Leerlaufarbeit

Wenn Sie eine Aufgabe haben, die lange dauert und kontinuierlich ausgeführt werden muss, stellen Sie sicher, dass Sie sie in kleine Abschnitte unterteilen, damit der Hauptthread dies tun kann Reagieren Sie auf Benutzereingabevorgänge. Es sollte keine Aufgabe geben, die die Benutzereingabe um mehr als 50 ms verzögert.

Laden

Das Laden der Seite sollte innerhalb von 1000 ms abgeschlossen sein. Auf Mobilgeräten ist dieses Ziel schwer zu erreichen, da es sich dabei um eine Interaktion mit der Seite und nicht nur um das Rendern und Scrollen auf dem Bildschirm handelt.

Moderne Best Practices für das Laden (Chrome Dev Summit 2017)

53 % der Nutzer verlassen eine mobile Website, wenn das Laden länger als drei Sekunden dauert. Besuch

50 % der Nutzer erwarten, dass Seiten in weniger als 2 Sekunden geladen werden

77 % der mobilen Websites benötigen in 3G-Netzwerken mehr als 10 Sekunden zum Laden

19 Sekunden sind der Durchschnitt Ladezeit für mobile Websites in 3G-Netzwerken

Codeinhalt

Sie haben vielleicht bemerkt, dass der größte Engpass die benötigte Zeit zum Laden der Website ist. Konkret geht es um die Download-, Parsing-, Kompilierungs- und Ausführungszeit von JavaScript. Es scheint keine andere Möglichkeit zu geben, als weniger JavaScript-Dateien zu laden oder diese flexibler zu laden.

Wie funktioniert JavaScript-Code eigentlich, abgesehen vom Starten der Website?

Bevor Sie Ihren Code optimieren, überlegen Sie, was Sie gerade erstellen. Erstellen Sie ein Framework oder eine VDOM-Bibliothek? Muss Ihr Code Tausende von Operationen pro Sekunde ausführen? Erstellen Sie eine zeitkritische Bibliothek, die Benutzereingaben und/oder Animationen verarbeitet? Wenn nicht, müssen Sie Ihre Zeit und Energie auf wirkungsvollere Bereiche umlenken.

Das Schreiben von performantem Code ist nicht so wichtig, da es normalerweise nur geringe Auswirkungen auf das Gesamtbild der Dinge hat. 50.000 Operationen/s klingen besser als 1.000 Operationen/s, aber in den meisten Fällen ändert sich die Gesamtzeit nicht.

Parsen, kompilieren und ausführen

Grundsätzlich liegen die meisten JavaScript-Leistungsprobleme nicht in der Ausführung des Codes selbst, sondern in einer Reihe von Schritte, die unternommen werden müssen, bevor der Code ausgeführt werden kann.

Wir diskutieren hier die Abstraktionsebene. Der meiste Code, der auf einem Computer ausgeführt wird, liegt im kompilierten Binärformat vor. Dies bedeutet, dass der Code mit Ausnahme aller Abstraktionen auf Betriebssystemebene nativ auf der Hardware ausgeführt werden kann, ohne dass eine Vorbereitung erforderlich ist.

JavaScript-Code ist nicht vorkompiliert, er ist im Browser lesbar.

JavaScript-Code wird zunächst geparst, d. h. gelesen und in eine Struktur umgewandelt, die zum Kompilieren von Computerindizes verwendet werden kann, dann in Bytecode kompiliert und schließlich in Maschinencode für die Geräte-/Browserprozessorausführung kompiliert.

Ein weiterer sehr wichtiger Aspekt: ​​JavaScript ist Single-Threaded und läuft im Haupt-Thread des Browsers. Dies bedeutet, dass jeweils nur ein Prozess ausgeführt werden kann. Wenn Ihre DevTools-Leistungszeitleiste mit gelben Spitzen gefüllt ist und die CPU-Auslastung 100 % erreicht, werden Frames verloren gehen. Dies ist eine häufige und ärgerliche Situation beim Scrollen.

All diese Analyse, Kompilierung und Ausführung müssen durchgeführt werden, bevor JavaScript-Code ausgeführt werden kann. In der ChromeV8-Engine machen Parsing und Kompilierung etwa 50 % der gesamten JavaScript-Ausführungszeit aus.

In diesem Teil sollten Sie also zwei Dinge wissen:

1 Obwohl JavaScript-Parsing Die Dauer ist nicht völlig linear mit der Größe des Bundles, aber je weniger JavaScript verarbeitet werden muss, desto weniger Zeit wird benötigt.

2. Jedes von Ihnen verwendete JavaScript-Framework (React, Vue, Angular, Preact...) ist eine weitere Abstraktionsebene (sofern es sich nicht um eine vorkompilierte handelt). Dies erhöht nicht nur die Größe Ihres Pakets, sondern verlangsamt auch Ihren Code, da Sie nicht direkt mit dem Browser kommunizieren.

Es gibt Möglichkeiten, dies zu mildern, z. B. den Einsatz von Servicemitarbeitern, die einen Teil der Arbeit in einem anderen Thread im Hintergrund ausführen, oder die Verwendung von asm.js, um Code zu schreiben, der sich einfacher zu Maschinenanweisungen kompilieren lässt.

Alles, was wir tun können, ist, die Verwendung von JavaScript-Animationsbibliotheken zu vermeiden. Verwenden Sie diese Bibliotheken nur, wenn dies mit regulären CSS-Übergängen und -Animationen überhaupt nicht möglich ist.

Obwohl diese JavaScript-Animationsbibliotheken CSS-Transformationen, Kompositionseigenschaften und requestAnimationFrame( ) verwenden, werden sie dennoch im Hauptthread von JavaScript ausgeführt. Grundsätzlich greifen diese Bibliotheken mithilfe von Inline-Stilen alle 16 ms auf das DOM zu. Sie müssen sicherstellen, dass das gesamte JavaScript innerhalb von 8 ms nach jedem Frame abgeschlossen ist, um die reibungslose Animation zu gewährleisten.

Andererseits werden CSS-Animationen und -Übergänge im Hauptthread ausgeführt, und wenn sie effizient ausgeführt werden können, können Relayout-/Reflow-Situationen vermieden werden.

Wenn man bedenkt, dass die meisten Animationen während des Ladens oder der Benutzerinteraktion laufen, kann dies Ihrer Webanwendung einige sehr wichtige Optimierungen verleihen.

Die Webanimations-API ist ein kommender Funktionssatz, der die Ausführung leistungsstarker JavaScript-Animationen außerhalb des Hauptthreads ermöglicht. Aber vorerst müssen Technologien wie CSS-Übergänge weiterhin verwendet werden.

Bundle-Größe ist sehr wichtig

Es ist nicht mehr notwendig, mehrere 3f1c4e4b6b16bbbd69b2ee476dc4f83a vor dem schließenden Tag 36cc49f0c466276486e50c850b7e4956 einzufügen . Ära. Mittlerweile ist auf npm eine Vielzahl von Toolkits zu finden, die mit Webpack in einer einzigen 1-MB-JavaScript-Datei gebündelt werden können und den Browser des Benutzers darauf hinweisen, zu crawlen, wenn der Datenplan abgeschlossen ist.

Dadurch wird weniger JavaScript verwendet, was auch bedeutet, dass Ihr Projekt möglicherweise nicht mehr die gesamte Lodash-Bibliothek benötigt. Wenn Sie eine JavaScript-Bibliothek verwenden müssen, sollten Sie etwas anderes als React in Betracht ziehen, z. B. Preact oder HyperHTML, die nur 1/20 der Größe von React haben.

Webpack 3 verfügt über erstaunliche Funktionen namens Code-Splitting und dynamische Importe. Es bündelt nicht alle JavaScript-Module in einem einzigen app.js-Paket, sondern verwendet die import()-Syntax, um den Code automatisch aufzuteilen und asynchron zu laden.

Sie müssen keine Frameworks, Komponenten und clientseitiges Routing verwenden, um diese Vorteile zu nutzen. Sie müssen lediglich Folgendes in die Haupt-JavaScript-Datei schreiben:

if (document.querySelector('.mega-widget')) {
 import('./mega-widget');
}

Wenn Ihre Anwendung dieses Widget auf der Seite benötigt, lädt sie dynamisch den erforderlichen unterstützenden Code.

Außerdem benötigt Webpack Laufzeit, um zu funktionieren und es in alle von ihm generierten .js-Dateien einzufügen. Wenn Sie das commonChunks-Plugin verwenden, können Sie Folgendes verwenden, um die Laufzeit in Blöcke zu extrahieren:

new webpack.optimize.CommonsChunkPlugin({
 name: 'runtime',
}),

Stellen Sie sicher, dass Webpack vor dem Haupt-JavaScript-Bundle vollständig geladen wurde, dann wird die Laufzeit in allen anderen Blöcken zerlegt eine eigene Datei, in diesem Fall auch runtime.js genannt. Zum Beispiel:

<script src="runtime.js">
<script src="main-bundle.js">

Dann kommt der Teil des Kompilierens von Code und Polyfills. Wenn Sie modernen JavaScript-Code (ES6+) schreiben, können Sie ihn mit Babel in ES5-kompatiblen Code konvertieren. Die Kompilierung erhöht nicht nur die Dateigröße, sondern auch die Komplexität und leidet häufig unter Leistungseinbußen im Vergleich zu nativem ES6+-Code.

Darüber hinaus werden Sie höchstwahrscheinlich das Paket babel-polyfill und whatwg-fetch verwenden, um fehlende Funktionen in älteren Browsern zu beheben. Wenn Sie also async/await schreiben, müssen Sie zum Kompilieren auch das Generatorpaket regenerator-runtime verwenden.

Das Problem besteht darin, dass Sie fast 100 KB zu Ihrem JavaScript-Paket hinzufügen, was nicht nur eine riesige Datei ist, sondern auch einen enormen Mehraufwand bei der Analyse und Ausführung darstellt, um ältere Browser unterstützen zu können.

一种方法是创建两个独立的 bundle,并根据实际条件来加载它们。Babel 转换编译器在 babel-preset-env 的帮助下,会使同时面临新旧两种浏览器的情况更加容易处理。

一个并不规范但行之有效的方法,是将以下内容放在一个内联脚本中:

(function() {
 try {
 new Function(&#39;async () => {}&#39;)();
 } catch (error) {
 // create script tag pointing to legacy-bundle.js;
 return;
 }
 // create script tag pointing to modern-bundle.js;;
})();

如果浏览器无法识别 async 函数,则会被认为是旧版本的浏览器,此时就会用到 polyfill 包。如果能识别,用户则将得到现代浏览器的处理。

结论

想要提高网站的运行速度,就需要确保网站能快速的加载 JavaScript 文件,以实现快速的互动。你的 JavaScript 代码应该被分成更小的、可管理的 bundle,同时尽可能地进行异步加载。在服务器端,请确保启用了 HTTP 2.0,以便实现更快的并行传输和 gzip/Brotli 压缩,从而大大减少了 JavaScript 的传输大小。

上面是我整理给大家的,希望今后会对大家有帮助。

相关文章:

使用JQUERY如何实现多个AJAX请求

使用js如何实现焦点图效果

在微信小程序中如何实现图片懒加载

Das obige ist der detaillierte Inhalt vonEine ausführliche Erklärung der Leistungsoptimierung in JavaScript. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn