nodejs学习笔记-05模块化,npm与包

110 阅读8分钟

模块化

1.模块化的好处

1.1 什么是模块化?

模块化是指解决一个复杂问题的时候,自顶向下逐层把系统划分成若干模块的过程对于整个系统来说,模块是可组合,可分解,可更换的单元

编程领域中的模块化就是遵循固定的规则,把一个大文件拆成独立并互相依赖的多个小模块 把代码进行模块化拆分的好处:

  1. 提高了代码的复用性
  2. 提高了代码的可维护性
  3. 可以实现按需加载

1.2 模块化规范

模块化规范就是对代码进行模块化的拆分与组合时,需要遵循的那些规则

比如:使用什么样的语法格式引用模块,在模块中使用什么样的语法格式向外暴露成员

模块化规范的好处:大家都遵循同样的模块化规范写代码,降低了沟通的成本,极大的方便了各个模块之间的相互调用,利人利己

2.Node.js中模块化

2.1 Node.js中根据模块来源的不同,将模块分为了3大类,分别为:

  • 内置模块(由Node.js官方提供的,比如:fs,path,http)
  • 自定义模块(用户创建的每个js文件,都是自定义模块)
  • 第三方模块(由第三方开发出来的模块,并非官方提供的内置模块,也不是用户创建的自定义模块,使用前需要先下载)

2.2 模块的加载

使用强大的require()方法,可以加载所需要的 内置模块,用户自定义模块,第三方模块进行使用,例如

// 1.加载内置的fs模块
const fs = require('fs')

// 2.加载用户自定义模块(require()里面写的时自定义模块的路径)
const custom = require('./custom.js')

// 3.加载第三方模块(需要先下载第三方模块)
const moment = require('moment')

注意: 使用reuqire()方法加载其他模块时,会执行被加载模块中的代码

2.3.Node.js中的模块化作用域

  1. 什么是模块作用域

    函数作用域类似,在自定义模块中定义的变量,方法等成员,只能在当前模块内被访问,这种模块级别的访问限制就叫做模块作用域

  2. 模块作用域的好处: 防止了全局变量污染的问题

  3. 向外共享模块作用域中的成员

    • module对象 在每个.js自定义模块中都有一个module对象,它里面存储了和当前模块有关的信息,如下图: image.png
    • module.exports对象 在自定义模块中,可以使用module.exports对象,将模块内的成员共享出去,供外界使用,外界使用require()方法导入自定义模块时,得到的就是module.exports所指向的对象 image.png
image.png image.png

注意:使用require()方法导入模块,导入的结果,永远以module.exports指向的对象为准 image.png

2.4模块化-exports对象

由于module.exports单词写起来比较复杂,为了简化向外共享成员的代码,Node提供了exports对象,默认情况下,exports和module.exports指向同一个对象,最终共享的结果,还是以module.exports指向的对象为准

console.log('exports',exports) // {}
console.log('module.exports',module.exports) // {}
console.log(exports === module.exports) // true

exportsmodule.exports的使用误区: 时刻谨记:require()导入模块时,得到的永远是module.exports指向的对象,为了防止混乱,建议不要再同一个模块中同时使用exports和module.exports

image.png

2.5Node.js中模块化-CommonJS模块化规范

node.js遵循了CommonJS模块化规范,commonJS规定了模块的特性各模块之间如何相互依赖

cimmonJS规定:

  1. 在每个模块内部,module变量代表当前模块
  2. module变量是一个对象,他的exports属性(即module.exports)是对外的接口
  3. 加载某个模块,其实是加载该模块的module.exports属性,require()方法用于加载模块

npm与包

1.npm与包

node.js中的第三方模块又叫做,不同于Node.js中的内置模块和自定义模块,包是由第三方个人或者团队开发出来的,免费供给所有人使用

  1. 为什么需要包?

由于Node.js的内置模块仅提供了一些底层的API,导致在基于内置模块进行项目开发的时候效率很低,包是基于内置模块封装出来的,提供了更高级、更方便的API,极大的提高了开发效率 包与内置模块之间的关系,类似于Jquery和浏览器内置API之间的关系

国外有家IT公司叫做npm,Inc,它提供了一个网站为全球最大的包共享平台,这家公司还提供了一个地址为registry.npmjs.org/ 的服务器,用来共享所有的包,我们可以通过这个服务器下载所需要的包

  1. 如何下载包

    可以使用包管理工具,从服务器 registry.npmjs.org/ 把需要的包下载到本地使用,可以使用包管理工具Node Package Manager(简称:npm包管理工具),这个包管理工具会随着Node.js的安装被一起安装到用户的电脑上,可以在终端执行npm -v 命令,来查看自己电脑上所安装的npm包管理工具的版本号,如下:

    image.png

