Nodejs 笔记(模块)

167 阅读5分钟

javascript 从表单校验到应用开发过程

CommonJs规范

诞生原因:

  1. 没有模块系统
  2. 标准库较少: 例如 I/O 等常见需求却没有标准API
  3. 没有标准接口: 例如 web服务器类或者数据库类没有标准统一接口
  4. 缺乏包管理系统: 没有自动加载和安装的能力
    目的:弥补当时javascript没有标准的缺陷
    Node、浏览器、W3C组织、CommonJs组织、ECMAScript之间的关系,共同构建了一个强大繁荣的生态

模块规范:

  1. 模块引用: commonJs规范中存在require()方法,引入一个模块的API到当前上下文中
  2. 模块定义: require()方法引入外部模块,exports导出当前模块的方法或变量。module代表模块自身,exports是它的属性。node中一个文件即一个模块
  3. 模块标识: 即传递给require()方法的参数,参数必须符合 小驼峰命名、相对路径、绝对路径

Node模块实现

node引入模块需要经历3个步骤:

  1. 路径分析
  2. 文件定位
  3. 编译执行
    Node中模块分为两类:
  4. 核心模块(Node提供的模块)
    源码编译时已编译进二进制执行文件,在Node进程启动时,部分核心代码被直接加载进内存中,所以这部分核心模块引入时省略了文件定位和编译执行,并在路径分析中优先判断,故加载速度最快
  5. 文件模块(用户编写的模块)
    文件模块是在运行是动态加载,需要完整的路径分析、文件定位、编译执行,故比核心模块慢

加载过程:
前置知识
1.Node对引入的模块都会进行缓存,以减少二次引入的开销。
2. 浏览器缓存文件,Node缓存编译和执行后的对象。
3. require()方法对二次引入的模块采用缓存优先的策略,且核心模块优先于文件模块

路径分析

  1. 核心模块:加载优先级仅次于缓存
  2. 路径形式的文件模块:在分析文件时,require() 方法会先将路径转化为真实路径,并以真实路径为索引,将编译执行后的对象存到缓存中,以使二次加载更快。
  3. 自定义模块:即不是核心模块也不是路径形式的标识符,可能是一个文件或者包的形式。文件查找方式类似于javascript的原型链或作用域查找,因而嵌套越深耗时越长

文件定位

  1. 文件扩展名分析:依次按 .js、.json、.node 查找
  2. 目录分析和包:

模块编译
Node定位到文件后会新建一个模块对象,根据路径载入并编译
.js文件:调用fs同步读取文件后编译
.node:调用dlopen()方法加载最后生成的文件
.json:调用fs同步读取文件后,调用JSON.parse()解析返回结果
其他扩展名文件:被当作.js文件方式载入
编译成功的模块将其文件路径作为索引缓存在Module._cache 对象上,通过require.extensions获知系统已有扩展方式(module._extensions)

模块中require、exports、module、__filename、__dirname 的由来
在编译的过程中,Node对获取的javascript内容做了首尾包装,在头部添加 (function (exports, require, __filename, __dirname) {\n 在尾部添加了 \n}),这样每个模块之间都进行了作用域隔离,最后通过vm原生提供的runInThisContext(类似eval)返回一个具体的function对象

模块调用栈
核心模块扮演两类职责:作为c/c++内建模块的封装层和桥接层,供文件模块调用。作为存粹的功能模块,不需要与底层打交道,但又十分重要。

包与NPM

包结构:
package.json: 包描述文件
bin: 用于存放可执行二进制文件的目录
lib: 用于存放JavaScript代码的目录
doc: 用于存放文档的目录 test: 用于存放单元测试用例的代码

包描述文件
name: 包名 author: 包作者
main: 模块引入时,优先检查这个字段,并将其作为模块的入口,若不存在则查找目录下的index.js、index.node、index.json文件作为默认入口
description: 包简介
version:版本号 通常格式:major.minor.revision
scripts: 脚本说明对象,主要被包管理器用来安装、编译、测试、卸载包
bin: 将包作为命令行工作使用,运行后直接调用指定位置的脚本
keywords: 关键词组,用于在npm中分类搜索
maintainers: 包维护列表,每个维护者由name、email、web这3个属性组成
contributors: 贡献者列表
bugs: 一个可以反馈bug的网址或email
licenses: 当前包所用许可证列表
repositories: 托管源代码的位置列表
homepage: 当前包的网页地址
engines: 支持的JavaScript引擎列表
directories: 包目录说明

全局模式安装: -g 不意味着任何地方可以引用它。而是将包安装为全局可用的可执行命令,根据包中的bin字段配置,将实际脚本链接到与Node可执行文件相同的路径下
本地安装:

npm install <tarbal file> 
npm install <tarbal url> 
npm install <folder> 

注册包仓库账号:

npm adduser  

包管理权限:

npm owner ls <package name>  
npm owner add <user> <package name>  
npm owner rm <user> <package name>  

分析包

npm ls

CommonJs规范主要用于后端
AMD、CMD 规范主要用户前端