在nodejs中引入模块需要经历如下3个步骤

1.路径分析

2.文件定位

3.编译执行

在nodejs中模块分为两类,一类是nodejs提供的模块,称为核心模块,另一类的用户编写的模块,称为文件模块。

1.核心模块在nodejs源代码的编译过程中,编译进了二进制执行文件,在nodejs进程启动时,部分核心模块就被直接加载进内存够中 ,这部分核心模块引入时,文件定位和编译执行两个步骤可以省略,并且在路径分析中优先判断,所以它的加载速度时最快的。

2.文件模块则是在运行时动态加载,需要完整的路径分析,文件定位,编译执行过程,速度比核心模块慢。

一.优先从缓存中加载

为了减少二次引入的开销,nodejs会对引入过的模块进行缓存,缓存的是编译和执行之后的对象。不论是核心模块还是文件模块,require()方法对相同模块的二次加载都一律采用缓存优先的方式。不同之处在于核心模块的缓存检查优先于文件模块的缓存检查。

二.路径分析

在nodejs中使用require()引入文件时,require()方法接受一个标识符作为参数。nodejs就是通过这个标识符进行模块查找的。模块标识符只要分为如下几类:

1.核心模块,如http,fs,path等

2. .或..开始的相对路径文件模块

3.以/开始的绝对路径文件模块

4.非路径形式的文件模块,如自定义的connect模块

2.1.核心模块

核心模块的优先级仅次于缓存加载,如果要加载一个与核心模块标识符相同的自定义模块,那是不会成功的。如,你自己编写了一个http用户模块,想要加载成功,就必须选择一个不同的标识符或者使用路径的形式。

2.2.路径形式的文件模块

以..和/开始的标识符都被当作文件模块来处理。在分析路径模块时,require()方法会将路径转化为真实路径,并以真实路径作为索引,将编译执行后的结果存放在缓存中,以使二次加载时更快。由于指定了确切的文件位置,所以在查找过程中可以节约大量时间,其加载速度慢于核心模块。

2.3自定义模块

自定义模块指非核心模块,也不是路径形式的标志符。它是一种特殊的文件模块,可能是一个文件或者包的形式。这类模块的查找是最耗时的。

在介绍自定义模块的查找方法之前,需要先介绍一下模块路径这个概念。

模块路径是nodejs在定位文件模块的具体文件时制定的查找策略,其具体表现为一个路径组成的数组。例如:

(1)创建一个module_path.js文件,其内容为console.log(module.path);

(2)将其放在任何一个目录中,然后执行node module_path.js

在Linux下,你可能得到的时这样一个数组输出:

['/home/jack/res/node_modules',

'/home/jack/node_modules',

'/home/node_modules',

'/node_modules']

在windows下,可能如下:

['c:\\nodejs\\node_modules','c:\\node_modules']

可以看出,模块路径的生成规则如下:

1.当前文件目录下的node_modules目录

2.父目录下node_modules目录

3.父目录的父目录的node_modules目录

4.沿路径向上逐级递归,直到根目录下的node_modules目录

在加载的过程中,nodejs会逐个尝试模块路径中的路径,直到找到目标文件为止。所以当前文件的路径越深,模块查找耗时就越多,这是自定义模块的加载速度最慢的原因

三.文件定位

从缓存加载的优化策略使得二次引入时不需要路径分析,文件定位和编译执行的过程,大大提高了再次加载模块时的效率。

但在文件定位过程中,还是一些细节需要主意,这主要包括文件扩展名的分析,目录和包的处理

1.文件扩展名分析

require()在分析标识符的过程中,会出现标识符中不存在文件扩展名的情况。在这个情况下,nodejs会按.js,.node,.json的次序补充扩展名,依次尝试。在尝试的过程中需要调用fs模块同步阻塞式的判断文件是否存在。所以,如果是.node或.json文件加上扩展名会加快一点速度。

2.目录分析和包

在分析标识符的过程中,require()通过分析文件扩展名之后,可能没有查找到对应的文件,但是得到一个目录,这是nodejs会将目录当作一个包处理。

在这个过程中,首先,nodejs在当前目录下查找package.json,通过JSON.parse()解析出包描述对象,从中取出main属性指定的文件名进行定位,如果文件名缺少扩展名,就将进入扩展名分析的步骤。如果main属性指定的文件名错误,或者没有package.json文件,就将index作为默认文件名,然后依次查找index.js,index.node,index.json。如果在目录分析过程中没有定位成功任何文件,则自定义模块进入下一个模块路径进行查找,如果所以的模块路径都查找完毕还是没有找到目标文件,则会抛出查找异常。

四.模块编译

在nodejs中,每一个文件模块都是一个对象

执行和编译是引入文件模块的最后一个阶段。定位到具体文件后,nodejs会新建一个模块对象,然后根据路径载入并编译,对于不同的扩展名载入的方法有所不同。

1..js文件。通过fs模块同步读取文件后编译执行

2..node文件。这是通过c/c++编写的扩展文件。通过dlopen()加载最后编译生成的文件

3..json文件。通过fs模块同步读取文件后,用JSON.parse()解析返回结果

4.其他扩展名文件。它们都被当作js文件载入

注:《深入浅出nodejs》学习笔记

