Wann sollte ich Inline vs. External Javascript verwenden?

129

Ich würde gerne wissen, wann ich externe Skripte einbinden oder sie in Bezug auf Leistung und Wartungsfreundlichkeit in den HTML-Code schreiben sollte.

Was ist die allgemeine Praxis dafür?

Real-World-Szenario - Ich habe mehrere HTML-Seiten, die eine clientseitige Formularüberprüfung benötigen. Dafür verwende ich ein jQuery-Plugin, das ich auf all diesen Seiten einbinde. Aber die Frage ist, mache ich:

  • Schreiben Sie die Code-Bits, die dieses Skript inline konfigurieren?
  • alle Bits in eine Datei aufnehmen, die von all diesen HTML-Seiten gemeinsam genutzt werden?
  • jedes Bit in eine separate externe Datei aufnehmen, eine für jede HTML-Seite?

Vielen Dank.

Dan Burzo
quelle

Antworten:

114

Zu dem Zeitpunkt, als diese Antwort ursprünglich veröffentlicht wurde (2008), war die Regel einfach: Alle Skripte sollten extern sein. Sowohl für die Wartung als auch für die Leistung.

(Warum Leistung? Wenn der Code separat ist, kann er von Browsern einfacher zwischengespeichert werden.)

JavaScript gehört nicht in den HTML - Code und wenn es Sonderzeichen (wie enthält <, >) es schafft auch Probleme.

Heutzutage hat sich die Skalierbarkeit des Webs geändert. Das Reduzieren der Anzahl von Anforderungen ist aufgrund der Latenz mehrerer HTTP-Anforderungen zu einer gültigen Überlegung geworden. Dies macht die Antwort komplexer: In den meisten Fällen wird immer noch empfohlen , JavaScript extern zu verwenden . In bestimmten Fällen, insbesondere bei sehr kleinen Codeteilen, ist es jedoch sinnvoll, sie in den HTML-Code der Site einzufügen.

Konrad Rudolph
quelle
6
@ Nick: Die meisten Probleme können überwunden werden. Es ist jedoch besser, sie überhaupt nicht zu generieren.
Konrad Rudolph
17
Manchmal erhalten Sie beim Inlining eine bessere Leistung. Schauen Sie sich die Quelle von google.com an . Sie wissen, was sie tun.
Callum
13
@callum Google hat einen anderen Anwendungsfall als 99,999999% der Websites. Natürlich messen sie äußerst sorgfältig und selbst der kleinste Unterschied ist wichtig. Nur weil sie festgestellt haben, dass Inlining in ihrem speziellen Anwendungsfall besser funktioniert (wahrscheinlich, weil sich das Skript sehr häufig ändert?), Bedeutet dies nicht, dass wir daraus eine allgemeine Regel ableiten können oder dass wir sogar das „Konventionelle“ ignorieren sollten. Regel (um Skripte zu externalisieren).
Konrad Rudolph
8
@KonradRudolph - Einverstanden, aus Googles Ansatz sollte keine allgemeine Regel abgeleitet werden. Ich sage nur, es ist ein Hinweis darauf, dass es sich lohnen könnte, die Regel in Ihrer Antwort in Frage zu stellen . Ich denke, der Grund, warum Google dies tut, ist die Reduzierung von HTTP-Anfragen, und dies könnte mehr als 0,000001% der Websites zugute kommen. Die Bandbreite wird immer höher, aber die Umlaufzeiten bleiben gleich. Das Entfernen einer gesamten seriellen HTTP-Anforderung ist manchmal besser als der Caching-Vorteil von externem JS. Hängt natürlich von der Größe Ihres JS ab.
Callum
5
@callum Während dies wahr ist, bleibt der Punkt über das Caching immer noch wichtig. Das Reduzieren von Roundtrips ist nur wichtig, wenn Ihre Besucher nicht zurückkehren (und Sie dann nicht genügend Seitentreffer erhalten, damit es wichtig wird) oder wenn sich Ihr Inhalt so oft ändert, dass das Zwischenspeichern der Skriptdateien keinen Vorteil hat.
Konrad Rudolph
31

Die Wartbarkeit ist definitiv ein Grund, sie extern zu halten. Wenn die Konfiguration jedoch einzeilig ist (oder im Allgemeinen kürzer als der HTTP-Overhead, den Sie erhalten würden, um diese Dateien extern zu machen), ist es in Bezug auf die Leistung besser, sie inline zu halten. Denken Sie immer daran, dass jede HTTP-Anforderung einen gewissen Overhead in Bezug auf Ausführungszeit und Datenverkehr verursacht.

Natürlich wird dies alles irrelevant, sobald Ihr Code länger als ein paar Zeilen ist und nicht wirklich spezifisch für eine einzelne Seite ist. Sobald Sie diesen Code wiederverwenden möchten, machen Sie ihn extern. Wenn nicht, schauen Sie sich die Größe an und entscheiden Sie dann.

