Node中的模块

一、模块

  在 Node.js 中,文件和模块是一一对应的(每个文件被视为一个独立的模块)。

  模块分为三种:核心模块(node定义的)、第三方模块、自定义模块。可以通过require()加载第三模块。require会将module.exports对象暴露给外部。

  模块中的命名空间是独立的,不是全局的。

二、require()

  下面的代码是require的假设实现。 

 1 //自定义一个require()
 2 let path=require('path');
 3 const fs=require('fs');
 4 function $require(id){
 5     //拼合文件路径
 6     let filename=path.join(__dirname,id);
 7     let dirname=path.dirname(filename);
 8     //读取要加载的文件的内容
 9     let content=fs.readFileSync(filename,'utf8');
10     let module={exports:{},id:filename}
11     //执行代码
12     let exports=module.exports;
13     let code=`(function(__filename,module,exports){
14         ${content}
15     }(filename,module,exports))`;
    eval(code)
16 return module.exports; 17 } 18 const mymodule=$require("./modele1.js"); 19 mymodule.say();

三、require的加载机制

  文件模块加载  

  如果按确切的文件名没有找到模块,则 Node.js 会尝试带上 .js.json 或 .node 拓展名再加载。

  .js 文件会被解析为 JavaScript 文本文件,.json 文件会被解析为 JSON 文本文件。 .node 文件会被解析为通过 dlopen 加载的编译后的插件模块。

  以 '/' 为前缀的模块是文件的绝对路径。 例如,require('/home/marco/foo.js') 会加载 /home/marco/foo.js 文件。

  以 './' 为前缀的模块是相对于调用 require() 的文件的。 也就是说,circle.js 必须和 foo.js 在同一目录下以便于 require('./circle') 找到它。

  当没有以 '/''./' 或 '../' 开头来表示文件时,这个模块必须是一个核心模块或加载自 node_modules 目录。

  如果给定的路径不存在,则 require() 会抛出一个 code 属性为 'MODULE_NOT_FOUND' 的 Error

  目录模块加载  

  可以把程序和库放到一个单独的目录,然后提供一个单一的入口来指向它。 把目录递给 require() 作为一个参数,有三种方式。

     第一种方式是在根目录下创建一个 package.json 文件,并指定一个 main 模块。 例子,package.json 文件类似:

  { "name" : "some-library",
    "main" : "./lib/some-library.js" }

  如果这是在 ./some-library 目录中,则 require('./some-library') 会试图加载 ./some-library/lib/some-library.js这就是 Node.js 处理 package.json 文件的方式。

  注意:如果 package.json 中 "main" 入口指定的文件不存在,则无法解析,Node.js 会将模块视为不存在,并抛出默认错误:Error: Cannot find module 'some-library'

  如果目录里没有 package.json 文件,则 Node.js 就会试图加载目录下的 index.js 或 index.node 文件。 例如,如果上面的例子中没有 package.json 文件,则 require('./some-library') 会试图加载:

  • ./some-library/index.js
  • ./some-library/index.node

  加载核心模块和node_module  

   模块标识符没有以 '/' 、 '../' 或 './' 开头,加载的可能是核心模块,如果传递给 require() 的模块标识符不是一个核心模块,则 Node.js 会从当前模块的父目录开始,尝试从它的 /node_modules 目录里加载模块。

  如果还是没有找到,则移动到再上一层父目录,直到文件系统的根目录。

  例子,如果在 '/home/ry/projects/foo.js' 文件里调用了 require('bar.js'),则 Node.js 会按以下顺序查找:

  • /home/ry/projects/node_modules/bar.js
  • /home/ry/node_modules/bar.js
  • /home/node_modules/bar.js
  • /node_modules/bar.js

  这使得程序本地化它们的依赖,避免它们产生冲突。

四、package.json文件

  使用package.json文件配置项目所依赖的模块。可以使用npm init初始化一个package.json文件。使用npm install安装项目所依赖的文件。 

原文地址:https://www.cnblogs.com/yiluhuakai/p/8577121.html