Heim Web-Frontend js-Tutorial Ich habe einen Modul-Bundler geschrieben. Notizen usw

Ich habe einen Modul-Bundler geschrieben. Notizen usw

Jul 25, 2024 am 03:10 AM

I wrote a module bundler. notes, etc

Ich habe einen einfachen JavaScript-Bundler erstellt und es stellte sich heraus, dass er viel einfacher war, als ich erwartet hatte. Ich werde alles, was ich gelernt habe, in diesem Beitrag teilen.

Beim Schreiben großer Anwendungen empfiehlt es sich, unseren JavaScript-Quellcode in separate JS-Dateien aufzuteilen. Das Hinzufügen dieser Dateien zu Ihrem HTML-Dokument mithilfe mehrerer Skript-Tags führt jedoch zu neuen Problemen wie

  • Verschmutzung des globalen Namensraums.

  • Rennbedingungen.

Modul-Bundler kombinieren unseren Quellcode aus verschiedenen Dateien in einer großen Datei und helfen uns so, die Vorteile von Abstraktionen zu nutzen und gleichzeitig die Nachteile zu vermeiden.

Modul-Bundler erledigen dies im Allgemeinen in zwei Schritten.

  1. Suchen aller JavaScript-Quelldateien, beginnend mit der Eintragsdatei. Dies wird als Abhängigkeitsauflösung bezeichnet und die erzeugte Karte wird als Abhängigkeitsdiagramm bezeichnet.
  2. Verwenden des Abhängigkeitsdiagramms zum Generieren eines Bundles: eine große Zeichenfolge von JavaScript-Quellcode, die in einem Browser ausgeführt werden kann. Dies könnte in eine Datei geschrieben und mithilfe eines Skript-Tags zum HTML-Dokument hinzugefügt werden.

ABHÄNGIGKEITSAUFLÖSUNG

Wie bereits erwähnt, hier

  • Nehmen Sie eine Eintragsdatei,
  • Lesen und analysieren Sie den Inhalt,
  • Fügen Sie es zu einer Reihe von Modulen hinzu
  • finden Sie alle seine Abhängigkeiten (andere importierte Dateien),
  • Inhalte von Abhängigkeiten lesen und analysieren
  • Abhängigkeiten zum Array hinzufügen
  • Suchen Sie Abhängigkeiten von Abhängigkeiten und so weiter und so fort, bis wir zum letzten Modul kommen

So würden wir das machen (JavaScript-Code voraus)

Erstellen Sie eine bundler.js-Datei in Ihrem Texteditor und fügen Sie den folgenden Code hinzu:

const bundler = (entry)=>{
          const graph = createDependencyGraph(entry)

          const bundle = createBundle(graph)
          return bundle
}
Nach dem Login kopieren

Die Bundler-Funktion ist der Haupteintrag unseres Bundlers. Es nimmt den Pfad zu einer Datei (Eintragsdatei) und gibt eine Zeichenfolge (das Bundle) zurück. Darin wird mithilfe der Funktion „createDependencyGraph“ ein Abhängigkeitsdiagramm generiert.

const createDependencyGraph = (path)=>{
          const entryModule = createModule(path)

          /* other code */
}
Nach dem Login kopieren

Die Funktion createDependencyGraph übernimmt den Pfad zur Eintragsdatei. Es verwendet die Funktion „createModule“, um eine Moduldarstellung dieser Datei zu generieren.

