当前位置: 首页 > 后端技术 > Node.js

nodeJS模块搜索策略

时间:2023-04-03 15:50:16 Node.js

es6和nodeJS模块搜索策略主要分为三步:路径分析【找到指定文件所在的目录在哪里】文件位置【找到文件的目录后,找到指定文件【notafolder】】编译执行其中,我们需要重点关注前两步。由于不同类型模块的路径解析和文件定位策略不同,我们先讨论一下我们一般将模块分为哪几类。模块分类nodeJS中的模块主要分为两类。一种是nodeJS自带的模块,称为核心模块,比如http、ftp、path等模块【npm包不是核心模块,虽然两者的参考代码格式是一样的】【核心模块定义在Node.js源码的lib/目录下。】.另一种是用户编写的模块,称为文件模块[npm包和自己编写的模块文件都是文件模块]。它们的关系如下图所示:模块引入的代码格式核心模块:varhttp=require('http');路径形式的模块:varmoduleA=require('./moduleA.js');记住,路径的形式写模块路径时,必须有./或../或/开头,否则会被认为是核心模块或自定义模块。自定义模块:varexpress=require('express');虽然写法和核心模块一样,但是最大的区别在于自定义模块不是nodeJS内置的,需要从npm库中下载。由模块导入。核心模块是内置的,不用下载也可以导入【不过就算是核心模块也必须先导入才能使用】这里给大家放一张图:也就是说nodeJS不是正好等于ECMAScript必须内置很多FS、TCP、http等模块,才可以称为nodeJS。浏览器中的JS也是如此。浏览器中的JS并不完全等同于ECMAScript【构成JS的核心语法基础】,必须有一个内置模块BOM【浏览器对象模型,用于操作浏览器上的对象】,DOM【文档对象模型,用于操作网页中的元素]。路径分析核心模块:由于核心模块是在nodeJS编译时加载的,所以核心模块不需要进行路径分析和文件定位。路径形式的模块:由于指定了确切的路径,所以require方法在导入时会将路径转换为硬盘上的真实路径,并以此路径为索引缓存编译后的结果[索引:文件名,值:模块对象]。自定义模块:自定义模块的路径解析比以路径形式引入的模块要复杂一些,主要是因为它的文件路径不像后者那样是固定的,可能是目录下node_modules目录下对应的文件夹当前目录名称,可能还有父亲,甚至更多。同样,找到的模块文件也会存储在缓存中。文件定位当路径解析完成后,nodeJS会进行文件定位。核心模块不需要文件定位这一步,但是路径形式模块和自定义模块的文件定位方式是一样的。由于CommonJS规范和es6模块化都允许文件的标识符不带扩展名,甚至可以指定最终的文件名,直接写入上层的目录名即可。这两种情况有不同的处理方法。正常的写法【只有路径形式模块可以这样写】如require('./a.js');,当路径解析成功后,会直接查找是否有同名文件目录下,找到就命中,找不到就报错省略扩展名的声明方法【只有路径形式模块可以这样写】会按照.js的顺序一一尝试、.node和.json在此目录中。由于这个申报表和第三个申报表很像,所以策略是先定位申报表省略扩展名的文件,如果没有命中,再用以美元为单位指定最终文件名的申报表定位文件,然后没有命中,就会报错。不指定最终文件名,直接写上层的目录名【路径形式模块和自定义模块都会这样写】首先会在hit目录下找到package.json文件,main属性在json文件会被取出值,作为命中文件,如果找不到package.json或者对应的main属性,会使用index作为文件名,然后按照.js,.node,.的顺序尝试。json【如果还是没有找到对应的文件,如果是路径形式的模块,则定位文件失败。如果是自定义模块,会继续在上层目录中寻找node_modules,直到命中或者没有上层]require()总是会先加载核心模块。例如,require('http')总是返回内置的HTTP模块,即使存在同名文件也是如此。也就是说核心模块和自定义模块总是假设这条路径是核心模块再找,如果没找到就是自定义模块。nodeJS在一定程度上优化了模块加载,所有文件只要被引用一次就会被缓存。下次引用时,会先检查缓存中是否有对应的文件,即先从缓存中加载文件,这样速度会更快。