Kernkonzepte von webpack-dev-serverWebpacks ContentBase vs. publicPath vs. output.pathwebpack-dev-server verwendet den aktuellen Pfad als angeforderten Ressourcenpfad (den sogenannten Aktueller Pfad Dies ist der Pfad zum Ausführen des Befehls webpack-dev-server. Wenn webpack-dev-server gepackt ist, z. B. wcf, dann bezieht sich der aktuelle Pfad auf den Pfad zum Ausführen des wcf-Befehls (im Allgemeinen der Stammpfad des Projekts). Leser können dieses Standardverhalten jedoch ändern, indem sie content-base angeben: webpack-dev-server --content-base build/ Auf diese Weise verwendet der Webpack-Dev-Server die Ressourcen im Build-Verzeichnis, um Anforderungen für statische Ressourcen wie CSS/Bilder zu verarbeiten. content-base sollte grundsätzlich nicht mit publicPath oder output.path verwechselt werden. Die Inhaltsbasis gibt den Pfad der statischen Ressource an, wie im folgenden Beispiel: <!DOCTYPE html> <html> <Kopf> <Titel></Titel> <link rel="stylesheet" type="text/css" href="index.css" rel="externes nofollow" > </Kopf> <Text> <div id="react-content">Hier JS-Inhalt einfügen</div> </body> </html> Wie lautet der Pfad von index.css oben, nachdem es als Vorlage für das HTML-Webpack-Plugin verwendet wurde? Im Verhältnis zu wem? Es wurde oben betont: Wenn content-base nicht angegeben ist, ist es relativ zum aktuellen Pfad. Der sogenannte aktuelle Pfad ist das Verzeichnis, in dem webpack-dev-server ausgeführt wird. Wenn dieser Befehl also im Stammpfad des Projekts ausgeführt wird, müssen Sie sicherstellen, dass die Ressource index.css im Stammpfad des Projekts vorhanden ist, da sonst ein 404-Fehler im html-webpack-plugin auftritt. Um dieses Problem zu lösen, können Sie die Inhaltsbasis natürlich in dasselbe Verzeichnis wie die HTML-Vorlage des HTML-Webpack-Plugins ändern. Wie oben erwähnt, bezieht sich die Inhaltsbasis nur auf Anforderungen für statische Ressourcen. Unterscheiden wir also zwischen ihrem öffentlichen Pfad und ihrem Ausgabepfad. modul.exporte = { Eintrag: { App: ["./app/main.js"] }, Ausgabe: { Pfad: Pfad.resolve(__dirname, "build"), öffentlicher Pfad: "/assets/", //An diesem Punkt entspricht der Pfad /assets/ dem Build-Verzeichnis, bei dem es sich um eine Zuordnungsbeziehung handelt: „bundle.js“ } } Dann können wir über localhost:8080/assets/bundle.js auf die kompilierten Ressourcen zugreifen. Wenn sich im Build-Verzeichnis eine HTML-Datei befindet, können Sie mit der folgenden Methode auf die JS-Ressource zugreifen: <!DOCTYPE html> <html lang="de"> <Kopf> <meta charset="UTF-8"> <title>Dokument</title> </Kopf> <Text> <script src="assets/bundle.js"></script> </body> </html> An diesem Punkt sehen Sie die folgende Ausgabe auf der Konsole: Bildbeschreibung hier eingeben Konzentrieren Sie sich auf die folgenden beiden Ergebnisse:
Der Grund für diese Ausgabe ist, dass contentBase auf „Build“ eingestellt ist, da der ausgeführte Befehl Hot-Reloading (HMR) für Webpack-Dev-Server Um den HMR-Modus für den Webpack-Dev-Server zu aktivieren, fügen Sie der Befehlszeile einfach --hot hinzu. Dadurch wird das Plugin HotModuleReplacementPlugin zur Webpack-Konfiguration hinzugefügt. Der einfachste Weg zum Aktivieren von HotModuleReplacementPlugin ist also die Verwendung des Inline-Modus. Fügen Sie im Inlinemodus einfach --inline --hot zur Befehlszeile hinzu, um dies automatisch zu erreichen. Funktion reloadApp() { wenn(heiß) { log("info", "[WDS] Hot-Update der App..."); window.postMessage("webpackHotUpdate" + currentHash, "*"); } anders { log("info", "[WDS] App aktualisiert. Wird neu geladen..."); fenster.standort.neuladen(); } } Die Protokolle in webpack/hot/dev-server beginnen alle mit [HMR] (es ist ein Plugin von Webpack selbst): wenn(!aktualisierteModule) { console.warn("[HMR] Update kann nicht gefunden werden. Vollständiger Neustart erforderlich!"); console.warn("[HMR] (Wahrscheinlich wegen eines Neustarts des Webpack-Dev-Servers)"); fenster.standort.neuladen(); zurückkehren; } Wie verwendet man also die HMR-Funktion in Node.js? Zu diesem Zeitpunkt müssen Sie drei Konfigurationsdateien ändern: 1. Fügen Sie einen Webpack-Einstiegspunkt hinzu: webpack/hot/dev-server wenn(Optionen.inline) { var devClient = [require.resolve("../client/") + "?" + Protokoll + "://" + (Optionen.public || (Optionen.host + ":" + Optionen.port))]; //Fügen Sie den Client-Eintrag des Webpack-Dev-Servers zum Paket hinzu, um eine automatische Aktualisierung zu erreichen, wenn (Optionen.hot) devClient.push("webpack/hot/dev-server"); //Hier ist die Verarbeitung der Hot-Konfiguration im webpack-dev-server [].concat(wpOpt).forEach(function(wpOpt) { wenn(Typ von wpOpt.entry === "Objekt" && !Array.istArray(wpOpt.entry)) { Objekt.Schlüssel(wpOpt.entry).fürJeden(Funktion(Schlüssel) { wpOpt.entry[Schlüssel] = devClient.concat(wpOpt.entry[Schlüssel]); }); } anders { wpOpt.entry = devClient.concat(wpOpt.entry); } }); } Die Verwendung von Node.js, das die drei oben genannten Bedingungen erfüllt, ist wie folgt: var config = require("./webpack.config.js"); config.entry.app.unshift("webpack-dev-server/client?http://localhost:8080/", "webpack/hot/dev-server"); //Bedingung 1 (Hinzufügen des Clients von webpack-dev-server und des Servers von HMR) var Compiler = webpack(Konfiguration); var Server = neuer webpackDevServer(Compiler, { hot: true //Bedingung 2 (--hot-Konfiguration, webpack-dev-server fügt automatisch HotModuleReplacementPlugin hinzu) ... }); server.listen(8080); webpack-dev-server startet ProxyWebpack-Dev-Server-Nutzung http-Proxy-Middleware Um die Anforderung an einen externen Server weiterzuleiten, lautet das Konfigurationsbeispiel wie folgt: Proxy: { '/api': { Ziel: 'https://other-server.example.com', sicher: falsch } } // In webpack.config.js { devServer: { Proxy: { '/api': { Ziel: 'https://other-server.example.com', sicher: falsch } } } } // Mehrfacheingabe Proxy: [ { Kontext: ['/api-v1/**', '/api-v2/**'], Ziel: 'https://other-server.example.com', sicher: falsch } ] Diese Art von Proxy ist in vielen Fällen sehr wichtig. Beispielsweise können einige statische Dateien über einen lokalen Server geladen werden, während einige API-Anfragen alle über einen Remote-Server ausgeführt werden. Ein anderes Szenario besteht darin, Anforderungen auf zwei separate Server aufzuteilen, beispielsweise einen Server, der für die Autorisierung zuständig ist, und einen anderen Server, der für die Anwendung selbst zuständig ist. Hier ist ein Beispiel aus der täglichen Entwicklung: (1) Eine Anfrage erfolgt über einen relativen Pfad, wie zum Beispiel die Adresse "/msg/show.htm". Allerdings werden den Alltags- und Produktionsumgebungen unterschiedliche Domänennamen vorangestellt, beispielsweise you.test.com für die Alltagsnutzung und you.inc.com für Produktionsumgebungen. (2) Wenn Sie beispielsweise einen Webpack-Dev-Server lokal starten und dann über den Webpack-Dev-Server auf den täglichen Server zugreifen möchten und die Adresse des täglichen Servers 11.160.119.131 lautet, können Sie dies durch die folgende Konfiguration abschließen: devServer: { Port: 8000, Proxy: { "/msg/show.htm": { Ziel: "http://11.160.119.131/", sicher: falsch } } } Wenn zu diesem Zeitpunkt „/msg/show.htm“ angefordert wird, lautet die tatsächlich angeforderte URL-Adresse „http//11.160.119.131/msg/show.htm“. (3) In der Entwicklungsumgebung ist ein Problem aufgetreten. Wenn der lokale devServer unter "http://30.11.160.255:8000/" oder dem häufigeren "http://0.0.0.0:8000/" gestartet wurde, gab der echte Server eine URL zurück, die eine Anmeldung anfordert. Das Starten des lokalen devServers auf localhost würde dieses Problem jedoch nicht verursachen (ein möglicher Grund ist, dass localhost die vom Backend benötigten Cookies hat, andere Domänennamen jedoch nicht, was dazu führt, dass der Proxyserver beim Zugriff auf den regulären Server nicht über die entsprechenden Cookies verfügt und daher eine Berechtigungsüberprüfung erforderlich ist). Die Angabe von localhost erfolgt über wcf Zur Vervollständigung, da WCF standardmäßig IP- oder Localhost-Zugriff unterstützen kann. Dies kann natürlich auch durch Hinzufügen des folgenden Codes erfolgen: devServer: { Port: 8000, Gastgeber:'localhost', Proxy: { "/msg/show.htm": { Ziel: "http://11.160.119.131/", sicher: falsch } } } (4) In Bezug auf das Prinzip von webpack-dev-server können Leser Informationen wie „Warum wird der Reverse-Proxy als Reverse-Proxy bezeichnet“ lesen, um mehr zu erfahren. Tatsächlich können Forward-Proxy und Reverse-Proxy in einem Satz zusammengefasst werden: „Der Forward-Proxy verbirgt den realen Client, während der Reverse-Proxy den realen Server verbirgt.“ Der Webpack-Dev-Server spielt tatsächlich die Rolle eines Proxyservers. Es gibt keine gemeinsame Same-Origin-Policy zwischen den Servern. Wenn der Webpack-Dev-Server angefordert wird, fordert er Daten vom realen Server an und sendet die Daten dann an Ihren Browser. Browser => localhost:8080 (Webpack-Dev-Server ohne Proxy) => http://you.test.com Browser => localhost:8080 (Webpack-Dev-Server hat einen Proxy) => http://you.test.com Der erste Fall oben ist der Fall ohne Proxy. Wenn die Seite bei localhost:8080 über die Front-End-Richtlinie auf http://you.test.com zugreift, gibt es eine Same-Origin-Richtlinie, d. h. der zweite Schritt besteht darin, über die Front-End-Richtlinie auf eine andere Adresse zuzugreifen. Im zweiten Fall wird der zweite Schritt jedoch tatsächlich über den Proxy ausgeführt, d. h. die Kommunikation zwischen Servern, und es gibt kein Same-Origin-Policy-Problem. Stattdessen greifen wir direkt auf den Proxyserver zu, der eine Seite zurückgibt. Einige Front-End-Anfragen (Proxy, Konfiguration neu schreiben), die bestimmte Bedingungen auf der Seite erfüllen, werden alle vom Proxyserver ausgeführt. Auf diese Weise wird das Same-Origin-Problem mithilfe des Proxyservers gelöst. (5) Oben wird der Fall beschrieben, in dem das Ziel eine IP ist. Wenn das Ziel als Domänenname angegeben werden soll, kann es erforderlich sein, den Host zu binden. Beispielsweise ist der Host unten gebunden: devServer: { Port: 8000, Proxy: { "/msg/show.htm": { Ziel: "http://youku.min.com/", sicher: falsch } } } Dies ist genau dasselbe wie das Binden des Ziels an eine IP-Adresse. Um es in einem Satz zusammenzufassen: „Ziel gibt an, welchem Host die Anforderung entsprechen soll, die eine bestimmte URL erfüllt, also der tatsächlichen Hostadresse, auf die der Proxyserver zugreifen soll.“ Proxy: { '/irgendein/Pfad': { Ziel: 'https://other-server.example.com', sicher: falsch, Bypass: Funktion (Anforderung, Res, Proxy-Optionen) { wenn (req.headers.accept.indexOf('html') !== -1) { console.log('Proxy für Browseranforderung überspringen.'); gibt '/index.html' zurück; } } } } Anfragen an den Proxy können auch überschrieben werden, indem eine Funktion bereitgestellt wird, die die HTTP-Anfrage prüfen oder ändern kann. Das folgende Beispiel schreibt die HTTP-Anfrage neu. Seine Hauptfunktion besteht darin, den /api-Teil vor der URL zu entfernen. Proxy: { '/api': { Ziel: 'https://other-server.example.com', Pfad neu schreiben: {'^/api' : ''} } } Die PathRewrite-Konfiguration stammt von der http-proxy-middleware. Weitere Konfigurationen können angezeigt werden Offizielle Dokumentation zu http-Proxy-Middleware. Option historyApiFallbackWenn Sie die History-API von HTML 5 verwenden, möchten Sie möglicherweise index.html als angeforderte Ressource verwenden, wenn ein 404-Fehler auftritt. In diesem Fall können Sie diese Konfiguration verwenden: historyApiFallback:true. Wenn Sie jedoch output.publicPath ändern, müssen Sie die Umleitungs-URL angeben. Sie können die Option historyApiFallback.index verwenden. // Ausgabe.öffentlicher Pfad: '/foo-app/' historyApiFallback: { Index: "/foo-app/" } Verwenden Sie die Umschreiboption, um statische Ressourcen zurückzusetzen historyApiFallback: { schreibt um: [ // zeigt views/landing.html als Zielseite an { von: /^\/$/, nach: '/views/landing.html' }, // zeigt views/subpage.html für alle Routen, die mit /subpage beginnen { von: /^\/Unterseite/, nach: '/views/Unterseite.html' }, // zeigt views/404.html auf allen anderen Seiten { von: /./, nach: '/views/404.html' }, ], }, Verwenden Sie disableDotRule, um die Anforderung zu erfüllen, dass, wenn eine Ressourcenanforderung eine wenn (parsedUrl.pathname.indexOf('.') !== -1 && options.disableDotRule !== true) { Logger( 'Nicht umschreiben', Anforderungsmethode, erforderliche URL, „weil der Pfad ein Punktzeichen (.) enthält.“ ); nächstes zurückgeben(); } rewriteTarget = Optionen.index || '/index.html'; logger('Umschreiben', req.method, req.url, 'to', rewriteTarget); req.url = Umschreibziel; nächste(); }; Das heißt, wenn es sich um eine Anforderung für eine absolute Ressource handelt, die also dotRule erfüllt, aber disableDotRule (Deaktivieren der DotRule-Dateianforderung) falsch ist, bedeutet das, dass wir die Ressourcen, die dotRule erfüllen, selbst verarbeiten, sodass sie nicht an index.html weitergeleitet werden müssen! Wenn disableDotRule wahr ist, bedeutet dies, dass Ressourcen, die die dotRule erfüllen, nicht verarbeitet werden und daher direkt zu index.html weitergeleitet werden! Geschichte({ disableDotRule: true }) Weitere Webpack-Dev-Server-Konfigurationvar server = neuer WebpackDevServer(compiler, { contentBase: "/Pfad/zum/Verzeichnis", //Inhaltsbasiskonfiguration hot: true, // HMR aktivieren, und webpack-dev-server sendet eine „webpackHotUpdate“-Nachricht an den Clientcode historyApiFallback: false, //Single-Page-Anwendung 404 leitet zu index.html weiter komprimieren: wahr, // GZIP-Komprimierung des Ressourcen-Proxys aktivieren: { "**": "http://localhost:9090" }, //Proxy-Konfiguration von http-proxy-middleware setup: funktion(app) { //webpack-dev-server selbst ist ein Express-Server, der seine eigenen Routen hinzufügen kann // app.get('/some/path', function(req, res) { // res.json({ benutzerdefiniert: 'Antwort' }); // }); }, //Parameter für die express.static-Methode des Express-Servers konfigurieren http://expressjs.com/en/4x/api.html#express.static statischeOptionen: { }, //Im Inline-Modus wird es verwendet, um die im Browser ausgegebene Protokollebene zu steuern, z. B. „Fehler“, „Warnung“, „Info“ oder „Keine“. clientLogLevel: "info", //Keine Protokolle in der Konsole ausdrucken ruhig: falsch, //Startprotokoll nicht ausgeben noInfo: falsch, //webpack überwacht keine Dateiänderungen und kompiliert bei jeder Anforderung neu lazy: true, //Dateiname Dateiname: "bundle.js", // Überwachungskonfiguration von webpack, wie viele Sekunden zum Überprüfen von Dateiänderungen benötigt werden watchOptions: { AggregateTimeout: 300, Umfrage: 1000 }, //Virtuelle Pfadzuordnung von output.path publicPath: "/assets/", //Benutzerdefinierte HTTP-Header festlegen: { "X-Custom-Header": "yes" }, //Paketstatusinformationen Ausgabekonfiguration stats: { colors: true }, //Konfigurieren Sie die für https erforderlichen Zertifikate: { cert: fs.readFileSync("Pfad zur Zertifikatsdatei.pem"), Schlüssel: fs.readFileSync("Pfad zur Schlüsseldatei.pem"), cacert: fs.readFileSync("Pfad zur cacert-Datei.pem") } }); server.listen(8080, "localhost", Funktion() {}); // server.close(); Die anderen Konfigurationen oben sind leicht zu verstehen, mit Ausnahme von Dateiname und Lazy. Lassen Sie uns weiterhin die spezifischen Verwendungsszenarien von Lazy und Dateiname analysieren. Wir wissen, dass der webpack-dev-server in der Lazy-Phase die Methode compiler.watch nicht aufruft, sondern vor dem Kompilieren auf das Eintreffen der Anforderung wartet. Der Quellcode lautet wie folgt: startWatch: Funktion() { var Optionen = Kontext.Optionen; var Compiler = Kontext.Compiler; // fang an zu schauen wenn(!optionen.lazy) { var watching = compiler.watch(optionen.watchOptionen, share.handleCompilerCallback); Kontext.beobachten = beobachten; //context.watching holt das Watching-Objekt so zurück, wie es ist} else { //Wenn es faul ist, bedeutet das, dass wir nicht beobachten, sondern kompilieren, wenn angefordert.context.state = true; } } Beim Aufruf von Rebuild wird context.state überprüft. Nach jeder Neukompilierung wird context.state in compiler.done! auf true zurückgesetzt. neu erstellen: Funktion neu erstellen() { //Wenn kein Stats-Objekt durch compiler.done generiert wurde, setze forceRebuild auf true //Wenn Statistiken vorhanden sind, die darauf hinweisen, dass es schon einmal erstellt wurde, rufen Sie die Run-Methode auf, wenn (context.state) { Kontext.Status = falsch; //Im Lazy-State ist context.state true, neu erstellen Kontext.Compiler.Run(share.handleCompilerCallback); } anders { Kontext.forceRebuild = wahr; } }, So rufen wir den oben beschriebenen Neuaufbau auf, um mit der Neukompilierung fortzufahren, wenn eine Anforderung eingeht: handleRequest: Funktion(Dateiname, ProzessRequest, req) { // im Lazy-Modus, bei Bundle-Anforderung neu erstellen wenn(context.options.lazy && (!context.options.filename || context.options.filename.test(filename))) teilen.neu erstellen(); //Wenn der Dateiname einen Hash enthält, dann lesen Sie den Dateinamen über das FS aus dem Speicher und der Rückruf dient dazu, die Nachricht direkt an den Client zu senden!!! if(HASH_REGEXP.test(Dateiname)) { versuchen { wenn(context.fs.statSync(Dateiname).isFile()) { Prozessanforderung(); zurückkehren; } } Fang(e) { } } teilen.bereit(ProzessAnforderung, req); //Die Callback-Funktion sendet das Dateiergebnis an den Client}, Unter diesen sendet processRequest die kompilierten Ressourcen direkt an den Client: Funktion ProzessAnfrage() { versuchen { var stat = context.fs.statSync(Dateiname); //Dateinamen abrufen if(!stat.isFile()) { wenn(stat.isDirectory()) { Dateiname = PfadJoin(Dateiname, Kontext.Optionen.Index || "index.html"); //Dateiname stat = context.fs.statSync(Dateiname); wenn(!stat.isFile()) "nächstes" werfen; } anders { wirf "nächstes"; } } } Fang(e) { goNext() zurückgeben; } // Serverinhalt // Wenn direkt auf die Datei zugegriffen wird, lesen Sie sie. Wenn es sich um einen Ordner handelt, greifen Sie auf den Ordner zu. var content = context.fs.readFileSync(filename); Inhalt = shared.handleRangeHeaders(Inhalt, Anforderung, Res); res.setHeader("Zugriffskontrolle-Origin zulassen", "*"); // Zur Unterstützung von XHR usw. res.setHeader("Inhaltstyp", mime.lookup(Dateiname) + "; Zeichensatz=UTF-8"); res.setHeader("Inhaltslänge", Inhalt.Länge); if (Kontext.Optionen.Header) { für (Variablenname in Kontext.Optionen.Header) { res.setHeader(Name, Kontext.Optionen.Header[Name]); } } // Express setzt den StatusCode automatisch auf 200, aber nicht alle Server tun dies (Koa). res.statusCode = res.statusCode || 200; wenn(res.send) res.send(Inhalt); sonst res.end(content); } } Wenn wir im Lazy-Modus den Dateinamen nicht angeben, d. h. jede Anforderung bezieht sich auf die Webpack-Ausgabedatei (den Chunk), wird diese jedes Mal neu erstellt! Ist jedoch ein Dateiname angegeben, wird dieser erst neu aufgebaut, wenn auf den Dateinamen zugegriffen wird! Damit ist dieser Artikel über die Kernkonzepte und Fälle von webpack-dev-server abgeschlossen. Weitere relevante Kerninhalte zu webpack-dev-server finden Sie in den vorherigen Artikeln von 123WORDPRESS.COM oder in den folgenden verwandten Artikeln. Ich hoffe, dass jeder 123WORDPRESS.COM in Zukunft unterstützen wird! Das könnte Sie auch interessieren:
|
<<: So erstellen Sie Benutzer und verwalten Berechtigungen in MySQL
>>: MySQL-Vorkompilierung in einem Artikel verstehen
1. Um das Web responsive zu entwickeln, muss sich...
Bei der Entwicklung von Webprojekten verweisen wi...
1. Was ist In react Anwendungen werden Ereignisna...
Inhaltsverzeichnis 1. Übersicht 1. Einführung ins...
Inhaltsverzeichnis 1. Konzept 1.1 Definition 1.2 ...
In Unternehmen hat die hohe Verfügbarkeit von Dat...
In horizontaler Richtung können Sie die Ausrichtu...
Kontroverse um Nofollow Zwischen Zac und Guoping ...
Inhaltsverzeichnis Ziele für diesen Zeitraum 1. F...
Erstens: Starten und stoppen Sie den MySQL-Dienst...
Senden von E-Mails mit der Mail-Funktion von PHP ...
Schnelles Lesen Warum müssen wir SQL-Anweisungen ...
Inhaltsverzeichnis Grundlegende Konzepte von Dock...
Ich habe verschiedene große Websites durchsucht u...
Inhaltsverzeichnis 1. Beziehung zwischen übergeor...