Node.js中的第三方模块又叫做包,包是由第三方个人或团队开发出来的,可免费使用的。
包是基于内置模块封装出来的,提供了更高级的API
搜索你需要的包https://www.npmjs.com/
下载你需要的包(服务器)https://registry.npmjs.org/
npm,inc公司提供了一个包管理工具叫Node Pcakage Manager(npm包管理工具)
在项目中运行包,需要如下命令

npm install 包的完整名称

可以使用简写属性

npm i 包的完整路径

可以搜索文档来找使用方法

初次装包之后,在项目文件夹下多一个叫做node_modules的文件夹和package-lock.json的配置文件
node_modules 文件夹用来存放所有已安装到项目中的包。require()导入第三方包,是从这个目录中查找并加载包
package-lock.json 配置文件用来记录node_modules 目录下的每一个包的下载信息,例如包的名字、版本号、下载地址等等
注:不要手动修改node_modules 和package-lock.json中的任何代码
可以通过@来指定包的版本

npm i moment@2.24.0

包管理配置文件

npm规定,在项目根目录中,必须提供一个叫做package.json的包管理配置文件
在项目中,要把node_modules文件夹,添加到.gitigonre忽略文件中

快速创建package.json

npm 包管理工具提供了一个快捷命令,可以在执行命令时所处的目录中快速创建package包管理。
在创建了目录的时候执行,并且只需执行一次

npm init -y

注:上述命令只能在英文的目录下成功运行,不要存在英文和空格
package.json中,有一个dependencies,记录安装了哪些包

一次性安装所有的包

可以运行npm install(或npm i)一次性安装所有的依赖包,会读取package.json,并一次性下载到项目中

卸载包

使用npm uninstall

npm uninstall moment

执行npm uninstall后,会把卸载的包自动从package.json中的dependencies中移除

devDependencies

如果某些包只在项目开发阶段会用到,在项目上线之后不会用到,则建议把这些包记录到devDependencies中
如果开发和项目上线之后都要用到,则需要把这些包记录到dependencies中

npm i moment -D
#安装指定的包,记录到devDependencies中
npm install moment --save--dev
#上述命令时简写形式,等价于下面这个完整的写法

解决下包速度慢的问题

淘宝提供了一个npm镜像服务器(说谢谢阿里)

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

nrm

可以安装nrm工具,利用nrm提供的终端命令,快速切换镜像源

#通过npm包管理器,将nrm安装为全局可用的工具
npm i nrm -g
#查看所有可用的镜像源
npm ls
#将下包的镜像源切换为taobao镜像
nrm use taobao

包的分类

项目包

被安装在node_modules目录中的包,都是项目包,项目包又可以被分为两类。
开发依赖包(记录于devDependencies的包,只会在开发期间用到)
核心依赖包(记录于dependencies的包,在开发和项目上线之后都会用到)

全局包

在执行npm i 命令时,如果提供了-g参数,则会把包装为全局包
全局包默认安装到C:\Users\用户目录\AppDate\Roaming\npm\node_modules目录下

npm i 包名 -g # 全局安装指定的包
npm uninstall 包名 -g # 卸载全局安装的包

注:只有工具性质的包,才有全局安装的必要性,他们提供了好用的终端命令

规范的包结构

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

开发自己的包

新建一个文件夹,作为包的根目录,在文件夹中,新建3个文件
package.json(包管理配置文件),index.js(包的入口文件) README.md(包的说明文档)

初始化package.json

{
    "name":"包的名字(包名不能重复,可以到官网查)",
    "version":"1.0.0",
    "main":"index.js",
    "description": "包的描述信息",
    "keywords":["superxmy","yep"],
    "license": "ISC"
}

格式化时间

// 定义格式化时间的函数
function dateFormat(dateStr) {
    const dt = new Date(datestr)

    const y = dt.getFullYear()
    const m = padZero(dt.getMonth() + 1)
    const d = padZero(dt.getDate())

    const hh = padZero(dt.getHours())
    const mm = padZero(dt.getMinutes())
    const ss = padZero(dt.getSeconds())

    return `${y}-${m}-${d} ${hh}:${mm}:${ss}`
}
// 定义补零函数
function padZero(n) {
    return n > 9 ? n : '0' + n
}
// 向外暴露需要的成员
module.exports={
    dateFormat
}

转义HTML

// 定义转义HTML
function htmlEscape(htmlstr){
    return htmlstr.replace(/<|>|"|&/g,(match) =>{
        switch(match){
            case '<':
                return '&lt;'
            case '>':
                return '&gt;'
            case '"':
                return '&quot;'
            case '&':
                return '&amp;'            
        }
    })
}

// 向外暴露需要的成员
module.exports={
    htmlEscape
}

还原HTML

// 定义还原HTML
function htmlUnEscape(str){
    return str.replace(/&lt;|&gt;|&quot;|&amp;/g,(match)=>{
        switch(match){
            case '&lt;':
                return '<'
            case '&gt;':
                return '>'
            case '&quot;':
                return '"'
            case '&amp;':
                return '&'    
        }
    })
}
// 向外暴露需要的成员
module.exports={
    htmlUnEscape
}

模块化拆分

image-20220310154029279

// index.js文件

const date=require("./src/dataFormat")
const escape=require("./src/htmlEscape")
// 导入dataformat和htmlescape

// 向外暴露所需要的成员 
module.exports={
    ...date, //展开date
    ...escape
}

发布包

1.注册npm账号
2.在终端中执行npm login命令,依次输入用户名,密码,邮箱。注:在执行npm login之前,必须把下包的服务器切换为npm的官方服务器。
3.切换到包的根目录
4.运行npm publish命令

删除包

在终端中运行upm unpublish 包含 --force命令
注:该命令只能删除72h以内发布的包,被删除的包24h内不允许重复发布。发布包要慎重

模块的加载机制

模块在第一次加载会被缓存,这意味着多次调用require()不会导致模块的代码被执行。
内置模块的加载优先级最高,如果你在node_modules目录下有相同的包(如fs),依然会加载官方的包
使用require()加载自定义模块,需要以./或../开头,否则会作为内置模块或第三方模块加载。
如果使用require()导入自定义模块省略了拓展名,他会以以下顺序常识加载
1.按确切的文件名。2.补全.js拓展名进行加载。3.补全.json拓展名进行加载。4.补全.node拓展名进行加载。5.报错
如果传递给require()的不是内置模块,也没有./或../,则会从当前模块的父目录开始,尝试从/node_modules文件夹中加载第三方模块

当把目录作为模块标识符,传递给require()进行加载时,有三种加载方式
1.在目录下查找package.json文件,并查找main属性,作为加载入口
2.如果没有package.json文件,或main入口不存在或无法解析,则会加载目录下的index.js文件
3.若都不行则报错。

Q.E.D.