Node.js 模块与 Npm 包管理器

作者: 刘星
日期: 2021年4月07日

为了让 Node.js 的文件可以相互调用,Node.js 提供了一个基于CommonJS的模块系统。

模块是 Node.js 应用程序的基本组成部分,文件和模块是一一对应的。换言之,一个 Node.js 文件就是一个模块,这个文件可能是 JavaScript 代码、JSON 或者编译过的 C/C++ 扩展。

我们都知道 JavaScript 先天就缺乏一种功能:模块。浏览器环境的 js 模块划分只能通过src引入使用。然而,我们是辛运的的,我们在身在这个前端高速发展的时代*(当然了,这也是一种压力,一觉醒来又有新东西诞生了)*。高速发展下社区总结出了CommonJS这算得上是最为重要的里程碑。CommonJS 制定了解决这些问题的一些规范,而 Node.js 就是这些规范的一种实现。Node.js 自身实现了 require 方法作为其引入模块的方法,同时 NPM 也是基于 CommonJS 定义的包规范

Node 模块

每个文件就是一个模块,有自己的作用域。在一个文件里面定义的变量、函数、类,都是私有的,对其他文件不可见。commonJS 这套规范的出现使得用户不必再考虑变量污染,命名空间这些问题了。

小示例

// add.js
const add = (a, b)=>{
    return a+b
}
=============================
// index.js
const add = require('./add')

let result = add(1, 2)
console.log(result)

1.模块引用

require()这个方法存在接受一个模块标识,以此引入模块

const fs = require('fs')

Node 中引入模块要经历一下三步:

  1. 路径分析
  2. 文件定位
  3. 编译执行

Node 优先从缓存中加载模块。Node 的模块可分为两类:

  • Node 提供的核心模块
  • 用户编写的文件模块

Node 核心模块加载速度仅次于缓存中加载,然后路径形式的模=模块次之,最慢的是自定义模块。

2.模块定义

在模块中,上下文提供了exports来到处模块的方法或者变量。它是唯一出口

exports.add = function(){
  // TODO
}

在模块中还存在一个 module 对象,它代表模块自身,exports是它的属性。为了方便,Node 为每个模块提供一个 exports 变量,指向 module.exports。这等同在每个模块头部,有一行这样的命令

var exports = module.exports

不能直接将 exports 变量指向一个值,因为这样等于切断了exportsmodule.exports的联系

exports 和 module.exports 区别

exports 仅仅是 module.exports 的一个地址引用。nodejs 只会导出 module.exports 的指向,如果 exports 指向变了,那就仅仅是 exports 不在指向 module.exports,于是不会再被导出

  • module.exports 才是真正的接口,exports 只不过是它的一个辅助工具。最终返回给调用的是 module.exports 而不是 exports。
  • 所有的 exports 收集到的属性和方法,都赋值给了 module.exports。当然,这有个前提,就是 module.exports 本身不具备任何属性和方法。如果,module.exports 已经具备一些属性和方法,那么 exports 收集来的信息将被忽略
  • Node 开发者建议导出对象用 module.exports,导出多个方法和变量用 exports

npm 模块管理器

npm的出现则是为了在 CommonJS 规范的基础上,实现解决包的安装卸载,依赖管理,版本管理等问题,npm不需要单独安装。在安装 Node 的时候,会连带一起安装npm

  • 允许用户从 NPM 服务器下载别人编写的第三方包到本地使用。
  • 允许用户从 NPM 服务器下载并安装别人编写的命令行程序到本地使用。
  • 允许用户将自己编写的包或命令行程序上传到 NPM 服务器供别人使用。

npm 包

一个符合 CommonJS 规范的包应该是如下这种结构:

  • 一个 package.json 文件应该存在于包顶级目录下
  • 二进制文件应该包含在 bin 目录下。
  • JavaScript 代码应该包含在 lib 目录下。
  • 文档应该在 doc 目录下。
  • 单元测试应该在 test 目录下