let ID = 0
const createModule = (filename)=>{
          const content = fs.readFileSync(filename)
          const ast = babylon.parse(content, {sourceType: “module”})

          const {code} = babel.transformFromAst(ast, null, {
              presets: ['env']
            })

           const dependencies = [ ]
           const id = ID++
           traverse(ast, {
                   ImportDeclaration: ({node})=>{
                       dependencies.push(node.source.value)
                   }
            }
            return {
                           id,
                           filename,
                           code,
                           dependencies
                       }
}
Nach dem Login kopieren

Die Funktion „createAsset“ nimmt den Pfad zu einer Datei und liest deren Inhalt in einen String. Diese Zeichenfolge wird dann in einen abstrakten Syntaxbaum analysiert. Ein abstrakter Syntaxbaum ist eine Baumdarstellung des Inhalts eines Quellcodes. Es kann mit dem DOM-Baum eines HTML-Dokuments verglichen werden. Dadurch ist es einfacher, einige Funktionen des Codes auszuführen, z. B. das Durchsuchen usw.
Wir erstellen einen Ast aus dem Modul mit dem Babylon-Parser.

Als nächstes konvertieren wir mit Hilfe des Babel-Core-Transpilers den Codeinhalt in eine Syntax vor ES2015 für browserübergreifende Kompatibilität.
Anschließend wird der ast mit einer speziellen Funktion von babel durchlaufen, um jede Importdeklaration unserer Quelldatei (Abhängigkeiten) zu finden.

Wir verschieben diese Abhängigkeiten (bei denen es sich um Zeichenfolgen mit relativen Dateipfaden handelt) dann in ein Abhängigkeitsarray.

Außerdem erstellen wir eine ID, um dieses Modul eindeutig zu identifizieren und
Schließlich geben wir ein Objekt zurück, das dieses Modul darstellt. Dieses Modul enthält eine ID, den Inhalt unserer Datei im String-Format, ein Array von Abhängigkeiten und den absoluten Dateipfad.

const createDependencyGraph = (path)=>{
          const entryModule = createModule(path)

          const graph = [ entryModule ]
          for ( const module of graph) {
                  module.mapping = { }
module.dependencies.forEach((dep)=>{
         let absolutePath = path.join(dirname, dep);
         let child = graph.find(mod=> mod.filename == dep)
         if(!child){
               child = createModule(dep)
               graph.push(child)
         }
         module.mapping[dep] = child.id
})
          }
          return graph
}
Nach dem Login kopieren

Zurück in unserer Funktion createDependencyGraph können wir nun mit der Generierung unseres Diagramms beginnen. Unser Diagramm ist ein Array von Objekten, wobei jedes Objekt jede in unserer Anwendung verwendete Quelldatei darstellt.
Wir initialisieren unseren Graphen mit dem Eingabemodul und führen ihn dann in einer Schleife durch. Obwohl es nur ein Element enthält, fügen wir Elemente am Ende des Arrays hinzu, indem wir auf das Abhängigkeitsarray des Einstiegsmoduls (und anderer Module, die wir hinzufügen werden) zugreifen.

Das Abhängigkeitsarray enthält relative Dateipfade aller Abhängigkeiten eines Moduls. Das Array wird durchlaufen und für jeden relativen Dateipfad wird zunächst der absolute Pfad aufgelöst und zum Erstellen eines neuen Moduls verwendet. Dieses untergeordnete Modul wird an das Ende des Diagramms verschoben und der Prozess beginnt von vorne, bis alle Abhängigkeiten in Module konvertiert wurden.
Außerdem gibt jedes Modul ein Zuordnungsobjekt an, das einfach jeden relativen Abhängigkeitspfad der ID des untergeordneten Moduls zuordnet.
Für jede Abhängigkeit wird geprüft, ob bereits ein Modul vorhanden ist, um eine Duplizierung von Modulen und unendliche zirkuläre Abhängigkeiten zu verhindern.
Zum Schluss geben wir unseren Graphen zurück, der nun alle Module unserer Anwendung enthält.

BÜNDELN

Nachdem das Abhängigkeitsdiagramm erstellt wurde, umfasst die Erstellung eines Bundles zwei Schritte

  1. Wrapping each module in a function. This creates the idea of each module having its own scope
  2. Wrapping the module in a runtime.

Wrapping each module

We have to convert our module objects to strings so we can be able to write them into the bundle.js file. We do this by initializing moduleString as an empty string. Next we loop through our graph appending each module into the module string as key value pairs, with the id of a module being the key and an array containing two items: first, the module content wrapped in function (to give it scope as stated earlier) and second an object containing the mapping of its dependencies.

const wrapModules = (graph)=>{
         let modules = ‘’
           graph.forEach(mod => {
    modules += `${http://mod.id}: [
      function (require, module, exports) {
        ${mod.code}
      },
      ${JSON.stringify(mod.mapping)},
    ],`;
  });
return modules
}
Nach dem Login kopieren

Also to note, the function wrapping each module takes a require, export and module objects as arguments. This is because these don’t exist in the browser but since they appear in our code we will create them and pass them into these modules.

Creating the runtime

This is code that will run immediately the bundle is loaded, it will provide our modules with the require, module and module.exports objects.

const bundle = (graph)=>{
        let modules = wrapModules(graph)
        const result = `
    (function(modules) {
      function require(id) {
        const [fn, mapping] = modules[id];

        function localRequire(name) {
          return require(mapping[name]);
        }

        const module = { exports : {} };

        fn(localRequire, module, module.exports);

        return module.exports;
      }

      require(0);
    })({${modules}})`;
  return result;
}
Nach dem Login kopieren

We use an immediately invoked function expression that takes our module object as an argument. Inside it we define our require function that gets a module from our module object using its id.
It constructs a localRequire function specific to a particular module to map file path string to id. And a module object with an empty exports property
It runs our module code, passing the localrequire, module and exports object as arguments and then returns module.exports just like a node js module would.
Finally we call require on our entry module (index 0).

To test our bundler, in the working directory of our bundler.js file create an index.js file and two directories: a src and a public directory.

In the public directory create an index.html file, and add the following code in the body tag:

<!DOCTYPE html>
<html>
    <head>
        <title>Module bundler</title>
        <meta name="viewport" content="width=device-width, initial-scale=1" />
    </head>
    <body>
       <div id='root'></div>
       <script src= ‘./bundler.js> <script>
    </body>
</html

In the src directory create a name.js file and add the following code
Nach dem Login kopieren

const name = “David”
export default name

also create a hello.js file and add the following code
Nach dem Login kopieren

import name from ‘./name.js’
const hello = document.getElementById(“root”)
hello.innerHTML = “hello” + name

Lastly in the index.js file of the root directory import our bundler, bundle the files and write it to a bundle.js file in the public directory
Nach dem Login kopieren

const createBundle = require(“./bundler.js”)
const run = (output , input)=>{
let bundle = creatBundle(entry)
fs.writeFileSync(bundle, ‘utf-8’)
}
run(“./public/bundle.js”, “./src/hello.js”)


Open our index.html file in the browser to see the magic.

In this post we have illustrated how a simple module bundler works. This is a minimal bundler meant for understanding how these technologies work behind the hood.

please like if you found this insightful and comment any questions you may have.
Nach dem Login kopieren

Das obige ist der detaillierte Inhalt vonIch habe einen Modul-Bundler geschrieben. Notizen usw. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Erklärung dieser Website
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

Heiße KI -Werkzeuge

Undresser.AI Undress

Undresser.AI Undress

KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover

AI Clothes Remover

Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool

Undress AI Tool

Ausziehbilder kostenlos

Clothoff.io

Clothoff.io

KI-Kleiderentferner

Video Face Swap

Video Face Swap

Tauschen Sie Gesichter in jedem Video mühelos mit unserem völlig kostenlosen KI-Gesichtstausch-Tool aus!

Heißer Artikel

<🎜>: Bubble Gum Simulator Infinity - So erhalten und verwenden Sie Royal Keys
3 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌
Mandragora: Flüstern des Hexenbaum
3 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌
Nordhold: Fusionssystem, erklärt
3 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌

Heiße Werkzeuge

Notepad++7.3.1

Notepad++7.3.1

Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version

SublimeText3 chinesische Version

Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1

Senden Sie Studio 13.0.1

Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6

Dreamweaver CS6

Visuelle Webentwicklungstools

SublimeText3 Mac-Version

SublimeText3 Mac-Version

Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Heiße Themen

Java-Tutorial
1668
14
PHP-Tutorial
1273
29
C#-Tutorial
1255
24
JavaScript -Engines: Implementierungen vergleichen JavaScript -Engines: Implementierungen vergleichen Apr 13, 2025 am 12:05 AM

Unterschiedliche JavaScript -Motoren haben unterschiedliche Auswirkungen beim Analysieren und Ausführen von JavaScript -Code, da sich die Implementierungsprinzipien und Optimierungsstrategien jeder Engine unterscheiden. 1. Lexikalanalyse: Quellcode in die lexikalische Einheit umwandeln. 2. Grammatikanalyse: Erzeugen Sie einen abstrakten Syntaxbaum. 3. Optimierung und Kompilierung: Generieren Sie den Maschinencode über den JIT -Compiler. 4. Führen Sie aus: Führen Sie den Maschinencode aus. V8 Engine optimiert durch sofortige Kompilierung und versteckte Klasse.

Python vs. JavaScript: Die Lernkurve und Benutzerfreundlichkeit Python vs. JavaScript: Die Lernkurve und Benutzerfreundlichkeit Apr 16, 2025 am 12:12 AM

Python eignet sich besser für Anfänger mit einer reibungslosen Lernkurve und einer kurzen Syntax. JavaScript ist für die Front-End-Entwicklung mit einer steilen Lernkurve und einer flexiblen Syntax geeignet. 1. Python-Syntax ist intuitiv und für die Entwicklung von Datenwissenschaften und Back-End-Entwicklung geeignet. 2. JavaScript ist flexibel und in Front-End- und serverseitiger Programmierung weit verbreitet.

Von C/C nach JavaScript: Wie alles funktioniert Von C/C nach JavaScript: Wie alles funktioniert Apr 14, 2025 am 12:05 AM

Die Verschiebung von C/C zu JavaScript erfordert die Anpassung an dynamische Typisierung, Müllsammlung und asynchrone Programmierung. 1) C/C ist eine statisch typisierte Sprache, die eine manuelle Speicherverwaltung erfordert, während JavaScript dynamisch eingegeben und die Müllsammlung automatisch verarbeitet wird. 2) C/C muss in den Maschinencode kompiliert werden, während JavaScript eine interpretierte Sprache ist. 3) JavaScript führt Konzepte wie Verschlüsse, Prototypketten und Versprechen ein, die die Flexibilität und asynchrone Programmierfunktionen verbessern.

