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

Node.js之模块机制

时间:2023-04-04 00:01:08 Node.js

本文首发于公众号:程序员周先森。本平台不定期更新,喜欢我的文章,请关注我的微信公众号。事实上,在JavaScript的开发中,主要广泛应用于浏览器的前端。因为在实际应用中,JavaScript的性能主要取决于宿主环境的API支持。最早的时候,只有BOM和DOM的支持。随着HTML5的出现,越来越强大的浏览器出现了。API是通过JavaScript来调用的,但是这些都发生在前端,而JavaScript在后端的规范还远远落后。Java有class文件,Phthon有导入机制,PHP有include和require,但是JavaScript通过script标签引入代码的方式比较杂乱,给我们后期维护增加了难度。对于JavaScript来说,有四大缺点:1.没有模块系统。2.标准库比较小。3.没有标准、统一的接口。4.缺少包管理系统。Node.js实现了非常易用的模块系统,Node的包管理系统NPM对包规范的全面支持使得Node应用在开发过程中更加高效。本文主要讲解Node模块和包的实现。Node的模块规范其实是很简单的定义一个模块,主要分为三个部分:模块引用、模块定义和模块标识。1)模块引用Node.js中有一个require()方法,这个方法接受模块标识符,从而将一个模块的API引入到当前上下文中。2)模块定义既然我们可以使用require()来导入模块,那么自然也可以导入模块。Node.js提供了exports对象来导出当前模块的方法和变量,exports是唯一的export。在每个模块中,都有一个模块对象,代表模块本身,exports其实是模块的一个属性。在Node.js中,一个文件其实就是一个模块,可以通过将我们需要导出的方法和属性作为属性绑定到exports对象中来导出方法或属性。在另一个模块中,可以通过require()导入模块,可以使用导出的方法sum()。3)模块ID模块ID实际上是传递给require()方法的一个参数。模块ID必须是以驼峰命名的字符串或者以./、../开头的路径,引入模块模块ID时可以省略.js后缀。模块的好处是将具体的方法和变量限定在特定的范围内,让开发者完全不用考虑变量污染的问题。Node.js模块是在Node.js中实现的,一共有三种模块,其中一种是Node.js提供的核心模块,比如上一篇文章提到的fs文件模块和database数据库模块,还有第二类是开发者自己编写的文件模块,比如刚才例子中的test.js模块,第三类是自定义模块,是一种特殊的文件模块,通常是文件或者包的形式,比如导入mysql需要的jar包。在Node.js中引入模块需要三个步骤:(1)路径分析对于文件模块,模块标识在导入时指明文件的确切位置,因此在路径分析中可以省去很多时间,加载速度仅次于核心模块。自定义模块会从项目根目录开始逐一比较路径,直到找到目标模块。因此,自定义模块的路径越深,路径解析越费时,因此自定义模块的加载速度最慢。(2)文件定位刚才说了,模块标识不需要包含后缀名,所以Node.js在定位文件的时候会依次加上.js、.json、.node后缀名,然后去到文件位置,因为Node.js是单线程的,所以在定位文件的时候会阻塞,所以如果导入模块的后缀是.json或者.node,可以在导入的时候加上后缀,可以提高查找速度。(3)编译执行到特定文件的定义后,Node.js会创建一个模块对象,然后导入并编译该模块。每个编译成功的模块的文件路径都会作为索引缓存在缓存对象上,以提高二次导入模块的性能。Node.js源码在编译过程中,直接将核心模块编译成二进制文件,然后直接加载到内存中。因此在导入核心模块时,可以直接跳过文件定位和编译执行两步,在路径分析时先判断核心模块,所以核心模块的加载速度是最快的。文件模块在执行时是动态加载的,所以路径解析、文件定位、编译执行这三个步骤不能省略,所以加载速度比核心模块慢。Node.js会缓存导入的模块,以减少重新导入模块的性能开销。重新加载的模块均采用缓存优先的方式。核心模块的缓存检查优先于文件模块。刚才包管理工具NPM提到了Node模块,虽然我们可以引用模块,但是模块还是散列在各个地方,不能直接相互引用。Node的包管理工具NPM将模块相互连接起来。包实际上是JavaScript代码在模块的基础上的进一步组织。其实npm会有一个包描述文件package.json,一般位于包的根目录下。NPM的所有行为都与包描述文件密切相关。前几篇文章提到过,NPM作为默认的包管理工具,会作为Node环境一起安装。NPM常用功能NPM帮助Node完成第三方模块的发布、安装和依赖。因为NPM的存在,Node和第三方模块之间形成了良好的生态,并且逐渐变得越来越强大。接下来简单介绍一些常用的npm命令npm--version查看当前npm版本npm查看帮助说明npmhelp查看具体命令说明执行该命令会在浏览器中打开对应命令的文档npminstall安装依赖包,默认使用--save参数,默认添加到package.json执行这条命令,npm会在当前目录下创建一个node_modules目录,然后node_modules会创建一个对应依赖包的目录,然后将依赖包解压到该目录下。npminit在该目录中初始化并生成一个package.json文件。npmuninstall卸载依赖包。默认情况下,--save参数用于从package.json中删除npmls以查看当前目录中的依赖包。npmroot-g查看全局安装。地址npmlist查看当前依赖版本。NPM的问题在NPM平台上,大家可以共享包,所以包质量没办法保证,而且Node.js运行在服务端,需要考虑安全问题。所以一个优秀的模块需要满足几大模块:好的测试,好的文档,好的测试覆盖率,好的代码规范,今天的内容就这些,其实本文不涉及代码编写,而是理解Node.js从模块的角度。Node.js通过模块规范弥补了JavaScript无结构的不足,NPM通过包的统一管理有效解决了项目开发中的依赖问题。下一篇文章将带你继续从异步编程的角度来理解Node.js。下篇文章见!欢迎关注我公众号:程序员周先森