npm与包

238 阅读4分钟

什么是包

Node.js中的第三方模块又叫做

就像电脑计算机指的是相同的东西, 第三方模块指的是同一个概念, 只是叫法不同。

包的来源

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

注意Node.js中的包都是免费且开源的, 不需要付费即可免费下载使用。

为什么需要包

由于Node.js的内置模块仅提供了一些底层的API, 导致在基于内置模块进行项目开发时,效率很低。

包是基于内置模块封装出来的,提供了更高级、更方便的API, 极大的提高了开发效率

内置模块之间的关系, 类似于jQuery浏览器内置API之间的关系。

从哪里下载包

有一家IT公司, 叫npm, Inc,这家公司旗下有个网站: www.npmjs.com/ , 它是全球最大的包共享平台, 可以从这个网站上搜索到任何需要的包。

npm,Inc.公司提供了一个地址为registry.npmjs.org/ 的服务, 来对外共享所有的包, 我们可以从这个服务器上下载自己所需要的包。

注意

如何下载包

npm,Inc.公司提供了一个包管理工具, 我们可以使用这个包管理工具,从registry.npmjs.org/ 服务器把需要的包下载到本地使用。

这个包管理工具的名字叫Node Package Manager (简称 npm包管理工具), 这个包管理工具随着Node.js的安装包一起被安装到用户电脑上。

可以在终端中执行npm -v命令, 来查看自己电脑上所安装的npm包管理工具的版本号:

C02FC01UML85:bm-gas-report xiamin$ npm -v
6.14.17

npm初体验

格式化时间的传统做法

dateFormate.js

 // 1. 定义格式化时间的方法
 
 function dateFormat(dtStr) {
     let dt = new Date(dtStr)
     let y = dt.getFUllYear()
     let m = padZero(dt.getMonth())
     let d = padZero(dt.getDate())
     
     let hh = padZero(dt.getHours())
     let mm = padZero(dt.getMinutes())
     let ss = padZero(dt.getSeconds())
     
     return `${y}-${m}-${d}  ${hh}:${mm}:${ss}`
     
 }
 
 // 2. 定义补零函数
 
 function padZero(n) {
    return n > 9 ? n : '0' + n
 }
 
 module.exports = {
     dateFormat
 }

test.js

    // 导入自定义模块
    const TIME = require('./dateFormate.js')
    
    // 调用方法, 进行时间格式化
    const dt = new Date()
    
    const newDt = TIME.dateFormate(dt)
    
    console.log(newDt)
    

格式化时间用包的做法

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

在项目中安装包的命令

如果想在项目中安装指定名称的包, 需要运行如下命令: npm install 包的完整名称

上述的装包命令, 可以简写成如下格式: npm i 完整的包名称

初次装包后多了哪些文件

初次装包完成后, 在项目文件夹下多一个叫做node_modules的文件夹和package-lock.json的配置文件。

其中: node_modules文件夹用来存放所有已安装到项目中的包require()导入第三方包时, 就是从这个目录中查找并加载包。

package-lock.json配置文件用来记录node_module目录下的每个包的下载信息,例如包的名字、版本号、下载地址等。

注意点: 程序员不要手动修改node_modules或者package-lock.json文件中的任何代码, npm包管理工具会自动维护它们。

安装指定版本的包

默认情况下, 使用npm install命令安装包的时候, 会自动安装最新版本的包,如果需要安装指定版本的包, 可以在包名之后, 通过 @符号指定具体版本, 例如: npm i moment@2.22.2

包的语义化版本规定

包的版本是以点分十进制形式进行定义的, 总共有三位数字, 例如2.24.0 其中每一位数字所代表的含义如下: 第1位数字: 大版本 第2位数字: 功能版本 第3位数字: Bug修复版本

版本号提升的规则: 只要前面的版本号增长了, 则后面的版本号归零

包管理配置文件

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

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

如何记录项目中安装了哪些包

项目根目录中, 创建一个叫做package.json的配置文件, 即可用来记录项目中安装了哪些包。 从而方便剔除node_modules目录之后, 在团队成员之间共享项目的源代码。

注意: 在项目开发中, 一定要把node_modules文件夹,添加到.gitignore忽略文件夹中。

快速创建package.json

npm包管理工具提供了一个快捷命令, 可以在执行命令时所处的目录中, 快速创建package.json这个包管理,配置文件: npm init -y

注意

  1. 上述命令只能在英文的目录下成功运行!, 所以, 项目文件夹名称一定要使用英文命名, 不要使用中文, 不能出现空格
  2. 运行npm install命令安装包时, npm包管理工具会自动把包的名称版本号, 记录到package.json中。

dependencies节点

