Maison  >  Article  >  interface Web  >  Une brève analyse du principe de fonctionnement de require dans Node.js_node.js

Une brève analyse du principe de fonctionnement de require dans Node.js_node.js

WBOY
WBOYoriginal
2016-05-16 16:43:121362parcourir

Presque tous les développeurs Node.js peuvent vous dire ce que fait la fonction require(), mais combien d'entre nous savent réellement comment cela fonctionne ? Nous l'utilisons quotidiennement pour charger des bibliothèques et des modules, mais son comportement reste un mystère pour nous.

Par curiosité, j'ai fouillé dans le code principal de Node pour découvrir ce qui se passait sous le capot. Mais ce n'est pas une fonction unique. J'ai trouvé module.js dans le système de modules du nœud. Ce fichier contient un module de base étonnamment puissant et relativement inconnu qui contrôle le chargement, la compilation et la mise en cache de chaque fichier. `require()`, son émergence n'est que la pointe de l'iceberg.

module.js

Copier le code Le code est le suivant :

fonction Module (id, parent) {
this.id = id;
this.exports = {};
this.parent = parent;
// ...

Module.js joue principalement deux rôles au sein de Node.js. Premièrement, il fournit une base pour tous les modules Node.js. Chaque fichier est une nouvelle instance d'un module de base qui persiste même après l'exécution du fichier. C'est pourquoi nous pouvons attacher des attributs à module.exports et les renvoyer en cas de besoin.

La deuxième tâche majeure de ce module est de gérer le mécanisme de chargement du module du nœud. La fonction d'opération indépendante "require" que nous utilisons est en fait un concept abstrait de module.require, qui lui-même n'est qu'une simple encapsulation de la fonction Module._load. Cette méthode de chargement gère le chargement réel de chaque fichier et commence notre voyage là-bas.

Module._load

Copier le code Le code est le suivant :

Module._load = function (requête, parent, isMain) {
// 1. Vérifiez Module._cache pour le module mis en cache
// 2. Créez une nouvelle instance de module si le cache est vide.
// 3. Enregistrez-le dans le cache.
// 4. Appelez module.load() avec le nom de fichier donné.
// Cela appellera module.compile() après avoir lu le contenu du fichier.
// 5. S'il y a eu une erreur lors du chargement/analyse du fichier,
// Supprime le mauvais module du cache
// 6. retourner module.exports
};

Module._load est responsable du chargement des nouveaux modules et de la gestion du cache des modules. La mise en cache de chaque module chargé réduit le nombre de lectures de fichiers redondantes et peut considérablement accélérer votre application. De plus, les instances de module partagées permettent aux fonctionnalités singleton des modules de rester dans l'état du projet.

Si un module n'existe pas dans le cache, Module._load créera un nouveau module de base de ce fichier. Il indique ensuite au module de lire le contenu des nouveaux fichiers avant de les envoyer à module._compile. [1]

Si vous remarquez l'étape 6 ci-dessus, vous verrez que module.exports a été renvoyé à l'utilisateur. C'est pourquoi lorsque vous définissez une interface publique à utiliser, vous utilisez exports et module.exports, car Module._load renverra ensuite le contenu requis. Je suis surpris qu'il n'y ait pas plus de fonctionnalités ici, mais ce serait bien s'il y en avait.

module._compile

Copier le code Le code est le suivant :

Module.prototype._compile = function(contenu, nom de fichier) {
// 1. Créez la fonction require autonome qui appelle module.require.
// 2. Attachez d'autres méthodes d'assistance à exiger.
// 3. Encapsule le code JS dans une fonction qui fournit notre require,
// module, etc. variables localement dans la portée du module.
// 4. Exécutez cette fonction
};

· C'est là que la vraie magie opère. Tout d’abord, une fonction require autonome spéciale est créée pour ce module. Il s’agit d’une fonctionnalité dont nous avons tous besoin et que nous connaissons bien. La fonction elle-même n'est qu'un package dans Module.require, et elle contient également quelques méthodes auxiliaires peu connues et faciles à utiliser :

· require() : Charger un module externe
· require.resolve() : Résout un nom de module en son chemin absolu
· require.main:module principal
· require.cache : tous les modules mis en cache
· ·require.extensions : Les méthodes de compilation disponibles pour chaque type de fichier valide selon son extension

Une fois require prêt, l'intégralité du code source chargé est encapsulé dans une nouvelle fonction qui peut accepter require, module, exports et toutes les autres variables exposées comme paramètres. Il s'agit d'une fonction créée uniquement pour encapsuler le module afin d'éviter les conflits avec l'environnement Node.js.

Copier le code Le code est le suivant :

(fonction (exports, require, module, __filename, __dirname) {
// VOTRE CODE INJECTÉ ICI !
});

La méthode Module._compile est exécutée de manière synchrone, donc l'appel à Module._load ne peut qu'attendre la fin de ce code et renvoyer module.exprts à l'utilisateur.

Conclusion

Nous avons donc compris l'intégralité du code de require et avons une première compréhension de son fonctionnement.

Si vous avez suivi tout cela, alors vous êtes prêt pour le dernier secret : require('module'). C'est vrai, le système de modules lui-même peut être chargé via le système de modules. Création. Cela peut paraître étrange, mais cela permet à l'espace utilisateur d'interagir avec le système de chargement des modules sans avoir à se plonger dans le noyau de Node.js. Les modules populaires sont construits comme ceci. [2]

Si vous souhaitez en savoir plus, consultez vous-même le code source du module.js. Il y a suffisamment de choses pour vous donner mal à la tête pendant un moment. Le premier peut-il me dire ce qu'est NODE_MODULE_CONTEXTS" et pourquoi il est ajouté et les personnes qui l'ajoutent peuvent obtenir des points bonus :)

[1] La méthode module._compile est uniquement utilisée pour exécuter des fichiers JavaScript. Les fichiers JSON doivent être analysés via JSON.parse() et renvoyés

[2] Cependant, les deux modules sont construits sur des méthodes de module privées telles que Module._resolveLookupPaths et Module._findPath. On peut penser que ce n'est pas beaucoup mieux...

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn