Maison >interface Web >js tutoriel >Comprendre le système de modules dans Node.js
Recommandations associées : "Tutoriel node js"
JavaScript en A simple Un langage de script permettant d'ajouter des fonctions interactives aux pages Web est sorti. Au début, il n'incluait pas de système de modules. Alors que JavaScript résolvait des problèmes de plus en plus complexes, l'écriture de tous les codes dans un seul fichier et l'utilisation de fonctions pour distinguer les unités fonctionnelles ne pouvaient plus être prises en charge. le développement d'applications complexes. Oui, ES6 apporte des classes et des modules communs à la plupart des langages de haut niveau, permettant aux développeurs d'organiser plus facilement le code
import _ from 'lodash'; class Fun {} export default Fun;
Les trois lignes de code ci-dessus montrent les deux éléments les plus importants d'un système de module, importation et exportation
export
Utilisé pour spécifier l'interface externe du module
import
Utilisé pour saisir les fonctions fournis par d'autres modules
Avant ES6, de nombreuses solutions de chargement de modules sont apparues dans la communauté, les plus importantes étant CommonJS et AMD. Node.js est né avant ES6, et le système de modules. utilisé une implémentation similaire à CommonJS, suivant plusieurs principes
Un fichier est un module, et la portée de la variable dans le fichier est dans le module
Utilisez l'objet module.exports
pour exporter l'interface externe du module
Utilisez require
pour introduire d'autres modules
circle.js
const { PI } = Math; module.exports = function area(r) { PI * r ** 2; };
Le code ci-dessus implémente un module de Node.js , le module ne dépend pas des autres modules et exporte la méthode area
pour calculer l'aire d'un cercle
test.js
const area = require('./circle.js'); console.log(`半径为 4 的圆的面积是 ${area(4)}`);
Le module s'appuie sur circle.js et utilise sa méthode de zone exposée pour calculer le cercle L'aire de
L'interface externe exposée du module utilise module.exports. Il existe deux usages courants : y ajouter des attributs ou attribuer des valeurs à de nouveaux objets test.js
// 添加属性 module.exports.prop1 = xxx; module.exports.funA = xxx; module.exports.funB = xxx; // 赋值到全新对象 module.exports = { prop1, funA, funB, };
Les deux manières d'écrire sont équivalentes, et il n'y a pas de différence quand en les utilisant
const mod = require('./test.js'); console.log(mod.prop1); console.log(mod.funA());
Il existe une autre façon d'utiliser directement l'objet exports
, mais vous ne pouvez lui ajouter que des attributs et ne pouvez pas l'attribuer à un nouvel objet, la raison sera introduite plus tard
// 正确的写法:添加属性 exports.prop1 = xxx; exports.funA = xxx; exports.funB = xxx; // 赋值到全新对象 module.exports = { prop1, funA, funB, };
l'utilisation de require est relativement simple, id prend en charge deux types : nom du module et chemin du fichier
const fs = require('fs'); const _ = require('lodash');
Le fs et lodash dans l'exemple sont tous deux des noms de module. fs est le module principal intégré de Node.js, et lodash est un module tiers installé sous node_modules
via npm s'il apparaît. le nom est le même, privilégiez l'utilisation des modules intégrés au système
Parce qu'un projet peut contenir plusieurs dossiers node_modules (conception relativement ratée de Node.js), le processus de recherche de modules tiers suivra le principe de proximité et remontez couche par couche (vous pouvez imprimer module.paths
dans le programme pour afficher le chemin de recherche spécifique) jusqu'à ce que le répertoire racine du système de fichiers soit trouvé selon la variable d'environnement NODE_PATH
Pour le processus spécifique, veuillez vous référer. vers la documentation officielle
De plus, Node.js recherchera également la liste du répertoire global suivante :
où $HOME
est le répertoire personnel de l'utilisateur et $PREFIX
est le node_prefix
configuré dans Node.js. Il est fortement recommandé de placer toutes les dépendances dans le répertoire node_modules local, qui se chargera plus rapidement et sera plus fiable
Les modules peuvent également être chargés en utilisant les chemins de fichiers. C'est le projet. méthode générale de chargement des modules personnalisés dans le module, l'extension du chemin peut être omise et le chemin sera essayé dans l'ordre de .js, .json et .node
'/'
sont les chemins absolus des fichiers. Rechercher les modules en fonction du chemin système './'
sont relatifs au fichier appelant actuellement la méthode require et ne sont pas affectés par l'endroit où les modules suivants sont utilisés seront mis en cache dans Module._cache
après le premier chargement. Si chaque appel à require('foo')
aboutit au même fichier, le même objet sera mis en cache. sera renvoyé et Ne provoquera pas l'exécution multiple du code du module. Node.js met en cache les modules en fonction de leurs noms de fichiers réels, de sorte que le même module n'est pas chargé deux fois lorsqu'il est référencé à partir de répertoires différents. require(foo)
a.js
console.log('a 开始'); exports.done = false; const b = require('./b.js'); console.log('在 a 中,b.done = %j', b.done); exports.done = true; console.log('a 结束');
b.js
console.log('b 开始'); exports.done = false; const a = require('./a.js'); console.log('在 b 中,a.done = %j', a.done); exports.done = true; console.log('b 结束');
:main.js
console.log('main 开始'); const a = require('./a.js'); const b = require('./b.js'); console.log('在 main 中,a.done=%j,b.done=%j', a.done, b.done);Lorsque main.js charge a.js, a.js charge b.js À ce moment, b.js essaiera de charger a.jsAfin d'éviter. boucles infinies Renvoie une
copie inachevée de l'objet d'exportation de a.js au module b.js, puis b.js termine le chargement et fournit l'objet d'exportation au module a.js
Ainsi, le exemple La sortie de estmain 开始 a 开始 b 开始 在 b 中,a.done = false b 结束 在 a 中,b.done = true a 结束 在 main 中,a.done=true,b.done=true
看不懂上面的过程也没关系,日常工作根本用不到,即使看懂了也不要在项目中使用循环依赖!
Node.js 每个文件都是一个模块,模块内的变量都是局部变量,不会污染全局变量,在执行模块代码之前,Node.js 会使用一个如下的函数封装器将模块封装
(function(exports, require, module, __filename, __dirname) { // 模块的代码实际上在这里 });
回头看看最开始的问题,为什么 exports 对象不支持赋值为其它对象?把上面函数添加一句 exports 对象来源就很简单了
const exports = module.exports; (function(exports, require, module, __filename, __dirname) { // 模块的代码实际上在这里 });
其它模块 require 到的肯定是模块的 module.exports 对象,如果吧 exports 对象赋值给其它对象,就和 module.exports 对象断开了连接,自然就没用了
随着 ES6 使用越来越广泛,Node.js 也支持了 ES6 Module,有几种方法
使用 babel 构建是在 v12 之前版本最简单、通用的方式,具体配置参考 @babel/preset-env(https://babeljs.io/docs/en/babel-preset-env)
.babelrc
{ "presets": [ ["@babel/preset-env", { "targets": { "node": "8.9.0", "esmodules": true } }] ] }
在 v12 后可以使用原生方式支持 ES Module
开启 --experimental-modules
模块名修改为 .mjs
(强烈不推荐使用)或者 package.json 中设置 "type": module
这样 Node.js 会把 js 文件都当做 ES Module 来处理,更多详情参考官方文档(https://nodejs.org/dist/latest-v13.x/docs/api/esm.html)
更多编程相关知识,请访问:编程视频!!
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!