package.json文件夹中, 有一个dependencies节点, 专门用来记录您使用npm install命令安装了哪些包。

"dependencies": {
    "@grapecity/spread-excelio": "14.2.0",
    "@grapecity/spread-sheets": "14.2.0",
    "@grapecity/spread-sheets-barcode": "14.2.0",
    "@grapecity/spread-sheets-charts": "14.2.0",
    "@grapecity/spread-sheets-designer": "14.2.0",
    "@grapecity/spread-sheets-designer-resources-cn": "14.2.0",
    "@grapecity/spread-sheets-designer-vue": "14.2.0",
    "@grapecity/spread-sheets-languagepackages": "14.2.0",
    "@grapecity/spread-sheets-pdf": "14.2.0",
    "@grapecity/spread-sheets-print": "14.2.0",
    "@grapecity/spread-sheets-resources-zh": "14.2.0",
    "@grapecity/spread-sheets-shapes": "14.2.0",
    "@grapecity/spread-sheets-vue": "14.2.0",
    "af-table-column": "^1.0.3",
    "axios": "^0.26.1",
    "core-js": "^3.6.5",
    "crypto-js": "^4.1.1",
    "dayjs": "^1.11.2",
    "element-ui": "^2.15.6",
    "js-cookie": "^3.0.1",
    "jsencrypt": "^3.2.1",
    "lodash-es": "^4.17.21",
    "vue": "2.7.14",
    "vue-router": "^3.2.0",
    "vuedraggable": "^2.24.3",
    "vuex": "^3.4.0"
  },

一次性安装所有的包

当我们拿到一个剔除了node_modules的项目后, 需要先把所有包下载到项目中, 才能将项目运行起来。否则会报类似于下面的错误: Error: Connot find modules 'moment'

可以运行npm install命令(或npm i)一次性安装所有的依赖包:

     npm install

卸载包

可以运行npm uninstall命令, 来卸载指定的包:

    npm uninstall moment

注意npm uninstall命令执行成功后, 会把卸载的包,自动从package.json的dependencies中移除掉。

devDependencies节点

如果某些包只在项目开发阶段会用到, 在项目上线之后不会用到,则建议把这些包记录到devDependencies节点中。

与之对应的, 如果某些包在开发和项目上线之后都需要用到, 则建议把这些包记录到dependencies节点中。

您可以使用如下的命令, 将包记录到devDependencies节点中:

    // 简写
    npm i 包名 -D
    // 全写
    npm install 包名 --save-dev

解决下包速度慢的问题

为什么下包速度慢

在使用npm 下包的时候, 默认从国外的registry.npmjs.org/ 服务进行下载, 此时, 网络数据的传输需要经过漫长的海底光缆, 因此下包速度会很慢。

淘宝NPM镜像服务器

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

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

切换npm的下包镜像源

下包的镜像源, 指的是下包的服务器地址

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

nrm

为了更方便的切换下包的镜像源, 我们可以安装nrm这个小工具, 利用nrm提供的终端命令, 可以快速查看和切换下包的镜像源。

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

包的分类

项目包

那些被安装到项目node_modules目录中的包, 都是项目包。

项目包又分为两类, 分别是:

  • 开发依赖包 (被记录到 devDependencies节点中的包, 只在开发期间会用到)
  • 核心依赖包 (被记录到dependencies 节点中的包, 在开发期间和项目上线之后都会用到)
    npm i 包名 -D  # 开发依赖包 (会被记录到devDependencies 节点下)
    
    npm i 包名  # 核心依赖包 (会被记录到dependencies 节点下)

全局包

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

   npm i 包名 -g  # 安装全局包

   npm uninstall 包名 -g  # 卸载全局包

注意

  1. 只有工具性质的包, 才有全局安装的必要性。 因为他们提供了好用的终端命令。
  2. 判断某个包是否需要全局安装后才能使用, 可以参考官方提供的使用说明即可。

i5ting_toc

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

  # 将i5ting_toc安装为全局包
  npm install -g i5ting_toc

  # 调用i5ting_toc, 轻松实现md 转html的功能
  i5ting_toc -f 要转换的md文件路径 -o

规范的包结构

一个规范的包, 它的组成结构,必须符合以下3点要求

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

开发属于自己的包

需要实现的功能

  1. 格式化日期
  2. 转义HTML中的特殊字符
  3. 还原HTML中的特殊字符
// 1. 导入自己的包
const ohob  = require('ohob-utils')

<!-- 功能1: 格式化日期 -->
const dt = ohob.dataFormat(new Date())

console.log(dt)

<!-- 功能2: 转义HTML的特殊字符 -->
const htmlStr = `<h1 style="color:red;"> 你好! &copy;<span>小黄!</span></h1>`

