Wie funktioniert require () in node.js?

74

Ich habe es versucht:

// mod.js
var a = 1;
this.b = 2;
exports.c = 3;

// test.js
var mod = require('./mod.js');
console.log(mod.a);    // undefined
console.log(mod.b);    // 2
console.log(mod.c);    // 3, so this === exports?

Ich kann mir also vorstellen, dass require () folgendermaßen implementiert werden kann:

var require = function (file) {
    var exports = {};
    var run = function (file) {
        // include "file" here and run
    };
    run.apply(exports, [file]);
    return exports;
}

Ist das richtig? Bitte helfen Sie mir, require () zu verstehen, oder wo finde ich den Quellcode? Vielen Dank!

Trantor Liu
quelle

Antworten:

53

Der Quellcode ist hier . exports/ requiresind keine Schlüsselwörter, sondern globale Variablen. Ihr Hauptskript wird gewickelt , bevor Start in einer Funktion , die alle die Globals wie hat require, processetc in seinem Kontext.

Beachten Sie, dass während module.js selbst nutzt require(), das ist ein anderes erfordert Funktion, und es wird definiert in der Datei mit dem Namen „node.js“

Nebeneffekt von oben: Es ist vollkommen in Ordnung, eine "return" -Anweisung in der Mitte Ihres Moduls zu haben (die zu keiner Funktion gehört), die den Rest des Codes effektiv "auskommentiert"

Andrey Sidorov
quelle
Dies macht es nicht einfacher. Dieses Modul verwendet, requirewährend es auch definiert require. Das ist ein Schritt, den ich nur angesichts des Quellcodes ein wenig schwer zu verstehen finde.
polkovnikov.ph
Anforderung im Modul selbst ist eine andere Anforderung . Die vereinfachte Version des Moduls wurde für das Bootstrap-Modulsystem erstellt - sehen Sie sich den Code hier an - github.com/nodejs/node/blob/v4.0.0/src/node.js#L861-L949
Andrey Sidorov
Wo ist die Dokumentation für diese globale Variable und ihren Rückgabewert?
Srikan
@Srikan in offiziellen Dokumenten - nodejs.org/dist/latest-v8.x/docs/api/… (Ich bin nicht genau richtig beim Aufrufen von Exporten / benötige globale Variablen - normalerweise sind dies die Argumente für eine aufgerufene Wrapper-Funktion wenn Ihr Modul geladen ist)
Andrey Sidorov
1
@AlexanderMills es ist nicht gerade eine globale Variable, es kommt von der Tatsache, dass jedes Modul in eine Funktion eingeschlossen ist und requireals eines der Argumente an diese Funktion übergeben wird
Andrey Sidorov
8