JavaScript und das Web: Kernfunktionalität und Anwendungsfälle JavaScript und das Web: Kernfunktionalität und Anwendungsfälle Apr 18, 2025 am 12:19 AM

Zu den Hauptanwendungen von JavaScript in der Webentwicklung gehören die Interaktion der Clients, die Formüberprüfung und die asynchrone Kommunikation. 1) Dynamisches Inhaltsaktualisierung und Benutzerinteraktion durch DOM -Operationen; 2) Die Kundenüberprüfung erfolgt vor dem Einreichung von Daten, um die Benutzererfahrung zu verbessern. 3) Die Aktualisierung der Kommunikation mit dem Server wird durch AJAX -Technologie erreicht.

JavaScript in Aktion: Beispiele und Projekte in realer Welt JavaScript in Aktion: Beispiele und Projekte in realer Welt Apr 19, 2025 am 12:13 AM

Die Anwendung von JavaScript in der realen Welt umfasst Front-End- und Back-End-Entwicklung. 1) Zeigen Sie Front-End-Anwendungen an, indem Sie eine TODO-Listanwendung erstellen, die DOM-Operationen und Ereignisverarbeitung umfasst. 2) Erstellen Sie RESTFUFFUPI über Node.js und express, um Back-End-Anwendungen zu demonstrieren.