const str = ohob.htmlEscape(htmlStr)
console.log(str)

<!-- 功能3: 还原HTML中的特殊字符 -->

初始化包的基本结构

1. 新建 ohob-tools文件夹, 作为包的根目录

2. 在ohob-tools文件夹中, 新建如下三个文件:

  • package.json (包管理配置文件)
  • index.js (包的入口文件)
  • README.md (包的说明文档)

3. 初始化package.json

{
  "name":"ohob-tools",
  "vesion": "1.0.0",
  "main": "index.js",
  "description": "提供了格式化时间, HTMLEScape的功能",
  "keywords": ["ohob", "dateFormat", "escape"],
  "license": "ISC"
}

4. 在index.js中定义格式化时间的方法

  // 格式化时间的方法
  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
  }


  <!-- 使用 -->
  <!-- const ohob = require() -->

5.在index.js中定义转义HTML的方法

  function htmlEscape(htmlStr) {
    return htmlStr.replace(/<|>|"|&/g, (match) => {
      switch(match) {
        case '<':
          return '&lt'
        case '>':
          return 'gt'
        case '"':
          return '&quot'
        case '&':
          return '&amp'
      }
    })
  }

6. 在index.js中定义还原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 '&'
      }
    })
  }

7. 将不同的功能进行模块化拆分

  1. 将格式化时间功能, 拆分到src-> dateFormate.js中
  2. 将处理HTML字符串的功能,拆分到src-> htmlEscape.js中
  3. 在index.js中, 导入两个模块, 得到需要向外共享的方法
  4. 在index.js中, 使用module.exports把对应的方法共享出去

8. 编写包的说明文档

包根目录中的README.md文件, 是包的使用说明文档, 通过它 ,我们可以事先把包的使用说明, 以markdown的格式写出来, 方便用户参考。

README文件中具体写什么内容, 没有强制性的要求; 只要能够清晰地把包的作用、用法、注意事项等描述清楚即可。

我们所创建的这个包的README 文档中, 会包含以下6项内容:

安装方式、导入方式、格式化时间、转义HTML中的特殊字符、还原HTML中的特殊字符、开源协议

发布包

注册npm账号

  1. 访问www.npmjs.com网站, 点击sign up按钮, 进入注册用户界面
  2. 填写账号相关的信息: Full Name、 Public Email、Username、Password
  3. 点击Create Account按钮, 注册账号
  4. 登录邮件, 点击验证链接, 进行账号的验证

登录npm账号

npm 账号注册完成后, 可以在终端中执行 npm login命令, 依次输入用户名, 密码, 邮箱后, 即可登录成功。

C02FC01UML85:ohob-tools ohob$ npm login
Username: ohob
Password: 
Email: (this IS public) 1004853727@qq.com
npm notice Please check your email for a one-time password (OTP)
Enter one-time password: 21991741
Logged in as ohob on https://registry.npmjs.org/.
C02FC01UML85:ohob-tools ohob$

注意:在运行npm login命令之前, 必须先把下包的服务器地址切换歪npm官方服务器, 否则会导致发布包失败!

把包发布到npm 上

把终端切换到包的根目录之后, 运行npm publish命令, 即可将包发布到npm上, (注意: 包名不能雷同

C02FC01UML85:ohob-tools ohob$ npm publish
npm notice 
npm notice 📦  ohob-tools@1.0.0
npm notice === Tarball Contents === 
npm notice 595B src/dateFormat.js
npm notice 801B src/htmlEscape.js
npm notice 299B index.js         
npm notice 205B package.json     
npm notice 0    README.md        
npm notice === Tarball Details === 
npm notice name:          ohob-tools                              
npm notice version:       1.0.0                                   
npm notice package size:  1.0 kB                                  
npm notice unpacked size: 1.9 kB                                  
npm notice shasum:        23a064b50304ee0ff6ab53f697bda7639df76079
npm notice integrity:     sha512-KsEPQMLJxvfHp[...]xbCHFZvfCQh4w==
npm notice total files:   5                                       
npm notice 
+ ohob-tools@1.0.0
C02FC01UML85:ohob-tools ohob$ 

删除已发布的包

运行 npm unpublish 包名 --force命令, 即可从npm删除已发布的包。

C02FC01UML85:ohob-tools ohob$ npm unpublish ohob-tools --force
npm WARN using --force I sure hope you know what you are doing.
- ohob-tools
C02FC01UML85:ohob-tools ohob$ 

注意:

  1. npm unpublish 命令只能删除72小时以内发布的包
  2. npm unpublish 删除的包, 在24小时内不允许重复发布
  3. 发布包的时候要慎重, 尽量不要往npm上发布没有意义的包!

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 6 天,点击查看活动详情