Andrey zeigte den Quellcode, aber wenn Sie sich auch fragen, wie man ihn verwendet, finden Sie hier die einfache Erklärung ( http://nodejs.org/api/modules.html ).

Dies waren zwei gute Beispiele für mich.

//foo.js, multiple methods
var circle = require('./circle.js');
console.log( 'The area of a circle of radius 4 is ' + circle.area(4));

//circle.js
var PI = Math.PI;
exports.area = function (r) {
  return PI * r * r;
};
exports.circumference = function (r) {
  return 2 * PI * r;
};

//bar.js
var square = require('./square.js');
var mySquare = square(2);
console.log('The area of my square is ' + mySquare.area());

//square.js, single method
module.exports = function(width) {
  return {
    area: function() {
      return width * width;
    }
  };
}

Mein Lieblingsmuster ist

(function (controller) {

  controller.init = function (app) {

    app.get("/", function (req, res) {
        res.render("index", {});
    });

  };
})(module.exports);
Andy
quelle
Wenn Sie a definieren var express = require('express'), warum müssen sie danach eine andere Variable neu definieren als var app = express()?
TomSawyer
Ich
@ TomSawyer, weil require('express')eine Funktion zurückgeben, die eine App zurückgibt . Es ist nur so, wie sie es gebaut haben. Hoffentlich haben Sie diese Frage bereits beantwortet, seit Sie sie vor 4 Jahren gestellt haben.
Eric Jeker
6
var mod = require('./mod.js');

Die Anforderung ist eine Funktion, die ein Argument namens Pfad akzeptiert. In diesem Fall ist der Pfad ./mod.js

Wenn die Anforderung aufgerufen wird, werden eine Reihe von Aufgaben ausgeführt:

  1. AnruffunktionModule.prototype.require deklariert in lib / module.js die behaupten , dass der Pfad vorhanden ist und war ein String

  2. Aufruf, Module._loadder eine Funktion in lib / module.js ist , die die Datei durch auflöstModule._resolveFilename(request, parent, isMain) ,

  3. Die Module._resolveFilenameFunktion wird aufgerufen und prüft, ob das Modul nativ ist (die nativen Module werden von NativeModuleder in lib / internal / bootstrap_node.js definierten Funktion zurückgegeben ). Wenn ja, wird das Modul zurückgegeben, andernfalls wird die Anzahl der Zeichen des Parh überprüft (Muss 2) Zeichen mindestens) und einige Zeichen (der Pfad muss von gestartet werden ./) über Module._resolveLookupPathsdie in lib / internal / bootstrap_node.js definierte Funktion
  4. Überprüfen Sie das Verzeichnis, das die Datei enthält
  5. Wenn der Pfad eine Erweiterung enthält (in unserem Beispiel yes: mod.js), überprüft die in lib / path.js definierte Basisnamenfunktion , ob die Erweiterung " js " ist.
  6. Anschließend wird ein neues Modul für die im Argument angegebene Datei erstellt var module = new Module(filename, parent);
  7. Der Inhalt wird über v8 über die NativeModule.prototype.compilein lib / internal / bootstrap_node.js definierte Funktion kompiliert
  8. Das NativeModule.wrapin lib / internal / bootstrap_node.js definierte Element verwendet den kompilierten Javascript-Inhalt mod.jsund verpackt ihn: Es verpackt ihn in einen anderen Code, mit dem all dies funktioniert. Der Code, den Sie geschrieben haben, mod.jswird also in einen Funktionsausdruck eingeschlossen. Das bedeutet, dass alles, was Sie in Node schreiben, in V8 ausgeführt wird
  9. Ein module.exports wird zurückgegeben
Mohamed Ben HEnda
quelle
0

Ich grabe ein bisschen mehr von nodejs Quellcode / 2 / und mache ein Sequenzdiagramm / 1 /, hoffe, dies könnte Ihnen einen intuitiven Überblick geben. Es gibt einen weiteren Artikel http://fredkschott.com/post/2014/06/require-and-the-module-system/, in dem auch der require () -Mechanismus auf einfache Weise erläutert wird. Lesen Sie zuerst diesen Artikel, um Hilfe zu erhalten Verstehe das Diagramm schnell. Geben Sie hier die Bildbeschreibung ein

Ref:

/ 1 / Diagrammquellen-Repo: https://github.com/z1yuan/nodejs.git

/ 2 / https://github.com/nodejs/node-v0.x-archive.git

Zhi Yuan
quelle
-9

Die Quelle finden Sie hier neben den Downloads: http://nodejs.org/ export / require sind Schlüsselwörter, ich glaube nicht, dass sie direkt in Javascript codiert sind. Der Knoten ist in C ++ codiert, Javascript ist nur eine Skript-Shell um den C ++ - Kern.

mpm
quelle
Wenn Sie nur "denken" oder raten, ist es besser, keine Fragen zu beantworten. Wenn ein Modul aus dem Dateisystem geladen und analysiert wird, wird es in eine Funktion eingeschlossen und von der v8-Engine kompiliert. Schließlich wird das Modul zwischengespeichert. require, module, __filename, Etc. sind Funktionen und Variablen in das Modul nach der Kompilierung injizierten, und das Modul läuft im Rahmen v8 - Motors, aber das Modul selbst ist ein Verschluss, so Variablen und Funktionen nie in Konflikt gerieten werden (außer im Fall , dass Sie die globale Variable verwenden und Chaos.
Jone Polvora