node.js学习笔记(一)模块和包管理

原创 西城寻风 随笔 node.js笔记 258阅读 2017-05-04 15:54:50 举报

概念:模块(Module)和包(Package)是Node.js最重要的支柱。开发一个具有一定规模的程序不可能只用一个文件,通常需要把各个功能拆分、分装、然后组合起来。模块正式为了实现这种方式而诞生,在浏览器JavaScript中,脚本模块的拆分和组合通常使用HTML的script标签来实现,Node.js提供了require函数来调用其他模块,而且模块都是基于文件,机制非常简单,模块和包的区别是透明的,因此经常不作区分。

一、模块
1、模块概念
模块是 Node.js 应用程序的基本组成部分,文件和模块是一一对应的。换言之,一个Node.js 文件就是一个模块,这个文件可能是 JavaScript 代码、 JSON 或者编译过的 C/C++ 扩展。
var http=require('http'),其中http是Node.js的一个核心模块,通过require函数获取这个模块,然后使用其中的对象。
二、模块创建及加载
(1)创建
Node.js提供了exports和require两个对象,其中exports是模块公开的接口,require用于从外部获取一个模块的接口,即获取模块的exports对象。
新建module.js的文件
javascript 代码

在同一目录下创建 getmodule.js,内容是:
javascript 代码

运行 node getmodule.js 结果 hello novaline

注:module.js 通过 exports 对象把 setName 和 sayHello 作为模块的访问接口,在 getmodule.js 中通过 require('./module') 加载这个模块,然后就可以直接访问 module.js 中 exports 对象的成员函数了。npm 提供的上万个模块都是通过这种简单的方式搭建起来的。

2、单次加载
无论调用多少次 require, 获得的模块都是同一个
3、覆盖exports
有时候我们只是想把一个对象封装到模块中,例如:

javascript 代码

此时我们在其他文件中需要通过require('./singleobject').Hello 来获取Hello对象,这略显冗余,可以用下面方法稍微简化:

javascript 代码

这样就可以直接获得这个对象了:

javascript 代码

注意,模块接口的唯一变化是使用 module.exports = Hello 代替了exports.Hello = Hello。在外部引用该模块时,其接口对象就是要输出的 Hello 对象本身,而不是原先的exports。

事实上, exports 本身仅仅是一个普通的空对象,即 {},它专门用来声明接口,本质上是通过它为模块闭包的内部建立了一个有限的访问接口。因为它没有任何特殊的地方,所以可以用其他东西来代替,譬如我们上面例子中的 Hello 对象。

警告:不可以通过对 exports 直接赋值代替对 module.exports 赋值。exports 实际上只是一个和 module.exports 指向同一个对象的变量,它本身会在模块执行结束后释放,但 module 不会,因此只能通过指定module.exports 来改变访问接口。

三、创建包
包是在模块基础上更深一步的抽象,它将某个独立的功能封装起来,用于发布、更新、依赖管理和版本控制。 Node.js 根据 CommonJS 规范实现了包机制,开发了npm来解决包的发布和获取需求。
Node.js 的包是一个目录,其中包含一个 JSON 格式的包说明文件 package.json。严格符 合 CommonJS 规范的包应该具备以下特征:
package.json 必须在包的顶层目录下;
二进制文件应该在 bin 目录下;
JavaScript 代码应该在 lib 目录下;
文档应该在 doc 目录下;
单元测试应该在 test 目录下。
Node.js 对包的要求并没有这么严格,只要顶层目录下有 package.json,并符合一些规范 即可。当然为了提高兼容性,建议在制作包的时候,严格遵守 CommonJS 规范。

   1.作为文件夹的模块
   模块与文件是一一对应的。文件不仅可以是 JavaScript 代码或二进制代码,还可以是一个文件夹。最简单的包,就是一个作为文件夹的模块。
   例子:
   建立一个叫做somepackage 的文件夹,在其中创建 index.js,内容如下:
  **javascript 代码**
    然后在 somepackage 之外建立 getpackage.js  内容如下:
  **javascript 代码**
   运行node getpackage.js 结果输出 hello.
   使用这种方法可以把文件夹封装为一个模块,即所谓的包。包通常是一些模块的集合,在模块的基础上提供了更高层的抽象,相当于提供了一些固定接口的函数库。

     通过定制package.json,我们可以创建更复杂、更完善、更符合规范的包用于发布。

