Was ist `require.context`?

74

Webpack-Dokumente

Mit der Funktion require.context () können Sie Ihren eigenen Kontext erstellen.

Großartig. Was ist ein "Kontext"? Was macht das eigentlich?

Sie können ein zu durchsuchendes Verzeichnis übergeben, ein Flag, das angibt, ob auch Unterverzeichnisse durchsucht werden sollen, und einen regulären Ausdruck, mit dem Dateien abgeglichen werden.

Erlaubt mir "suchen"? Suche nach Dateien, von denen ich annehme, und was dann? Was macht diese Funktion letztendlich? Was wird es verwendet?

GN.
quelle
und dann was? Was hängt dann davon ab, was Sie in Ihrer Webpack-Konfigurationsdatei angegeben haben. Was Sie aus der Dokumentation zitiert haben, klingt für mich klar. Es ermöglicht Ihnen anzugeben, von wo aus die Dateien gesammelt und die Importe und andere Flags aufgelöst werden sollen, um den Prozess zu unterstützen
Meme Composer

Antworten:

73

Eines der wichtigsten Merkmale der Compiler webpack des rekursiv alle Module zu analysieren, aus den Einträgen starten, eine grafische Darstellung aller Modulabhängigkeiten durch die Analyse zu bauen require(), require.context(), importund import()Ausdrücke.

Die übliche Interpretation von "Kontext" in Webpack und ähnlich in Node.js ist ein Verzeichnis, das als Basis für die Auflösung von Pfaden zu Modulen verwendet wird. Beispielsweise wird das aktuelle Arbeitsverzeichnis als Standardkontext für das Webpack verwendet, um den tatsächlichen Pfad zum Eingabemodul aufzulösen index.js. Der Kontext für die Anfrage require.resolve('../../../foo.js')ist __dirname.

require.contextist eine spezielle Funktion, die vom Webpack-Compiler unterstützt wird und es Ihnen ermöglicht, alle passenden Module ab einem Basisverzeichnis abzurufen. Das Webpack soll zur Kompilierungszeit angewiesen werden, diesen Ausdruck in eine dynamische Liste aller möglichen übereinstimmenden Modulanforderungen umzuwandeln, die aufgelöst werden können. Diese wiederum werden als Build-Abhängigkeiten hinzugefügt und können zur Laufzeit angefordert werden.

Kurz gesagt, Sie würden require.contextgenau die gleiche Situation verwenden, wenn Sie in Node.js zur Laufzeit Globs verwenden würden, um dynamisch eine Liste der erforderlichen Modulpfade zu erstellen. Der Rückgabewert ist ein aufrufbares Objekt, das sich wie require verhält und dessen Schlüssel die erforderlichen Modulanforderungsdaten enthalten, die als Argument für das Modul an das Modul übergeben werden können.