npm初体验 (以时间格式化为例)

1.1传统的格式化时间做法:

  1. 创建格式化时间的自定义模块
  2. 定义格式化时间的方法
  3. 创建补零函数
  4. 暴露出去格式化时间的函数
  5. 导入格式化时间的自定义模块
  6. 调用格式化时间的函数
// 自定义格式化时间的模块
function dateFormat(dtStr) {
  const dt = new Date(dtStr);
  const y = dt.getFullYear();
  const m = padZero(dt.getMonth() + 1);
  const h = padZero(dt.getDate());
  const hh = padZero(dt.getHours());
  const mm = padZero(dt.getMinutes());
  const ss = padZero(dt.getSeconds());
  return `${y}-${m}-${h}-${hh}-${mm}-${ss}`;
}
// 定义补零函数
function padZero(n) {
  return n > 9 ? n : "0" + n;
}
// 暴露dateFormat方法
module.exports = {
  dateFormat,
};=
// 导入自定义格式化时间的模块
const TIME = require("./dataFormat");
// 调用方法,进行时间的格式化
const dt = new Date();
console.log("dt", dt);
const newDt = TIME.dateFormat(dt);
console.log("newDt", newDt);

image.png

1.2使用第三方模块格式化时间做法:

moment.js

  1. 使用npm包管理工具,在项目中安装格式化时间的包momentnpm install moment
  2. 使用reuqire()方法导入时间格式化的包
  3. 参考moment的官方API文档对时间进行格式化
// 导入moment包
const moment = require('moment')
const dt = moment().format('YYYY-MM-DD HH:mm:ss')
console.log('dt',dt)

image.png

初次装包完成之后,我们发现在项目文件夹中多了一个叫做node_modules的文件夹和package-lock.json的配置文件

node_modules文件夹用来存放所有已安装到项目中的包

package_lock.json文件用来记录node_modules目录下的每一个包的下载信息,比如包的名字,版本号,下载地址等等

2.包管理配置文件

npm规定,在项目的根目录中必须提供一个叫做package.json的包管理配置文件,用来记录与项目有关的一些配置信息,例如:

  • 项目的名称,版本号,描述等
  • 项目中都用到了哪些包
  • 哪些包只在开发期间会用到
  • 哪些包在开发部署阶段都需要用到

快速创建package.json:npm init -y

注意:

  1. 上述命令只能在英文的目录下成功运行,所以,项目文件夹的名称一定要使用英文命名,不能出现中文,不能出现空格

  2. 运行npm install 命令安装包的时候,npm包管理工具会自动把包的名称版本号,记录到package.json中

2.1 dependencies节点

在package.json文件中,专门用来记录项目中使用nom install命令安装了哪些包

image.png

运行 npm i 或者 npm install 命令可以一次性安装所有的包

2.2 devDependencies节点

如果某些包只在项目开发阶段会用到,在项目上线之后不会用到,则建议把这些包记录到devDependencies节点中,与之对应,如果某些包在开发项目上线之后都需要用到,则建议将这些包记录到depenencies节点中

可以通过npm install 包的名称 -D或者npm install 包的名称 --save-dev将所安装的包记录在devDependencies节点中

3.解决下包速度慢的问题

使用淘宝NPM镜像服务器,淘宝在国内搭建了一个服务器,专门把国外官网服务器上的包同步到国内的服务器,然后在国内提供下包的服务,从而极大地提高了下包的速度

image.png

镜像(mirroring)是一种文件存储形式,一个磁盘上的数据在另一个磁盘上存在一个完全相同的副本即为镜像

// 查看当前下包镜像源
npm config get registry
// 将当前下包的镜像源切换为淘宝镜像源
npm config set registry=https://registry.npm.taobao.org/

3.1工具nrm

为了更方便的切换下包的镜像源,可以安装nrm小工具

//安装nrm
npm i nrm -g
// 查看所有的可用镜像源
nrm ls
// 将下包镜像源切换为 taobao镜像
nrm use taobao

image.png

3.2 i5ting_toc

i5ting_toc是一个可以把md文档转为html页面的小工具,使用步骤如下:

// 安装
npm install -g i5ting_toc
// 调用i5ting_toc,轻松实现md转 html的功能
i5ting_toc -f 要转换的md文件路径 -o

3.3 规范的包结构

在清楚了包的概念,以及如何下载和使用包之后,我们可以了解一下包的内部结构 一个规范的包,他的组成目录,必须符合以下三点要求:

  1. 包必须以单独的目录而存在
  2. 包的顶级目录下必须包含package.json这个包管理配置文件
  3. package.json中必须包含name,version,main这三个属性,分别代表包的名字,版本号,包的入口