Node中的模块机制
什么是模块化
-
文件作用域
-
通信规则:
· 加载 require
· 导出
CommonJS 模块规范
在 Node 中的 JavaScript 还有一个很重要的概念:模块系统。
-
模块作用域
-
使用 require 来加载模块
-
使用 exports 接口对象来导出模块中的成员
加载 require
- 语法:
var 自定义变量名称 = require(‘模块’)
- 两个作用:
· 执行被加载模块中的代码
· 得到被加载中的 exports 导出接口对象
导出 exports
-
Node 中是模块作用域,默认文件中所有的成员只在当前文件模块有效
-
对希望可以被其他模块访问的成员,我们就需要把这些公开的成员都挂载到 exports 接口对象中
· 导出 多个 成员(必须在对象中):
exports.a =123
exports.b ='123'
exports.obj= { name : 'jack' }
exports.add= function(){}
· 导出 单个 成员(拿到的就是:函数、字符串):
module.exports = 'hello'
后者覆盖前者 module.exports = function( ){ }
· 也可以这样来导出多个成员:
module.exports = {
add : funtion(a,b){
retrun a + b
} ,
str : 'hello' ,
}
原理解析:
我们可以这样认为,每个模块内部都有一个自己的 module 对象,
在该 module 对象中 也有一个 exports 对象
var module = {
exports : { } 当然它默认为空对象
}
谁来 require 我,谁就能得到 module.exports ,
默认在代码的最后一行
return module.exports
因此,如果我们直接让 exports.add = function ( ){ } ,是不可以的,
注意这里返回的是 module.exports, 即便 module.exports = exports,
当我们给 exports 进行 赋值操作以后,它们两个对象的引用将不指向同一个
所以当只需要返回单个导出的成员时使用:
module.exports = function add (a,b){ return a+b; }
也就是说如果需要对外导出成员,只需要把导出的成员挂载到 module.exports 对象中
默认还有一句代码: var exports = module.exports
可以说 exports 是 module.exports 的一个引用
console.log( exports === module.exports ) 的结果为 true
[ exports.a = 1 等价于 module.exports.a = 1 ]
require 方法的加载规则
- 优先从缓存加载
假设有这样三个文件,mian.js 加载 a.js , a.js 加载了 b.js;
文件 文件内容
main.js : require ('./a');
a.js : console.log('a 加载了');
require('./b');
b.js : console.log('b 加载了');
一个 js 文件加载以后,就会进入缓存,优先从缓存里加载
由于在 a 中已经加载了 b , 所以这里不会重复加载,
可以拿到里面的接口对象,不会重复加载
这样做的目的是为了避免重复加载,提高文件加载的效率
require 的参数用于判断模块的标识
require(’ 模块标识 ')
- (核心模块 )非路径形式的模块标识:
核心模块的本质也是文件( .js 文件)
核心模块的文件已经被编译到了二进制文件中了,我们只需要按照名字来加载就可以了
www.github.com/node.js 在 node 中的 lib 文件夹下,可以看到源码
-
( 自己写的模块 )路径形式的模块:
. / (当前目录不可省) ../ (上一级目录,不可省略) /xxx (几乎不用) 带有盘符的路径(d:/a/foo.js)几乎不用 首位的 / 在这里表示的是当前文件模块所属 磁盘根路径
-
第三方模块:
凡是第三方包都要通过 npm 来下载
使用的时候就可以通过 require (‘包名’) 的方式进行加载才可以使用
注意:
由于第三方包 的路径 形式和 核心模块 的路径 形式很相似, 但是它们是不同的`而且 不可能有一个 第三方包 和 核心模块 的名字是一样的
第三方模块的加载机制:
例如 加载了 var template = require('art-template'); 加载查询顺序: node_modules/art-template/ node_modules/art-template/package.json node_modules/art-template/package.json 里的 main 加载 node_modules/art-template/package.json 里的 main 入口模块文件 如果 node_modules/art-template/package.json 里的main 不存在 加载默认的 index.js 备选项 如果当前目录不存在 node_modules 文件,往父级目录去找 node_modules 并且按照以上的规则进行查找,如果还没有,一直往父级的父级查找,一直到当前磁盘的根目录
n p m 和 package.json
- n p m —— node package manager (安装、下载包)
建议用 npm 进行安装包的时候,用 [ npm install 包名 --save ]
目的是用来保存依赖信息( dependencies 选项)
- package.json : 我们建议每一个项目都有一个 package.json 文件
(包装 和 描述 文件,就像产品说明书一样)
这个文件可以通过 npm init 的方式来自动初始化出来(以向导的方式创建)
-
如果你的 node_module 删除了也不用担心,我们只需要在当前目录: npm install
就可以把 package.json 中的 dependencies 中的所有依赖都下载回来
n p m 的两层含义:
-
npm 网站 ( npmjs.com )用于查找 第三方包 和 发自己的包
-
npm 命令行工具,只要你安装了 node 就已经安装了 npm ,
它也有版本的概念(命令行输入 npm --version)查看版本号
升级 npm (命令行输入 npm install --global npm)
解决 npm 被墙问题:
npm 存储服务器在国外,有时候会被墙,速度很慢,所以我们需要解决这个问题。
http://npm.taobao.org/ 淘宝的开发团队把 npm 在国内做了一个备份( npm 镜像 )
安装淘宝的 cnpm (China cpm) : npm install–global cnpm (在任意目录下执行都可以)
接下来你安装的时候把之前的 npm 替换成 cnpm
例如:
npm install jquery --- 用的是国外的 npm 服务器,速度比较慢
cnpm install jquery --- 用的是淘宝的服务器下载下来的 jquery
淘宝的 cnpm 服务器 每隔十分钟会 和 国外的 npm 服务器进行同步更新 (淘宝镜像)
如果不想安装 cnpm 又想使用淘宝的服务器来下载,可以这么使用:
npm install jquery --registry=http://npm.taobao.org
但是每次手动加参数很麻烦,所以我们可以把这个参数加入到配置文件当中:
npm config set registry http://npm.taobao.org
注意:只要经过了上面的命令的配置,则你以后所有的 npm install 都会默认通过淘宝的服务器来下载
配置以后可以查看 npm 配置信息: npm config list
常用命令
+ npm init:npm init-y 可以跳过向导,快速生成
+ npm install:依次把 dependencies 中的依赖项全部安装(简写: npm i)
+ npm install 包名:只下载(简写: npm i 包名)
+ npm install 包名 --save : 下载并保存依赖项(package.json文件中的 dependencies选项)
(简写: npm i-S 包名)
+ npm uninstall 包名 : 只删除,如果有依赖项依然会保存 (简写: npm un)
+ npm uninstall 包名 --save:删除的同时,也会把依赖信息也去除 (简写: npm un-S)
+ npm help : 查看使用帮助
+ npm命令 help : 查看指定命令的使用帮助