Horst Gutmann
quelle
5
Das ist eines meiner Anliegen. Eine separate HTTP-Anforderung für einige Codezeilen zu haben, erscheint verschwenderisch.
Dan Burzo
Könnten Sie vielleicht eine Beispielkonfiguration für Ihren Code veröffentlichen? IMO, wenn es weniger als 300 Zeichen und absolut seitenspezifisch ist, inline.
Horst Gutmann
Dies sollte die beste Antwort sein imo
sgarcia.dev
@Dan bedenken Sie, dass die separate Anfrage nur beim ersten Mal erfolgt. Wenn Sie erwarten, dass Ihre Benutzer die Seite mehr als einmal laden, ist das zwischengespeicherte externe System (auch für einige Zeilen) deutlich schneller als das Warten auf die Bytes für diese wenigen Zeilen über das Kabel beim Laden der Seite n = 2 +.
Jinglesthula
@HorstGutmann Wie hilft es, die Datei extern zu pflegen? Ich persönlich bevorzuge externe js, wann immer dies möglich ist, aber gibt es ein Ziel, das die Wartung erleichtert?
Jinglesthula
21

Das Externalisieren von Javascript ist eine der Leistungsregeln von Yahoo: http://developer.yahoo.com/performance/rules.html#external

Während die feste Regel, dass Sie Skripte immer externalisieren sollten, im Allgemeinen eine gute Wahl ist, möchten Sie in einigen Fällen möglicherweise einige der Skripte und Stile einbinden. Sie sollten jedoch nur Inline-Dinge verwenden, von denen Sie wissen, dass sie die Leistung verbessern (weil Sie dies gemessen haben).

Joeri Sebrechts
quelle
1
Ich denke, Yahoo empfiehlt auch, das gesamte Javascript zu einem HTTP-Aufruf hinzuzufügen - dies bedeutet jedoch nicht, dass sich die Skripte während der Entwicklung alle in derselben Datei befinden sollten
Paul Shannon
Wie oben erwähnt, ändert HTTP / 2 auch die Praxis "1 Anruf".
Jinglesthula
19

Wenn Sie sich nur um die Leistung kümmern, sind die meisten Ratschläge in diesem Thread völlig falsch und werden in der SPA-Ära, in der wir davon ausgehen können, dass die Seite ohne den JS-Code unbrauchbar ist, immer falscher. Ich habe unzählige Stunden damit verbracht, die Ladezeiten von SPA-Seiten zu optimieren und diese Ergebnisse mit verschiedenen Browsern zu überprüfen. Auf der ganzen Linie kann die Leistungssteigerung durch Neu-Orchestrierung Ihres HTML-Codes ziemlich dramatisch sein.

Um die beste Leistung zu erzielen, müssen Sie sich Seiten als zweistufige Raketen vorstellen. Diese beiden Stufen entsprechen ungefähr <head>und <body>Phasen, aber betrachten Sie sie stattdessen als <static>und <dynamic>. Der statische Teil ist im Grunde eine String-Konstante, die Sie so schnell wie möglich über die Antwortleitung schieben. Dies kann etwas schwierig sein, wenn Sie eine Menge Middleware verwenden, die Cookies setzt (diese müssen vor dem Senden von http-Inhalten gesetzt werden), aber im Prinzip wird nur der Antwortpuffer geleert, hoffentlich bevor Sie in einen Vorlagencode (Rasiermesser, PHP, etc) auf dem Server. Das mag schwierig klingen, aber dann erkläre ich es nur falsch, weil es fast trivial ist. Wie Sie vielleicht vermutet haben, sollte dieser statische Teil alles Javascript enthalten, das inline und minimiert ist. Es würde ungefähr so ​​aussehen

<!DOCTYPE html>
     <html>
         <head>
             <script>/*...inlined jquery, angular, your code*/</script>
             <style>/* ditto css */</style>
         </head>
         <body>
             <!-- inline all your templates, if applicable -->
             <script type='template-mime' id='1'></script>
             <script type='template-mime' id='2'></script>
             <script type='template-mime' id='3'></script>

Da es Sie so gut wie nichts kostet, diesen Teil über das Kabel zu senden, können Sie davon ausgehen, dass der Client dies nach einer Verbindung mit Ihrem Server etwa 5 ms + Latenz empfängt. Unter der Annahme, dass der Server relativ nahe ist, kann diese Latenz zwischen 20 ms und 60 ms liegen. Browser beginnen mit der Verarbeitung dieses Abschnitts, sobald sie ihn erhalten, und die Verarbeitungszeit dominiert normalerweise die Übertragungszeit um den Faktor 20 oder mehr. Dies ist nun Ihr amortisiertes Fenster für die serverseitige Verarbeitung des <dynamic>Teils.

