CommonJS模块规范,包描述文件及npm常用命令
# 什么是模块化
- 有文件作用域
- 通信规则
- 加载 require
- 导出
# CommonJS模块规范
JavaScript本身是不支持模块化的
在Node中的JavaScript还有一个很重要的概念:模块系统
- 模块作用域
- 使用require方法来加载模块
- 使用exports接口对象用来导出模块的成员
# 加载require
var 自定义变量名 = require('模块')
1
两个作用:
- 执行被加载模块中的代码
- 得到被加载模块中的exports导出接口对象
# 导出exports
- Node中是模块作用域,默认文件中所有的成员只在当前文件模块有效
- 对于希望可以被其他模块访问的成员,我们就需要把这些公开的成员都挂载到exports接口对象中就可以了
exports.a = 123
exports.b = 'hello'
exports.c = function () {
console.log('ccc')
}
exports.d = {
foo: 'bar'
}
//或者
module.exports = {
a: 123,
b: 'hello',
c: function () {
console.log('ccc')
},
d: {
foo: 'bar'
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
需求:Node中的exports是一个对象,但如果某一个模块仅导出一个方法,希望通过导入模块直接拿到该方法,而不需要通过 exports.方法 的形式(即导出单个成员)
function add(x,y) {
return x + y
}
//exports = add 这句不起作用
module.exports = add//如果多次赋值,后面会覆盖前面的
1
2
3
4
5
2
3
4
5
# exports和module.exports的区别
在Node中,每个模块内部都有一个自己的module对象,该module对象有一个默认为空的exports对象,可以默认为模块有以下代码
var exports = module.exports
console.log(exports === module.exports)//true
...
return module.exports
//所以当导出单个成员是让exports直接等于函数或者字符串会不起作用,因为改变了指针指向,没有改变module.exports的值
1
2
3
4
5
2
3
4
5
# require方法加载规则
- 优先从缓存加载(如果之前已引入一次,则不执行模块代码,直接获取模块的返回值)
- 判断模块标识(即require参数)
- 核心模块
- require参数为模块名
- 核心模块文件已经被编译到了二进制文件(node.exe)中了,我们只需要按照名字加载就可以了
- 第三方模块
- require参数为模块名
- 凡是第三方模块都必须通过npm来下载
- 使用的时候通过require('包名')的方式来进行加载才可以使用
- 不可能有任何一个第三方包和核心模块的名字是一样的
- 先进入当前目录下的node_modules,模块加载的是node_modules/包名/package.json文件中main属性指向的文件所导出的模块
- 如果通过上面形式找不到入口模块,则会自动找该目录下的index.js并执行
- 如果node_modules不在当前目录下,则会一直往上一级目录找,直到当前磁盘根目录还找不到,则报错:Can not find module xxx
- 注:一个项目有且只有一个node_modules,不会出现多个,一般放在项目根目录,这样所有项目子目录都可以访问到
- 用户自定义模块
- require参数为路径
- ./当前目录,../上一级目录(都不可省略,后缀名可省略)
- 核心模块
# 包描述文件package.json
建议每一个项目的根目录下都有一个package.json文件(包描述文件),这个文件可以通过
npm init
的方式自动初始化出来。
- npm命令中的--save会在项目的package.json中生成"dependencies"(项目依赖)
- 建议执行
npm install 包名
的时候都加上--save,用来保存依赖项信息 - 如果node_modules文件不在了,可以直接通过
npm install
命令将package.json的dependencies中的所有依赖项都下载回来
# package.json和package-lock.json
npm5以后才加入了这个文件,当你安装包的时候,npm都会生成或者更新
package-lock.json
这个文件,且不用加上--save这个参数,它会默认保存依赖。
- package-lock.json里面包含了node_modules里面所有包的依赖信息(包括版本、下载地址),这样重新下载回node_modules会更快。
- 从文件来看,有一个
lock
称之为锁- 如果项目依赖了1.1.1版本,你重新install会加载最新版本,而不是1.1.1
- 而package-lock.json这个lock是用来锁定版本号的,防止自动升级新版
# npm命令行工具
只要安装了node就已经安装了npm
npm也有版本,可以通过以下命令查看
npm --version
1
升级npm:
npm install --global npm
1
# 常用命令
- npm init
- 生成package.json文件
- npm init -y可以跳过向导,快速生成
- npm install
- 一次性把dependencies选项中的依赖项全部安装
- install可以简写成 i
- npm install 包名
- 只下载
- npm install --save 包名
- 下载并保存依赖项(package.json文件中的dependencies选项)
- 简写:npm i -S 包名
- npm uninstall 包名
- 只删除,如果有依赖项会依然保存
- 简写:npm un 包名
- npm uninstall --save 包名
- 删除的同时会把依赖信息也去掉
- npm help
- 查看npm使用帮助
- npm 命令 --help
- 查看指定命令的使用帮助
# 解决npm被墙问题
- npm存储包文件的服务器在国外,有时候会被墙,速度很慢,所以我们要解决这个问题。
- http://npm.taobao.org/淘宝的开发团队把npm在国内做了一个备份(即淘宝npm镜像),每10分钟同步一次以保证尽量与官方服务同步。
安装淘宝的cnpm:
//该命令可在任意目录下执行,--global表示安装到全局,而非当前目录
npm install --global cnpm
1
2
2
接下来你安装包的时候把之前的npm替换成cnpm,举个栗子:
//这里走国外的npm服务器,速度比较慢
npm install jquery
//使用cnpm就会通过淘宝的服务器来下载jquery
cnpm install jquery
1
2
3
4
5
2
3
4
5
如果不想安装cnpm又想使用淘宝的服务器来下载:
npm install jquery --registry=https://registry.npm.taobao.org
1
但每次手动加参数很麻烦,可以将该选项加入配置文件,这要以后所有的npm install都会默认通过淘宝服务器来下载:
npm config set registry https://registry.npm.taobao.org
#查看npm配置信息
npm config list
1
2
3
4
2
3
4