Es gibt verschiedene Möglichkeiten, wie Sie es verwenden können, aber ich denke, die beiden häufigsten Anwendungsfälle bestehen darin, entweder automatisch eine bekannte Art von Modulen zu erfordern (z. B. fügen Sie einfach ein some.test.jsTestmodul hinzu und in einem Modul verwenden Sie, require.contextum alle Tests dynamisch zu ermitteln). Sie müssen also nicht jedes Mal, wenn Sie ein neues Testmodul hinzufügen, dokumentieren und daran denken, dies manuell zu tun oder statische Assets in das Repository zu laden, um Dateien an die Build-Ausgabe zu senden (neue Webpack-Benutzer, die von anderen Build-Tools stammen, sind normalerweise überrascht, dass ihre Images , Schriftarten, Audiodateien und andere Elemente werden in der Ausgabe nur angezeigt, wenn sie von einem Modul benötigt werden.

Filip Dupanović
quelle
23

Hier ist ein praktisches, aber langes Beispiel. Ich werde Ihnen zeigen, wie Sie HTML-Fragmente aus einem Ordner laden und mit Webpack und auf eine Seite ausgebenrequire.context().

Es gibt heutzutage viele Möglichkeiten, eine Website mit Vorlagen und Vorlagensprachen zu erstellen: Sie haben handlebars, mustache, markdown, jasmine, JSX,und viele statische Generatoren, um damit umzugehen, wie z Eleventy, Hugo, Gatsby. Und das ist nicht zu vergessen die Wahl von Vanille-HTML oder einer Art Framework, wie z Vue.

Aber manchmal müssen Sie nur etwas HTML aus einigen Dateien holen und es auf eine Seite bringen. Es gibt eine Möglichkeit, HTML-Fragmente aus einem Ordner zu laden und sie mit Webpack und auf einer Seite auszugebenrequire.context().

Warum überhaupt require.context- oder HTML-Fragmente verwenden?

Wenn Sie eine Website oder sogar eine kleine Web-App erstellen möchten, gibt es wahrscheinlich einfachere, skalierbare Methoden.

Vor kurzem habe ich jedoch eine einfache UI-Bibliothek für Komponenten erstellt und wollte eine schnelle Möglichkeit, einfach HTML-Code abzurufen und in eine Endseite - oder eine Reihe von Seiten - aufzunehmen, um eine Live-Version der Bibliothek in Aktion anzuzeigen.

Die HTML-Dateien waren jedoch keine vollständigen Dokumente, sondern lediglich HTML-Fragmente, die eine bestimmte Komponente aus der Bibliothek gekapselt haben, um deren Markup anzuzeigen. Außerdem wollte ich, dass sie zur besseren Organisation im Projekt in separate Dateien in einem Ordner aufgeteilt werden. Das Hauptproblem dabei ist, einen zuverlässigen Weg zu finden, um alle Dateien zu erfassen, da sie Teile und nicht ganze HTML-Dokumente aufteilen und in einer logischen Reihenfolge abrufen, anstatt nur ein einziges Dokument zu haben.

Ich verwende Webpack, um alles zu bündeln und mich mit der CSS- und JS-Verarbeitung zu befassen. Daher war es sinnvoll, einen einfachen Weg zu finden, Webpack einzubeziehen , um diese Dateien abzurufen und zu verarbeiten. Es gibt natürlich auch andere Optionen, aber einige sind gar nicht so realisierbar ... Aber hier konzentrieren wir uns auf Webpack- basierte Lösungen

Webpack und require.context () zur Rettung!

Da wir Webpack bereits zum Erstellen dieses Dings verwenden, können wir eine der großartigen Funktionen von Webpack nutzen:require.context().

Konfigurieren Sie zuerst den HTML-Loader für die Verarbeitung unserer Dateien. Erstens müssen wir den HTML-Loader von Webpack installieren, da wir HTML-Dateien laden. eine leichte Leistung mit npm / Garn:

npm i -D html-loader or yarn add --dev html-loader

Von hier aus müssen wir die HTML-Loader-Konfiguration in unsere hinzufügen webpack.config.js

module: {
        rules: 
        [
            {
                test: /\.html$/,
                exclude: /node_modules/,
                use: {
                    loader: 'html-loader'
                }
            },
            ...
            {
            //other rules here
            }
        ]
      }

Jetzt kann Webpack HTML-Dateien für uns erkennen und verarbeiten, wenn wir Folgendes tun:

require('/path/to/html/file.html');

Aber das ist nur eine Datei, in die wir eine Menge laden müssen. Dies wird eine wachsende Liste sein - unpraktisch, wenn immer nur eine Zeile hinzugefügt wird.

Jetzt können wir HTML-Dateien require.context()laden und einige Dateien in einem Ordner laden und deren Inhalt verarbeiten.

Folgendes habe ich getan, um genau das zu erreichen:

// grab the element where we'll output the HTML to
const output = document.querySelector('#output');

// create a 'cache' where we can store our built up HTML from our fragments
let htmlFragmentCache = {};

// here, we're creating an anonymous function that loads up our HTML fragments
// then it adds them to our cache object
const importAll = requireContext => requireContext.keys().forEach(key => htmlFragmentCache[key] = requireContext(key));

// next, we call our importAll() function to load the files
// notice how this is where we call the require.context() function
// it uses our file path, whether to load subdirectories and what file type to get
importAll(require.context('./fragments', false, /.html$/));

// finally, we can loop over our cache's keys and add the HTML to our output element
Object.keys(htmlFragmentCache).forEach(key => output.innerHTML += htmlFragmentCache[key]);

Und so einfach ist das! Natürlich können auch diese wenigen Zeilen zu einer anonymen Funktion zusammengefasst werden (wirklich ein Beispiel für Immediately Invoked Function Expression or IIFE)ein noch saubereres und kürzeres Endergebnis:

(context => {
    // need to clear out the current element's contents (just in case!)
    output.innerHTML = '';

    // now, load up the html fragments and add them to the page
    context.keys().forEach(key => output.innerHTML += context(key));
})(require.context('./fragments', false, /.html$/));

Und da haben wir es. Eine wirklich saubere und einfache Methode zum Laden einer Reihe von HTML-Dateien in einem Ordner mithilfe require.context()einer JavaScript-Datei, die mit Webpack geladen, verarbeitet und gebündelt wird. Bosh!

Humoyun Ahmad
quelle
Ich erhalte Fehler require.context ist keine Funktion @Humoyun Ahmad
Vish
1
require.contextKönnen Sie weitere Informationen zu dem Fall bereitstellen ? Es reicht nicht aus, nur zu sagen, dass es nicht funktioniert: z. B. ist es eine Webpack-spezifische Funktion. Wenn Sie es also direkt mit Jest (Testen) verwenden, funktioniert es nicht. Sie müssen versuchen, es irgendwie zu verspotten
Humoyun Ahmad
Höchstwahrscheinlich versucht Vish, require.context außerhalb des Webpacks zu verwenden, höchstwahrscheinlich in einem Testskript. In diesem Fall muss es polygefüllt werden.
RichS