1、模块化的基本概念
模块化是指解决一个复杂的问题时,自顶向下逐层把系统划分成若干模块的过程。对于整个系统来说,模块是可组合、分解和更换的单元。
(1)模块化的优点
遵循固定规则,把大文件拆分成对立并相互依赖的多个小模块
好处:
- 提高代码的复用性;
- 提高代码的可维护性;
- 可以按需加载;
(2)模块化规范
用什么语法格式引用模块,用什么语法格式向外暴露成员
2、CommonJS规定内容
CommonJS规定了模块特性和各模块之间如何相互依赖。
① 每个模块内部,module变量代表当前模块。
② module变量是一个对象,它的exports属性(module.exports)是对外的接口。
③ 加载某个模块其实是加载该模块的module.exports属性,用require()方法用于加载模块。
3、Node.js中模块三大分类
- 内置模块(内置模块是由Node.js官方提供的,例如path,fs,http)
- 自定义模块(用户创建的每个JS文件都是自定义模块)
- 第三方模块(由第三方开发的模块,并非官方提供的内置模块,也不是用户创建的自定义模块,使用前需要下载)
(1)require()方法可以加载需要的内置模块、用户自定义模块、第三方模块进行使用。
const http = require('http');
使用require()方法加载其他模块时,会执行被加载模块中代码。
在使用require()加载用户自定义模块期间,可以省略.js的后缀名。
(2)模块作用域
在自定义模块中的变量以及方法等成员,只能在当前模块内被访问,这种模块级别的访问限制叫做模块作用域。(防止全局变量污染问题)
(3) 向外共享模块作用域中的成员
① module对象 :每个JS自定义模块中都有一个module对象,里面存储了当前模块有关信息。
② module.exports 对象: 在自定义模块中,将模块内的成员共享出去,供外界使用。(外界用require方法导入的自定义模块时,就是module.export所指对象)
// 文件一 module.js
module.exports.username = 'sss'
module.exports.sayHello = function(){
console.log('Hello!')
}
// 文件二
const m = require('./module');
console.log(m);
// 文件二引用文件一结果 m打印结果
// { username: 'sss', sayHello: [Function (anonymous)] }
使用require()方法导入模块时,导入的结果永远module.exports指向的对象为准
③ exports对象 : 默认情况下 exports和module.exports指向同一个对象。最终共享的结果还是以module.exports指向的对象为准
1、require() 模块,永远都是module.export所指对象
4、npm包管理
(1)包的概念
Node.js中第三方模块叫做包。
包是由第三方个人或者团队开发出来的,基于内置模块封装出来的,免费共所有人使用,目的提高开发效率。
http://www.npmjs.com/
(2)常用指令
查看npm版本: npm -v
安装包:npm install 包完整名称/ npm i 包完整名称
安装指定版本的包(无需卸载):npm i 包名称@版本号
卸载:npm uninstall 包名称
版本号是点分十进制:第一位大版本,第二位功能版本,第三位bug修复版本,只要前面版本号增长了,后面版本就会归零。
(3)包的导入
// 导入需要的包,名称就是装包的名称
const moment = require(moment)
安装完成包后,项目文件夹多了node_modules和package-lock.json配置文件
node_modules:所有已安装到项目里的包
package-lock.json:包下载信息
(4)包管理配置文件(package-lock.json)
因为第三方包过大,共享时剔除node_modules
创建package.json: npm init -y(路径项目文件夹不能有中文空格)
dependencies:记录npm哪些包,开发和上线之后都用
devDependencies节点:开发用,上线后不用 npm i 包名称 -D
(5)使用cnpm与nrm
解决下包慢的问题:淘宝NPM镜像服务器
切换npm下包镜像源
// 查看当前下包镜像源
npm config get registry
// 更换为淘宝镜像
// https://registry.npm.taobao.org/已经过期了
npm config set registry=npm config set registry https://registry.npmmirror.com
// 检查是否下载成功
npm config get registry
nrm:快速查看和切换下包的镜像源
// 通过npm包管理器,将nrm安装为全局可用的工具
npm i nrm -g
// 查看所有可用镜像源
nrm ls
// 将下包镜像源切换为淘宝镜像
nrm use taobao
5、规范的包结构
包的分类:项目包、全局包
项目包分为开发依赖包与核心依赖包,开发依赖包只在开发期间用到,核心依赖包在开发期间与项目上线都会用到
全局包:安装到node_modules中 安装时 npm i 包名称 -g
安装i5ting_toc:npm install -g i5ting_toc
// 调用i5ting_toc,实现md文件转换html功能
i5ting_toc -f 要转换md文件路径 -o
包的规范
一个规范的包,它的组成结构,必须符合以下3点要求:
① 包必须以单独的目录而存在;
② 包的顶级目录下要必须包含 package.json 这个包管理配置文件;
③ package.json 中必须包含 name,version,main 这三个属性,分别代表包的名字、版本号、包的入口,
6、发布包
以test-tools举例
(1)初始化包的基本结构
① 新建 test-tools 文件夹,作为包的根目录
② 在 test-tools 文件夹中,新建如下三个文件:
package.json (包管理配置文件)
index.js (包的入口文件)
README.md(包的说明文档)
(2) 初始化package.json
{
"name": "test-tools",
"version": "1.0.0",
"main": "index.js",
"description":"提供了xxxx的功能",
"keywords". ["xx1", "xx2", "xx3"],
"license": "IsC"
}
(3) 设计入口文件(main属性设计的入口文件)
// index.js
function xx1(){
...
return
}
function xx2(){
...
return
}
...
// 向外暴露需要成员
module.exports ={
xx1;
}
(4) 模块化拆分
① 将不同功能拆分到不同js中去
② 在index.js中导入两个模块
③ 在index.js中,使用module.exports把对应方法共享出去
(5)把包发布到npm上
编写说明文档README.md是包的说明文档,markdown格式
安装方式、导入方式、功能模块的说明、开源协议
① 注册npm账号
② 终端登录npm账号(先切换官方服务器,不能用淘宝服务器)。上传包。
// 登录
npm login
// 把包发布到npm上,包名不能重复
npm publish
③ 如果要删除已发布包(72h 以内),删除后24小时不能重复发布
npm unpublish 包名称 --force
7、模块加载机制
(1)优先从缓存中加载:模块第一次加载后会缓存,多次调用require不会执行多次
(2)内置模块加载优先级最高
(3)自定义模块必须以./或者../开头路径标识符,扩展名加载顺序:确切文件名加载-.js-.json-.node-加载失败
(4)第三方模块加载机制,不是内置模块,也没有相对路径开头,从当前目录开始,尝试从node_modules文件中加载第三方模块,直到文件系统根目录为止
(5)目录作为模块,先寻找package.json,找main属性作为入口,如果没有或者入口不能解析,则从加载目录下找寻index.js文件,如果还是找不到,则报错:Error:Cannot find module 'xxx'