Node.js 101: create a package
这是我为公司同事科普如何开发 Node.js app 的系列文章。
什么是 Node.js? #
Node.js is a platform built on Chrome’s JavaScript runtime for easily building fast, scalable network applications. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient, perfect for data-intensive real-time applications that run across distributed devices.
如何安装? #
Download 或 brew install node
。
如何运行 Node.js #
# bash script, works on Linux / Mac
touch demo.js
echo "console.log('hello world)" > demo.js
node --harmony demo.js
# output "hello world"
node --hamrony -e "console.log('hi there')"
# output "hi there"
什么是 --harmony
#
Harmony 可以理解为一个为了解决 ECMAScript / JavaScript 混乱局面的项目。
作为一个 JavaScript 开发者都应该去了解 ECMAScript 5,作为一个 Node.js 开发者更应该去了解 ECMAScript 6。
因此,Chrome 在内核里加入 ECMAScript 5 / 6 的内容,并提供选项,供开发者尽早试验新的特性;而基于 V8 引擎的 Node.js 自然也会有,这个选项就是 --harmony
。
具体的细节请善用 Google,Node.js 能用的 ES 6 特性请查阅 GitHub 上的 node-es6-examples。
只要记住跑 Node.js 脚本时,加上 --harmony
即可:node --harmony
。
Linux / Mac 使用者可以建立别名:alias node='node --harmony'
。
Windows?再见。
注:本系列所有代码均运行在 Harmony 模式下,Node.js 版本为 0.11.13
。
如何写一个 Node.js 项目 #
如果一个教程只是围绕 hello world
就太没趣了,本文将通过 Sagase package 介绍如何写一个实际有用的项目。
Sagase 项目是提供一个使用正则搜索文件的工具,包括命令行和用于 Node.js 的库。项目结构如下:
lib/
cli.js
sagase.js
Gruntfile.js
package.json
先记住这么多,稍后一一解释。
Node.js package #
Node.js package 是 Node.js 的代码包 (集合) ,可以是:
- 方法、类等 (像
stdio.h
) - 用于命令行的工具
- web app 之类的项目
如果用过 Ruby 的 Gems、Python 的 pip,应该很容易就能理解。
几乎所有的 Node.js 项目都是一个 package——虽然也可以用独立的 .js
,但效率将大打折扣。
npm #
Node.js package 通过 npm 管理,常用命令:
npm init
npm install PACKAGE
npm uninstall PACKAGE
npm update
创建 Node.js 项目 #
在命令行执行 npm init
,回答若干问题,或者一路回车,将会自动创建一个典型的 package.json
,这时候就可以开始写 Node.js 项目了。
package.json #
每一个 Node.js 项目基本会有一个 package.json
,用于描述这个包功能、作者等信息,同时也包括运行环境、依赖项等等重要信息。一般长这样:
{
"name": "sagase",
"version": "0.1.1",
"main": "lib/sagase.js",
"description": "Searching files recursively.",
"bin": {
"sagase": "lib/cli.js"
},
"dependencies": {
"async": "^0.9.0",
"bluebird": "^2.1.2",
"chalk": "^0.4",
"fs-extra": "^0.8",
"lodash": "^2.4.1",
"nomnom": "^1.6"
},
"devDependencies": {
"grunt-contrib-jshint": "~0.7.0",
"grunt-contrib-watch": "~0.5.0",
"jshint-stylish": "~0.1.3",
"load-grunt-tasks": "~0.2.0",
"time-grunt": "~0.2.0"
},
"engines": {
"node": ">= 0.8"
}
}
不太重要的就略过,请自行查看官方文档。
"main": "lib/sagase.js"
指明这个包的入口,就像 C 的 main
。如果包的根目录存在 index.js
,即使没有 main
也没问题的,否则引用这个包的时候将会报错:Error: Cannot find module 'xxxx'
。建议遵循 index.js
命名习惯。
"bin": {
"sagase": "lib/cli.js"
}
告诉 npm 将 lib/cli.js
软链接到系统的可执行文件目录,并命名为 sagase
,这样就可以在命令行里直接使用这个包。
"dependencies": {
"async": "^0.9.0",
"bluebird": "^2.1.2",
"chalk": "^0.4",
"fs-extra": "^0.8",
"lodash": "^2.4.1",
"nomnom": "^1.6"
},
"devDependencies": {
"grunt-contrib-jshint": "~0.7.0",
"grunt-contrib-watch": "~0.5.0",
"jshint-stylish": "~0.1.3",
"load-grunt-tasks": "~0.2.0",
"time-grunt": "~0.2.0"
}
dependencies
和 devDependencies
代表着这个项目依赖什么包。npm 在 npm install
的时候,会根据这个包所在的环境安装相应的依赖包,并存放在项目根目录的 node_modules
文件夹,当需要使用时就像官方包一样即可:
const async = require('async'), fs = require('fs')
devDependencies
和 dependencies
的区别在于,如果这个包是项目的主包,npm install
时将会同时安装所有依赖包;如果这个包是别的项目的依赖包,devdependencies
将被忽略,不会安装。
因此,一些代码测试、打包等流程需要用到的包就可以放在 devDependencies
。当在别的项目里使用这个包时,就不用浪费时间安装这些包。
而 ^0.9.0
则是指定可安装的版本范围,此例指 >= 0.9.0 && < 0.10.0
。
"engines": {
"node": ">= 0.8"
}
指定这个包运行时所需的 Node.js 版本,避免 API 版本不一致造成运行失败。建议 >= 0.10
或 >= 0.11.9
。
关键部分就这么多,上述的 package.json 将允许我们可以通过下述方式使用这个包。
首先是命令行模式,因为 Sagase 已发布到 npm 的公共服务器,可以通过 -g
参数安装到全局环境:
npm install -g sagase
sagase ./assets .js$ .min.js
在 Node.js 项目中使用则无需安装到全局环境,但一般使用 --save
在安装的同时把这个包添加到项目的 package.json:
npm install --save sagase
var find = require('sagase').find
find({
folder: './',
pattern: /.js$/,
exclude: /.min.js/
}).then(function (files) {
// do whatever you want
})
这一篇到此结束,下一篇开始讲开发部分。