Es dauert ungefähr 50 ms, bis der Browser (Chrome, Rest möglicherweise 20% langsamer) Inline-Abfrage + Signal + Winkel + ng animiert + ng Berührung + ng Routen + Lodash verarbeitet. Das ist an und für sich schon erstaunlich. Die meisten Web-Apps haben weniger Code als alle gängigen Bibliotheken zusammen, aber nehmen wir an, Sie haben genauso viel, sodass wir auf dem Client Latenz + 100 ms Verarbeitung gewinnen würden (dieser Latenzgewinn kommt vom zweiten Übertragungsblock). Bis der zweite Block eintrifft, haben wir den gesamten js-Code und die Vorlagen verarbeitet und können mit der Ausführung von dom-Transformationen beginnen.

Sie können einwenden, dass diese Methode orthogonal zum Inlining-Konzept ist, dies ist jedoch nicht der Fall. Wenn Sie anstelle von Inlining eine Verknüpfung zu CDNS oder Ihren eigenen Servern herstellen, muss der Browser eine andere Verbindung (en) öffnen und die Ausführung verzögern. Da diese Ausführung grundsätzlich kostenlos ist (da die Serverseite mit der Datenbank spricht), muss klar sein, dass all diese Sprünge mehr kosten würden, als überhaupt keine Sprünge zu machen. Wenn es eine Browser-Eigenart gäbe, die besagt, dass externes js schneller ausgeführt wird, könnten wir messen, welcher Faktor dominiert. Meine Messungen zeigen, dass zusätzliche Anforderungen die Leistung in dieser Phase beeinträchtigen.

Ich arbeite viel mit der Optimierung von SPA-Apps. Es ist üblich, dass die Leute denken, dass das Datenvolumen eine große Sache ist, während in Wahrheit Latenz und Ausführung oft dominieren. Die minimierten Bibliotheken, die ich aufgelistet habe, addieren sich zu 300 KB Daten, und das sind nur 68 KB gezippt oder 200 ms Download auf einem 2 MBit 3g / 4g-Telefon. Dies ist genau die Latenz, die auf demselben Telefon benötigt wird, um zu überprüfen, ob dieselben Daten vorhanden sind bereits im Cache, auch wenn der Proxy zwischengespeichert wurde, da die Steuer auf mobile Latenz (Telefon-zu-Turm-Latenz) weiterhin gilt. In der Zwischenzeit haben Desktop-Verbindungen mit geringerer First-Hop-Latenz normalerweise ohnehin eine höhere Bandbreite.

Kurz gesagt, im Moment (2014) ist es am besten, alle Skripte, Stile und Vorlagen einzubinden.

BEARBEITEN (MAI 2016)

Da JS-Anwendungen weiter wachsen und einige meiner Nutzdaten jetzt mehr als 3 Megabyte minimierten Codes stapeln, wird klar, dass zumindest gängige Bibliotheken nicht mehr eingebunden werden sollten.

Gleno
quelle
Ich habe nicht das erhalten, was jetzt Ihr amortisiertes Fenster für die serverseitige Verarbeitung des Teils <dynamic> ist. Der Server verarbeitet, was immer er benötigt, und bedient erst dann das gesamte gerenderte HTML (head + body), welche andere Serververarbeitung wird danach benötigt?
BornToCode
@BornToCode Die Idee ist, dem Client etwas zu tun zu geben, während die Serverseite etwas zu tun hat. Da die Client - Bibliotheken interpretiert werden müssen - es ist besser, diesen Prozess , bevor Sie den ersten Schritten jede Berechnung auf dem Server. Das amortisierte Fenster gibt die Zeit an, die der Client benötigt, um das JS zu verarbeiten. Sie erhalten dieses Fenster kostenlos, wenn Sie eine zweistufige Rakete orchestrieren.
Gleno
9

Tatsächlich gibt es einen ziemlich soliden Fall für die Verwendung von Inline-Javascript. Wenn das js klein genug ist ( einzeilig ), bevorzuge ich das Inline-Javascript aus zwei Gründen:

  • Lokalität . Es ist nicht erforderlich, in einer externen Datei zu navigieren, um das Verhalten von Javascript zu überprüfen
  • AJAX . Wenn Sie einen Abschnitt der Seite über AJAX aktualisieren, verlieren Sie möglicherweise alle Ihre DOM-Handler (onclick usw.) für diesen Abschnitt, je nachdem, wie Sie sie gebunden haben. Wenn Sie beispielsweise verwenden, können jQuerySie entweder die Methode liveoder delegateverwenden, um dies zu umgehen, aber ich finde, wenn das js klein genug ist, ist es vorzuziehen, es einfach inline zu setzen.
Miguel Ping
quelle
5

