Node基础(1)--模块机制

JavaScript从最开始的表单校验到现在的大型应用,大概经历工具类库、组件库、前端框架、前端应用的变迁。在经过了很长时间的努力,JavaScript不断被类聚和抽象,通过script标签的方式去引用代码的方式显得杂乱无章。不得不使用命名空间的方式去约束代码,以达到安全易用的目的。 JavaScript的痛点在

  • 没有模块系统
  • 标准库较少
  • 没有标准的接口
  • 缺乏包管理系统

CommonJS规范

CommonJS规范制定了一个良好的愿景——希望JavaScript在任何地方都可以去运行

Node借鉴CommonJS的Module规范实现一套易用模块,NPM对package的完好支持提高了Node应用的开发效率。

模块导出

export.add = function(a,b){
    return a + b
}
复制代码

模块引用

var math = require('math');
var sum  = math.add(1,2);
console.log(sum);
// 3
复制代码

模块标识

require()方法的参数,必须是小驼峰命名的字符串,相对路径和绝对路径。可以没有.js后缀。CommonJS引入的模块不用考虑变量污染和命名空间等。

Node的模块实现

Node模块分为两类,一种是Node提供的模块(fs,buffer等)称为核心模块,用户自己编写的模块叫文件模块。引入模块经过三个步骤

  1. 路径分析
  2. 文件定位
  3. 编译执行

** 核心模块在Node源代码编译过程中就加入了内存中,所以核心模块会跳过第一步和第二步在,在路径分析中优先判断,执行会更快。而文件模块运行中动态加载,需要完整的执行三步,会比核心模块慢。**

优先从缓存加载

在执行第一步和第二步之前,浏览器端会缓存文件提高性能,Node对引入过的模块会进行缓存,减少第二次引入带来的性能开销。浏览器是仅仅缓存文件,而Node会缓存编译和执行过后的文件。require会优先对缓存读取,核心模块的核心检查先于文件模块的缓存检查。

路径分析和文件定位

模块标识符分析

require接受不同的标识符作为参数。

  • 核心模块,如http,fs,path等Node自带的模块 核心模块优先级仅次于缓存加载,加载过程最快。 原因在核心模块是对底层的内建模块的封装,内建模块是用C/C++编写,性能上优于脚本语言,且Node开始执行的时候,文件编译生成的二进制文件就被加入到内存中,直接可以执行。

  • .和..开头的相对路径,/开头的绝对路径的文件模块 **以.、..和/开头的都会当成文件模块来处理,分析模块的时候会把路径转换为真实路径,将编译后的结果缓存。 **

  • 非路径形式的文件模块,自定义的connect模块。

模块路径的生成规则

  1. 当前文件目录下查找目标文件
  2. 父目录下查找目标文件
  3. 父目录的父目录下查找目标文件
  4. ...
  5. 递归查找,知道到根目录 自定义模块是最慢的一种,查找方式类似JS的原型链和作用域链的查找。
文件定位

从缓存加载的优化策略中,不需要路径分析、文件定位和编译执行,加快了再次加载模块的效率。当文件没有扩展名的时候,会按照.js、.json、.node的形式去补充扩展名,依次尝试去查找。

Tips: 引用.json和.node文件的时候加上后缀名会更快。同步配合缓存可以大幅度缓解Node单线程中阻塞式调用的缺陷。

当分析标识符过程中,没有找到相应的文件,却找到了一个目录,这时候会把目录当成一个包来处理。Node会查找目录中的package.json文件(包描述文件),再去解析出包对象。

模块编译

JavaScript的每一个文件模块都是一个对象,每一个模块文件中存在import,exports,module三个变量。export对象是通过形参的方式传入的,直接赋值会改变形参的引用。

var sum = function(a,b){
    return a+b;
}
module.exports = sum; //good
exports = sum; //bad
复制代码

还有C/C++模块和JSON文件的编译,后续会介绍。

内建模块

Node模块类型中,存在一种依赖层级关系,即文件模块可能依赖核心模块,核心模块依赖内建模块。

Node在启动时,会生成全局变量process,提供Binding()方法来协助加载内建模块。

AMD规范和CMD规范

AMD规范

AMD规范是CommonJS模块规范的一个延伸。 define(id?,dependencies?,factory) 模块id和依赖是可以选择的,跟Node定义模块不一样的是需要用一个define来明确定义一个模块,而在Node中实现是隐式包装。为了进行作用域隔离,避免变量污染。

CMD规范

CMD支持动态引入,CMD模块更接近Node对CommonJS规范的定义。 define(factory) require、export和module通过形参传递给模块,需要模块时随时调用require就可以。

包与NPM

CommonJS的包规范,一定程度上解决了变量依赖、依赖关系,进一步组织了JavaScript代码。

包结构

  • package.json 包描述文件
  • bin 存放二进制文件的目录
  • lib 存放JavaScript代码的目录
  • doc 存放文档
  • test 存放测试用例的代码

转载于:https://juejin.im/post/5bfa84e9e51d4536656f2bac

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值