package.json

  • name:包名,需要在 NPM 上是唯一的,小写字母和数字组成可包含_ - .但不能有空格
  • description:包简介。通常会显示在一些列表中
  • version:版本号。一个语义化的版本号(http://semver.org/ ),通常为 x.y.z。该版本号十分重要,常常用于一些版本控制的场合
  • keywords:关键字数组。用于 NPM 中的分类搜索
  • maintainers:包维护者的数组。数组元素是一个包含 name、email、web 三个属性的 JSON 对象
  • contributors:包贡献者的数组。第一个就是包的作者本人。在开源社区,如果提交的 patch 被 merge 进 master 分支的话,就应当加上这个贡献 patch 的人。格式包含 name 和 email
  • bugs:一个可以提交 bug 的 URL 地址。可以是邮件地址(mailto:[email protected]),也可以是网页地址
  • licenses:包所使用的许可证
  • repositories:托管源代码的地址数组
  • dependencies:当前包需要的依赖。这个属性十分重要,NPM 会通过这个属性,帮你自动加载依赖的包

除了前面提到的几个必选字段外,还有一些额外的字段,如 bin、scripts、engines、devDependencies、author

npm 的使用

行下面的命令,查看各种信息

# 查看 npm 命令列表
$ npm help

# 查看各个命令的简单用法
$ npm -l

# 查看 npm 的版本
$ npm -v

# 查看 npm 的配置
$ npm config list -l

npm 命令安装模块

Node 模块采用npm install命令安装。

每个模块可以“全局安装”,也可以“本地安装”。“全局安装”指的是将一个模块安装到系统目录中,各个项目都可以调用。一般来说,全局安装只适用于工具模块。“本地安装”指的是将一个模块下载到当前项目的node_modules子目录,然后只有在项目目录之中,才能调用这个模块。

# 本地安装
$ npm install <package name>

# 全局安装
$ sudo npm install -global <package name>
$ sudo npm install -g <package name>

指定所安装的模块属于哪一种性质的依赖关系

  • –save:模块名将被添加到 dependencies,可以简化为参数-S
  • –save-dev: 模块名将被添加到 devDependencies,可以简化为参数-D
$ npm install <package name> --save
$ npm install <package name> --save-dev

卸载模块

我们可以使用以下命令来卸载 Node.js 模块

$ npm uninstall <package name>

更新模块

我们可以使用以下命令来更新 Node.js 模块

$ npm update <package name>

创建模块

我们可以使用以下命令来创建 Node.js 模块

$ npm init

npm init创建模块会在交互命令行帮我们生产 package.json 文件

$ npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.

See `npm help json` for definitive documentation on these fields
and exactly what they do.

Use `npm install <pkg> --save` afterwards to install a package and
save it as a dependency in the package.json file.

Press ^C at any time to quit.
name: (node_modules) test                   # 模块名
version: (1.0.0) 
description: Node.js 测试模块                # 描述
entry point: (index.js) 
test command: make test
git repository: https://github.com/test/test.git  # Github 地址
keywords: 
author: 
license: (ISC) 
About to write to ……/node_modules/package.json:      # 生成地址

{
  "name": "test",
  "version": "1.0.0",
  "description": "Node.js 测试模块",
  ……
}


Is this ok? (yes) yes

以上的信息,你需要根据你自己的情况输入。默认回车即可。在最后输入 “yes” 后会生成 package.json 文件。

模块发布

发布模块前首先要在 npm 注册用户

$ npm adduser
Username: liuxing
Password:
Email: (this IS public) [email protected]

然后

$ npm publish

现在我们的 npm 包就成功发布了。

更多请查看 npm 帮助信息npm 文档

推荐推荐

文档信息

版权声明:署名-非商业性使用-禁止演绎 4.0 国际(CC BY-NC-ND 4.0)

原文链接:https://www.liuxing.io/blog/node-modules-and-npm/

发表日期:2021年04月07日


相关文章

node 打造微信个人号机器人

现在,日常生活已经离不开微信,本文将会抛砖引玉演示如何使用wechaty操作微信个人号做一些有意思的东西,可以实现自动通过好友请求、关键词回复、自动拉群等功能。大大提高了社群运营的效率。 wechaty(https://github.com/Chatie/wechaty)是一款开源的微信个人号 SDK,进行了一系列的封装,提供简单好用的接口,然后开发者可以在其之上进行微信机器人的开发。你可以用它来做很多事:

2018年4月25日

Node.js 使用 Nodemailer 发送邮件

电子邮件是—种用电子手段提供信息交换的通信方式,是互联网应用最广的服务。通过网络的电子邮件系统,用户可以以非常低廉的价格(不管发送到哪里,都只需负担网费)、非常快速的方式(几秒钟之内可以发送到世界上任何指定的目的地),与世界上任何一个角落的网络用户联系。 在很多项目中,我们都会遇到邮件注册,邮件反馈等需求。在 node 中收发电子邮件也非常简单,因为强大的社区有各种各样的包可以供我么直接使用。Nodemailer包就可以帮助我们快速实现发送邮件的功能。

2017年12月02日

Koa 快速入门教程(一)

Koa 是由 Express 原班人马打造的,致力于成为一个更小、更富有表现力、更健壮的 Web 框架,采用了async和await的方式执行异步操作。

2017年11月18日

最近更新

Curl 使用指南

Curl 是一个常用的命令行数据传输工具, 可以方便的从命令行创建网络请求

2021年5月04日

JavaScript 中的分号

JavaScript 代码到底加不加分号。本文带你了解 JavaScript 的分号自动插入机制,以及哪些情况必须加分号

2021年5月02日