node有一个简单的模块加载系统,一个模块要使用另一个模块需要使用require()去加载所需模块。
一、加载核心模块
node提供好多核心模块、http、url、fs、path等。
node会一直优先加载核心模块,即使有一个相同模块的名称。例如require('http')会一直加载核心模块http模块。
二、加载文件模块
在node中模块和文件有着一一对应的关系,一个js文件就可以作为一个模块(和java中类很类似,一个大的项目不可能不全部代码写在一个类中,那么node也是不可能全都写在一个js文件中) 。
如果给定模块名称没有后缀,node会加上.js、.node、.json去后缀去尝试加载。
如果模块名称以/开头,node则会认为是一个绝对路径,会去此绝对文件路径去尝试加载。
如果模块名称以./开头,node则会认为是一个相对路径,会去次相对文件路径去加尝试载。
如果模块名称不是以以上两种情况开头,那么node要么去核心模块中去加载,要不在node_modules目录中去尝试加载。
如果指定名称的模块没有找到,将抛出MODULE_NOT_FOUND错误。
三、从文件夹中去加载模块
如果不是以../、./、/开头的模块,node会尝试当前模块所在目录的上一级目录中的node_modules文件夹中去加载。
如果以上没有加载成功,会再到上一级目录中尝试加载,直到到文件系统的根目录为止。
如果始终没有发现,将抛出错误。
四、文件夹作为一个包
文件夹作为一个包是非常方便的,去在自己的模块内部去组织程序文件和库,然后提供单一的入口文件去使用require加载。
首先需要在模块根目录下建立一个package.json文件:{ "name" : "some-library","main" : "./lib/some-library.js" },去描述模块名称和入口文件。
如果在模块文件夹中没有package.json文件,那么node会在模块文件夹中尝试去加载index.js或者index.node文件。
五、模块缓存
模块会在第一次加载完成后缓存,这以为着如果每次require()解析的模块文件是相同的,那么每次都将会返回一个完全相同的模块对象。
node不保证每次返回的是一个相同的对象,如果解析的文件是不同的。
因此,每次require加载模块并一定模块的代码吗都会执行,如果想让代码执行多次,去导出一个方法,每次去调这个方法。