NPM与包
Node组织了自身的核心模块,也使得第三方文件模块可以有序地编写和使用。但是在第三方模块中,模块与模块之间仍然是散列在各地的,相互之间不能直接引用。在模块之外,包和NPM是将模块联系起来的一种机制。 - 朴灵
NPM遵循CommonJS的包规范。CommonJS包规范定义包结构和包描述文件两个部分,前者用于组织包中的各种文件,后者则用于描述包的相关信息,以供外部文件读取分析。
下面分别介绍一下包结构和包描述文件。
包结构
符合CommonJS规范的包目录应该包含一下文件:
1. package.json:包描述文件
2. bin:用于存放可执行二进制文件的目录
3. lib:用于javascript代码的目录
4. doc:用于存放文档的目录
5. test:用于存放单元测试用例的代码
可以看到,CommonJS包规范从文档、测试等方面都做过考虑。
包描述文件与NPM
包描述文件是一个JSON格式的文件(package.json),位于包的根目录下,是包的重要组成部分。NPM的所有行为都有包描述文件的字段息息相关。
CommonJS对于包描述文件定义了以下必须的字段。
1. name:包名
包名由小写的字母和数字组成,可以包含.、_和-,不允许出现空格。包名必须是唯一的。
2. description:包简介
3. version:版本号
版本号十分重要,常常用于一些版本控制的场合。
4. keywords:关键词数组
用于分类搜索。一个好的关键词数组有利于快速找到编写的包。
5. maintainers:包维护者列表
每个维护者由name、email和web三个属性组成,NPM通过此属性进行权限验证。
6. contributors:贡献者列表
贡献者列表第一个贡献者是包作者本人。其他贡献者是对此包有过贡献的人。
7. bugs:一个反馈bug的网页地址或邮件地址
8. licenses:许可证列表
当前包使用的许可证列表,表明这个包可以在哪些许可证下使用。
9. repositories:托管源代码的位置列表
表明可以通过哪些方式和地址访问包的源代码。
10. dependencies:当前包所需要依赖的包列表
这个属性十分重要,NPM会通过这个属性帮助自动加载依赖的包。
以上都是必须字段,除了必选字段,规范还定义了一些可选字段。
1. homepage:当前包的网站地址
2. os:操作系统支持列表
这些操作系统的取值包括aix、freebsd、linux、macos、solaris、vxworks、windows。
3. cpu:CPU架构的支持列表
有效的架构名称为arm、mips、ppc、sparc、x86和x86_64。
4. engine:支持的JavaScript引擎列表
有效的引擎取值包括ejs、flusspfered、gpsee、jsc、node和v8等。
5. builtin:标志当前包是否是内建在底层系统中的标准组件
6. directories:包目录说明
7. implements:实现规范的列表
标志当前包实现了CommonJS的哪些规范。
8. scripts:脚本说明对象
主要被包管理用来安装、编译、测试和卸载包。
包规范的定义可以帮助Node解决依赖包安装的问题,NPM正式基于该规范进行了实现。
包描述文件的规范中,NPM实际需要的字段有name、version、description、keywords、repositories、author、bin、main、scripts、engines、dependencies、devDependenices。
相对于包规范来说,多了author、bin、main、devDependencies4个字段。
1. author:包作者
2. bin
配置好bin字段后,可以直接通过npm install pageage_name -g命令添加脚本到执行路径,可以在命令行直接执行。
3. main
使用require引入包时,会检查这个字段,并将其作为包中其余模块的入口。
如果不存在这个字段,会查找包目录下的index.js、index.node、index.json文件作为默认入口。
4. devDependencies:开发环境下需要配置的依赖
NPM常用功能
CommonJS包规范是理论,NPM是其中的一种实践。对于Node而言,NPM帮助其完成第三方模块的发布、安装和依赖等。借助NPM,Node与第三方模块形成了一个很好的生态系统。
下面介绍一下NPM常用的一些功能。
1. 查看帮助
安装好NPM之后,可以使用 npm -v 查看当前NPM的版本。
可以看到,我的电脑目前安装的NPM版本是6.4.1。
在不熟悉NPM命令时,可以直接执行 npm 查看帮助引导说明。
可以看到,帮助中列出了所有的命令。
2. 安装依赖包
安装依赖包是NPM最常见的用法。安装好依赖包之后,就可以使用require关键字引入。
全局模式安装
如果包中存在命令行工具,可以使用 npm install package_name -g 命令进行全局模式安装。全局模式并不是将一个模块安装为一个全局包的意思,并不意味着可以在任何地方通过require来引用它。
实际上,-g是将一个包安装为全局可用的可执行命令。它根据包描述文件的bin字段配置,将实际脚本链接到与Node可执行文件相同的路径下。
本地安装
对于一些没有发布到NPM上的包,或是因为网络原因导致无法直接安装的包,可以通过将包下载到本地,然后以本地安装。本地安装只需为NPM指明pageage.json文件所在的位置即可。
具体参数如下:
npm install <tarball file>
npm install <tarball url>
npm install <folder>
非官方源安装
安装包可以不通过官方源安装,可以通过镜像源安装。
执行命令时,添加 –registry=http://registry.url即可。示例如下:
npm install underscore --registry=http://registy.url
3. NPM钩子说明
package.json中scripts字段的提出让包在安装或者卸载过程中提供钩子机制。
"scripts": {
"preinstall": "preinstall.js",
"install": "install.js",
"uninstall": "uninstall.js",
"test": "test.js"
}
在运行 npm install * 时,会首先执行preinstall指向的脚本,然后install指向的脚本会被执行。在执行 npm uninstall * 时,会执行uninstall执行的脚本。
当执行npm test时,会运行test执行的脚本。一个优秀的包应该包含测试用例,方便用户进行测试,以便检测包是否文档可靠。
4. 发布包
预想写一下发布包的流程,奈何账号验证的时候,NPM内部服务器错误,就略过吧,有时间再补一篇如何发布自己的自定义组件。(哈哈,没办法,就是这么任性。)
局部NPM
企业内部使用NPM有个人使用有一定的差别。企业的限制在于,享受模块开发带来的低耦合和项目组织上的好处时,也要考虑模块保密性的问题。现有的解决方案就是企业搭建自己的NPM仓库。关于如何搭建自己的个人仓库,有时间再分享。
NPM存在问题
NPM目前潜在的问题在于,在NPM平台上,每个人都可以分享包到平台上,鉴于开发人员水平不一,上面的包也良莠不齐。另外一个问题则是,Node代码可以运行在服务器端,需要考虑安全问题。
为了解决上述问题,可以使用CPAN社区中的 Kwalitee 风格来让模块自然排序。
符合 Kwalitee 的模块要满足的条件大致如下。
1. 具备良好的测试
2. 具备良好的文档(README、API)
3. 具备良好的测试覆盖率
4. 具备良好的编码规范
…
CPAN社区制定了相当多的规范来考察模块。未来,NPM社区也会有更多的规范来考察模块。
总结
文章主要介绍一下包与NPM之间的关系,文章内容大多来源于《深入浅出Node.js》,感兴趣的同学可以买一本精读,文章质量是很好的,既有深度又有广度。