包描述文件用于表达非代码相关的信息,它是一个JSON格式的文件-package.json,位于包的根目录下,是包的重要组成部分。而NPM的所有都与包描述文件的字段信息相关。由于CommonJS包规范尚处于草案阶段,NPM在实践中做了一定的取舍,具体细节在后面会介绍到。
CommonJS为package.json文件定义了如下一些必需的字段:
* **name**。包名,规范定义它需要由小写的字母和数字组成,包含.、_和-,但不允许出现空格。包名必须是唯一的,以免对外公布时产生重名冲突的误解。除此之外,NPM还建议不要在包名中附带上node或js来重复标识它是JavaScript或者Node模块。
* **description**。包简介。
* **version**。版本号。一个语义化的版本号,这在http://semver.org 上有详细定义,通常为major.minor.revision格式。该版本号十分重要,常常用于一些版本控制的场合。
* **keywords**。关键词数组,NPM中主要用来做分类搜索。一个好的关键词数组有利于用户快速找到你编写的包。
* **maintainers**。包维护者列表。每个维护者由name、email、和web这3个属性组成。示例如下:"maintainers":[{"name":"Jackson Tian","email":"shyvo1987@gmail.com","web":"http://html5ify.com"}] 。NPM通过该属性进行权限认证。
* **contributors**。贡献者列表。在开源社区中,为开源项目提供代码是经常出现的事情,如果名字能出现在知名项目的contributors列表中,是件比较有荣誉感的事情。列表中的第一个贡献者应当是包的作者本人。它的格式与维护者列表相同。
* **bugs**。一个可以反馈bug的网页地址或邮件地址。
* **licenses**。当前包所使用的许可证列表,表示这个包可以在哪些许可证下使用。它的格式如下:"licenses":[{"type":"GPLv2","url":"http://www.example.com/licenses/gpl.html"}] 。
* **repositories**。托管源代码的位置列表,表明可以通过哪些方式和地址访问包的源代码。
* **dependencies**。使用当前包所需要依赖的包列表。这个属性十分重要,NPM会通过这个属性帮助自动加载依赖的包。
除了必选字段外,规范还定义了一部分可选字段,具体如下所示:
* homepage。当前包的网站地址。
* os。操作系统支持列表。这些操作系统的取值包括aix、freebsd、linux、macos、solaris、vxworks、windows。如果设置了列表为空,则不对操作系统做任何假设。
* cpu。CPU架构的支持列表,有效的架构名称有arm、mips、ppc、sparc、x86和x86_64。同os一样,如果列表为空,则不对CPU架构做任何假设。
* engine。支持的JavaScript引擎列表,有效的引擎取值包括ejs、flusspferd、gpsee、jsc、spidermonkey、narwhal、node和v8。
* builtin。标志当前包是否是内建在底层系统的标准组件。
* directories。包目录说明。
* implements。实现规范的列表。标志当前包实现了CommonJS的哪些规范。
* scripts。脚本对象,它主要被包管理器用来安装、编译、测试和卸载包。示例如下:
~~~
"scripts":{
"install":"install.js",
"uninstall":"uninstall.js",
"build":"build.js",
"doc":"make-doc.js",
"test":"test.js"
}
~~~
包规范的定义可以帮助Node解决依赖包安装的问题,而NPM正是基于该规范进行了实现。最初,NPM工具是由Isaac Z. Schlueter单独创建,提供给Node服务的Node包管理器,需要单独安装。后来,在v0.6.3版本时集成进Node中作为默认包管理器,作为软件包的一部分一起安装。之后Isaac Z. Schlueter 也成为Node的掌门人。
在包描述文件的规范中,NPM实际需要的字段主要有name、version、description、keywords、repositories、author、bin、main、scripts、engine、dependencies、devDependencies。
与包规范的区别在于多了author、bin、main和devDependencies这4个字段。下面补充说明一下:
* author。包作者。
* bin。一些包作者希望包可以作为命令行工具使用。配置好bin字段后,通过 npm install package_name -g 命令可以将脚本添加到执行路径中,之后可以在命令行中直接执行。前面的node-gyp即是这样安装的。通过-g命令安装的模块包称为全局模式。
* main。模块引入方法require()在引入包时,会优先检查这个字段,并将其作为包中其余模块的入口。如果不存在这个字段,require()方法会查找包目录下的index.js、index.node、index.json文件作为默认入口。
* devDependencies。一些模块只在开发时需要依赖。配置这个属性,可以提示包的后续开发者安装依赖包。
下面是知名框架express项目的package.json文件,具有一定的参考意义:
~~~
{
"name":"express",
"description":"Sinatra inspired web development framework",
"version":"3.3.4",
"author":"TJ Holowaychuk <tj@vision-media.ca>",
"contributors":[
{
"name":"TJ Holowaychuk",
"email":"tj@vision-media.ca"
},
{
"name":"Aaron Heckmann",
"email":"aaron.heckmann+github@gmail.com"
},
{
"name":"Ciaran Jessup",
"email":"ciaranj@gmail.com"
},
{
"name":"Guillermo Rauch",
"email":"rauchg@gmail.com"
}
],
"dependencies":{
"connect":"2.8.4",
"commander":"1.2.0",
"range-parser":"0.0.4",
"mkdirp":"0.3.5",
"cookie":"0.1.0",
"buffer-crc32":"0.2.1",
"fresh":"0.1.0",
"methods":"0.0.1",
"send":"0.1.3",
"cookie-signature":"1.0.1",
"debug":"*"
},
"devDependencies":{
"ejs":"*",
"mocha":"*",
"jade":"0.30.0",
"hjs":"*",
"stylus":"*",
"should":"*",
"connect-redis":"*",
"marked":"*",
"supertest":"0.6.0"
},
"keywords":[
"express",
"framework",
"sinatra",
"web",
"rest",
"restful",
"router",
"app",
"api"
],
"repository":"git://github.com/visionmedia/express",
"main":"index",
"bin":{
"express":"./bin/express"
},
"scripts":{
"prepublish":"npm prune",
"test":"make test"
},
"engines":{
"node":"*"
}
}
~~~
- 目录
- 第1章 Node 简介
- 1.1 Node 的诞生历程
- 1.2 Node 的命名与起源
- 1.2.1 为什么是 JavaScript
- 1.2.2 为什么叫 Node
- 1.3 Node给JavaScript带来的意义
- 1.4 Node 的特点
- 1.4.1 异步 I/O
- 1.4.2 事件与回调函数
- 1.4.3 单线程
- 1.4.4 跨平台
- 1.5 Node 的应用场景
- 1.5.1 I/O 密集型
- 1.5.2 是否不擅长CPU密集型业务
- 1.5.3 与遗留系统和平共处
- 1.5.4 分布式应用
- 1.6 Node 的使用者
- 1.7 参考资源
- 第2章 模块机制
- 2.1 CommonJS 规范
- 2.1.1 CommonJS 的出发点
- 2.1.2 CommonJS 的模块规范
- 2.2 Node 的模块实现
- 2.2.1 优先从缓存加载
- 2.2.2 路径分析和文件定位
- 2.2.3 模块编译
- 2.3 核心模块
- 2.3.1 JavaScript核心模块的编译过程
- 2.3.2 C/C++核心模块的编译过程
- 2.3.3 核心模块的引入流程
- 2.3.4 编写核心模块
- 2.4 C/C++扩展模块
- 2.4.1 前提条件
- 2.4.2 C/C++扩展模块的编写
- 2.4.3 C/C++扩展模块的编译
- 2.4.2 C/C++扩展模块的加载
- 2.5 模块调用栈
- 2.6 包与NPM
- 2.6.1 包结构
- 2.6.2 包描述文件与NPM
- 2.6.3 NPM常用功能
- 2.6.4 局域NPM
- 2.6.5 NPM潜在问题
- 2.7 前后端共用模块
- 2.7.1 模块的侧重点
- 2.7.2 AMD规范
- 2.7.3 CMD规范
- 2.7.4 兼容多种模块规范
- 2.8 总结
- 2.9 参考资源
- 第3章 异步I/O
- 3.1 为什么要异步I/O
- 3.1.1 用户体验
- 3.1.2 资源分配
- 3.2 异步I/O实现现状
- 3.2.1 异步I/O与非阻塞I/O
- 3.2.2 理想的非阻塞异步I/O
- 3.2.3 现实的异步I/O
- 3.3 Node的异步I/O
- 3.3.1 事件循环
- 3.3.2 观察者
- 3.3.3 请求对象
- 3.3.4 执行回调
- 3.3.5 小结
- 3.4 非I/O的异步API
- 3.4.1 定时器
- 3.5 事件驱动与高性能服务器