Verständnis der JavaScript -Engine: Implementierungsdetails Verständnis der JavaScript -Engine: Implementierungsdetails Apr 17, 2025 am 12:05 AM

Es ist für Entwickler wichtig, zu verstehen, wie die JavaScript -Engine intern funktioniert, da sie effizientere Code schreibt und Leistungs Engpässe und Optimierungsstrategien verstehen kann. 1) Der Workflow der Engine umfasst drei Phasen: Parsen, Kompilieren und Ausführung; 2) Während des Ausführungsprozesses führt die Engine dynamische Optimierung durch, wie z. B. Inline -Cache und versteckte Klassen. 3) Zu Best Practices gehören die Vermeidung globaler Variablen, die Optimierung von Schleifen, die Verwendung von const und lass und die Vermeidung übermäßiger Verwendung von Schließungen.

Python gegen JavaScript: Community, Bibliotheken und Ressourcen Python gegen JavaScript: Community, Bibliotheken und Ressourcen Apr 15, 2025 am 12:16 AM

Python und JavaScript haben ihre eigenen Vor- und Nachteile in Bezug auf Gemeinschaft, Bibliotheken und Ressourcen. 1) Die Python-Community ist freundlich und für Anfänger geeignet, aber die Front-End-Entwicklungsressourcen sind nicht so reich wie JavaScript. 2) Python ist leistungsstark in Bibliotheken für Datenwissenschaft und maschinelles Lernen, während JavaScript in Bibliotheken und Front-End-Entwicklungsbibliotheken und Frameworks besser ist. 3) Beide haben reichhaltige Lernressourcen, aber Python eignet sich zum Beginn der offiziellen Dokumente, während JavaScript mit Mdnwebdocs besser ist. Die Wahl sollte auf Projektbedürfnissen und persönlichen Interessen beruhen.

Python vs. JavaScript: Entwicklungsumgebungen und Tools Python vs. JavaScript: Entwicklungsumgebungen und Tools Apr 26, 2025 am 12:09 AM

Sowohl Python als auch JavaScripts Entscheidungen in Entwicklungsumgebungen sind wichtig. 1) Die Entwicklungsumgebung von Python umfasst Pycharm, Jupyternotebook und Anaconda, die für Datenwissenschaft und schnelles Prototyping geeignet sind. 2) Die Entwicklungsumgebung von JavaScript umfasst Node.JS, VSCODE und WebPack, die für die Entwicklung von Front-End- und Back-End-Entwicklung geeignet sind. Durch die Auswahl der richtigen Tools nach den Projektbedürfnissen kann die Entwicklung der Entwicklung und die Erfolgsquote der Projekte verbessert werden.

See all articles