2.package.json
Node.js 在调用某个包时,会首先检查包中 package.json 文件的 main 字段,将其作为包的接口模块,如果 package.json 或 main 字段不存在,会尝试寻找 index.js 或 index.node 作为包的接口。
package.json 是 CommonJS 规定的用来描述包的文件,完全符合规范的 package.json 文件应该含有以下字段。

name:包的名称,必须是唯一的,由小写英文字母、数字和下划线组成,不能包含空格。
description:包的简要说明。
version:符合语义化版本识别规范的版本字符串。
keywords:关键字数组,通常用于搜索。
maintainers:维护者数组,每个元素要包含 name、email(可选)、web(可选)字段。
contributors:贡献者数组,格式与maintainers相同。包的作者应该是贡献者数组的第一个元素。
bugs:提交bug的地址,可以是网址或者电子邮件地址。
licenses:许可证数组,每个元素要包含type(许可证的名称)和url(链接到许可证文本的地址)字段。
repositories:仓库托管地址数组,每个元素要包含type仓库的类型,如git )、url(仓库的地址)和 path(相对于仓库的路径,可选)字段。
dependencies:包的依赖,一个关联数组,由包名称和版本号组成。

一个完全符合CommonJS规范的**package.json**

示例:

四、Node.js 包管理器
Node.js包管理器,即npm是 Node.js 官方提供的包管理工具,它已经成了 Node.js 包的 标准发布平台,用于 Node.js 包的发布、传播、依赖控制。npm 提供了命令行工具,使你可 以方便地下载、安装、升级、删除包,也可以让你作为开发者发布并维护包。

 1.获取一个包
  **javascript 代码**
 安装express ,可以在命令行运行:
 **javascript 代码**
 说明:npm 在获取 express 的时候还将自动解析其依赖,并获取 express 依赖的 mime、 mkdirp、qs 和 connect。

2.本地模式和全局模式

npm在默认情况下会从http://npmjs.org搜索或下载包,将包安装到当前目录的node_modules子目录下。

默认情况下我们使用 npm install命令就是采用本地模式,即把包安装到当前目录的node_modules 子目录下。 Node.js的 require 在加载模块时会尝试搜寻 node_modules子目录,因此使用 npm 本地模式安装的包可以直接被引用。

npm 还有另一种不同的安装模式被成为全局模式,使用方法为:**javascript 代码**
注:使用全局模式多数时候并不是因为许多程序都有可能用到它,为了减少多重副本而使用全局模式,而是因为本地模式不会注册 PATH环境变量。

当我们要把某个包作为工程运行时的一部分时,通过本地模式获取,如果要 在命令行下使用,则使用全局模式安装。

 提示:在 Linux/Mac 上使用 npm install -g 安装时有可能需要 root 权限, 因为 /usr/local/lib/node_modules/ 通常只有管理员才有权写入。

3.创建全局链接

npm 提供了一个有趣的命令 npm link, 它的功能是在本地包和全局包之间创建符号链接。我们说过使用全局模式安装的包不能直接通过 require 使用,但通过 npm link命令可以打破这一限制。

4.包的发布
 在发布之前,首先需要让我们的包符合 npm 的规范, npm 有一套以 CommonJS 为基础包规范,但与 CommonJS并不完全一致,其主要差别在于必填字段的不同。通过使用 npm init 可以根据交互式问答产生一个符合标准的 package.json,创建一个名为novaline的目录,然后在这个目录中运行npm init:
评论 ( 0 )
最新评论
暂无评论

赶紧努力消灭 0 回复