在nodejs中引进模块要经历的步骤的更多相关文章

  1. Nodejs中cluster模块的多进程共享数据问题

    Nodejs中cluster模块的多进程共享数据问题 前述 nodejs在v0.6.x之后增加了一个模块cluster用于实现多进程,利用child_process模块来创建和管理进程,增加程序在多核 ...

  2. Nodejs中关于模块的总结

    关于Nodejs中的模块 概念 Nodejs在ECMAScript的基础上扩展并封装了许多高级特性,如文件访问.网络访问等,使得Nodejs成为一个很好的Web开发平台.基于Nodejs这个平台将We ...

  3. Nodejs中的模块系统

    一.模块化的定义 ①具有文件作用域 ②具有通信规则:加载和导出规则 二.CommonJS模块规范 1.nodejs中的模块系统,具有文件作用域,也具有通信规则,使用require方法加载模块,使用ex ...

  4. node (02 CommonJs 和 Nodejs 中自定义模块)顺便讲讲module.exports和exports的区别 dependencies 与 devDependencies 之间的区别

    CommonJS 规范的提出,主要是为了弥补当前 JavaScript 没有标准的缺陷.它的终极目标就是:提供一个类似 Python,Ruby 和 Java 语言的标准库,而不只是停留在小脚本程序的阶 ...

  5. Node.js学习笔记(二) --- CommonJs和Nodejs 中自定义模块

    一. 什么是 CommonJs? JavaScript 是一个强大面向对象语言,它有很多快速高效的解释器. 然而, JavaScript标准定义的 API 是为了构建基于浏览器的应用程序.并没有制定一 ...

  6. NodeJS中Buffer模块详解

    一,开篇分析 所谓缓冲区Buffer,就是 "临时存贮区" 的意思,是暂时存放输入输出数据的一段内存. JS语言自身只有字符串数据类型,没有二进制数据类型,因此NodeJS提供了一 ...

  7. TypeScript完全解读(26课时)_14.ES6和Nodejs中的模块

    创建modules文件夹,我们的文件都写在这里面 modules下面新建index.js文件,在index.ts内引入这个js文件 es6的模块 最主要的两个关键字 import和export imp ...

  8. Nodejs中Async模块的流程控制方法

    首先,使用Asycn模块需要安装,它不是node自带的.其次,该模块有大约20多个流程控制方法,我们在这里仅分析常用的series, parallel, waterfall, auto这四种,并且尽量 ...

  9. 浅谈nodejs中HTTP模块应用

    这里给大家分享下后端人员如果利用nodejs对数据的一些处理情况  适用于初学者使用 大牛勿喷 给大家分享下主要后端思想部分代码,前端部分就不展示了 const http = require(&quo ...

随机推荐

  1. MySQL之UNDO及MVCC、崩溃恢复

      UNDO特性:避免脏读.事务回滚.非阻塞读.MVCC.崩溃恢复 事务工作流程(图2) MVCC原理机制 崩溃恢复:redo前滚.undo回滚 长事务.大事务:危害.判断.处理 UNDO优化:实现u ...

  2. linux stat 简单介绍

    stat 命令查看文件或文件系统的状态时间等属性 用法:stat [参数]... 文件... 简单的介绍一下stat命令显示出来的文件其他信息: - File:显示文件名 - Size:显示文件大小 ...

  3. Python学习--Selenium模块学习(2)

    Selenium的基本操作 获取浏览器驱动寻找方式 1. 通过手动指定浏览器驱动路径2. 通过 `$PATH`环境变量找寻浏览器驱动 可参考Python学习--Selenium模块简单介绍(1) 控制 ...

  4. 35_张孝祥Java高新技术_为注解增加各种属性

    注解的作用之所以那么强大,就是因为它有属性 注解很像接口,属性很像方法.   什么是注解的属性 一个注解相当于一个胸牌,如果你胸前贴了胸牌,就是传智播客的学生,否则,就不是.如果还想区分出事传智播客 ...

  5. MySQL基础之 索引

    MySQL索引讲解 索引的好处: MySQL索引的建立对于MySQL的高效运行是很重要的,索引可以大大提高MySQL的检索速度. 打个比方,如果合理的设计且使用索引的MySQL是一辆兰博基尼的话,那么 ...

  6. MySQL基础之 外键参照讲解

    外键: 定义:如果表A的主关键字是表B中的字段,则该字段称为表B的外键,表A称为主表,表B称为从表. 作用:外键是用来实现参照完整性的,不同的外键约束方式将可以是两张表紧密的结合起来.比如修改或者删除 ...

  7. js字符串String常用方法

    1.   charAt()         返回指定位置的字符. str.charAt(index) index 为必须参数,类型为number(0到str.length-1之间,否则该方法返回 空串 ...

  8. SDOI 2018 R2 游记

    一篇真正的“游记”. DAY -3 下午: 今天老师批准了我去省选划水的请假要求. 批准之后感觉学习非常有动力,顺便忽悠别的同学和我一起去,然而wzx是唯一一个表示可以考虑一下的同学,其他同学直接一口 ...

  9. python-webbrowser模块 浏览器操作

    python的webbrowser模块支持对浏览器进行一些操作,对于爬虫来说是比较基础的知识点 1.主要有以下三个方法: webbrowser.open(url, new=0, autoraise=T ...

  10. ssh访问服务器端visdom

    在服务器端启动visdompython -m visdom.server在windows端,将服务器的8097端口重定向到windows端(做了映射绑定):ssh -L 8097:127.0.0.1: ...