Ein weiterer Grund, warum Sie immer externe Skripte verwenden sollten, ist der einfachere Übergang zur Content Security Policy (CSP) . Die CSP-Standardeinstellungen verbieten alle Inline-Skripte, wodurch Ihre Site widerstandsfähiger gegen XSS-Angriffe wird.

Chiborg
quelle
4

Ich würde mir den erforderlichen Code ansehen und ihn in so viele separate Dateien wie nötig aufteilen. Jede js-Datei würde nur einen "logischen Satz" von Funktionen usw. enthalten, z. Eine Datei für alle Anmeldefunktionen.

Während der Site-Entwicklung auf jeder HTML-Seite geben Sie dann nur die benötigten an. Wenn Sie mit Ihrer Site live gehen, können Sie optimieren, indem Sie jede js-Datei, die eine Seite benötigt, in einer Datei kombinieren.

Gen
quelle
4

Die einzige Verteidigung, die ich für Inline-Javascipt anbieten kann, ist, dass Sie bei Verwendung stark typisierter Ansichten mit .net MVC auf c # -Variablen in der Mitte von Javascript verweisen können, die ich als nützlich erachtet habe.

Austin_G
quelle
3

Drei Überlegungen:

  • Wie viel Code benötigen Sie (manchmal sind Bibliotheken ein erstklassiger Verbraucher)?
  • Spezifität: Funktioniert dieser Code nur im Kontext dieses bestimmten Dokuments oder Elements?
  • Jeder Code im Dokument führt dazu, dass es länger und damit langsamer wird. Außerdem machen SEO-Überlegungen deutlich, dass Sie interne Skripte minimieren ...
Roenving
quelle
2

Externe Skripte sind auch mit Firebug einfacher zu debuggen. Ich mag es, mein JavaScript zu testen und alles extern zu haben, hilft. Ich hasse es, JavaScript in PHP-Code und HTML zu sehen, es sieht für mich nach einem großen Durcheinander aus.

Kupplung
quelle
2

Um JavaScript extern zu halten:

ASP.NET 3.5SP1 hat kürzlich Funktionen zum Erstellen einer Composite-Skriptressource eingeführt (mehrere JS-Dateien zu einer zusammenführen). Ein weiterer Vorteil ist, dass beim Aktivieren der Webserver-Komprimierung das Herunterladen einer etwas größeren Datei eine bessere Komprimierungsrate aufweist als viele kleinere Dateien (auch weniger HTTP-Overhead, Roundtrip usw.). Ich denke, dies spart beim ersten Laden der Seite, dann wird das Browser-Caching wie oben erwähnt aktiviert.

Abgesehen von ASP.NET werden in diesem Screencast die Vorteile ausführlicher erläutert: http://www.asp.net/learn/3.5-SP1/video-296.aspx

Brendan Kowitz
quelle
2

Ein weiterer versteckter Vorteil externer Skripte besteht darin, dass Sie sie einfach über einen Syntaxprüfer wie jslint ausführen können . Das kann Sie vor vielen herzzerreißenden, schwer zu findenden IE6-Fehlern bewahren.

Ken
quelle
1

In Ihrem Szenario scheint es gut für Sie zu sein, das externe Material in eine Datei zu schreiben, die auf den Seiten geteilt wird. Ich stimme mit allem überein, was oben gesagt wurde.

mattlant
quelle
1

Halten Sie Ihren Code während des frühen Prototyping inline, um eine schnelle Iteration zu gewährleisten. Stellen Sie jedoch sicher, dass bis zum Erreichen der Produktion alles extern ist.

Ich würde sogar sagen, wenn Sie nicht alle Ihre Javascript extern platzieren können, dann haben Sie ein schlechtes Design unter Ihren Händen, und Sie sollten Ihre Daten und Skripte umgestalten

Robert Gould
quelle
1

Google hat Ladezeiten in seine Seitenranking-Messungen einbezogen. Wenn Sie viel inline arbeiten, dauert es länger, bis die Spinnen durch Ihre Seite kriechen. Dies kann sich auf Ihr Seitenranking auswirken, wenn Sie zu viel enthalten. In jedem Fall können unterschiedliche Strategien Einfluss auf Ihr Ranking haben.

Kees Hessels
quelle
1

Nun, ich denke, dass Sie Inline verwenden sollten, wenn Sie Websites mit nur einer Seite erstellen, da Skripte nicht auf mehreren Seiten geteilt werden müssen

Zak Sheikh
quelle
-3

Versuchen Sie immer, externe Js zu verwenden, da Inline-Js immer schwer zu warten sind.

Darüber hinaus ist es professionell erforderlich, dass Sie ein externes js verwenden, da die Mehrheit der Entwickler die externe Verwendung von js empfiehlt.

Ich selbst benutze externe js.

Daniel Puiu
quelle
2
Beruflich erforderlich? Warum? Wer sagt das?
Siyah