Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Node.js学习笔记 #14

Open
hawx1993 opened this issue Jun 6, 2017 · 1 comment
Open

Node.js学习笔记 #14

hawx1993 opened this issue Jun 6, 2017 · 1 comment
Labels

Comments

@hawx1993
Copy link
Owner

hawx1993 commented Jun 6, 2017

Node利用单线程,远离多线程的死锁、状态同步等问题;利用异步I/O,让单线程远离阻塞,更好的利CPU

Libuv:它为 Node.js 提供了跨平台,线程池,事件池,异步 I/O 等能力,是 Node.js 如此强大的关键

npm check

安装npm-check:
npm install -g npm-check

检查npm包的状态:

npm-check -u -g
//npm更新全局指定包
npm update -g jshint
//删除全局包
npm uninstall -g jshint
//生成exec文件
npm link

同步的EventEmitter

var EventEmitter = require('events');

class Man extends EventEmitter {}

var man = new Man();

man.on('wakeup', function(){
    console.log('man has woken up'); // 代码1
});

man.emit('wakeup');

console.log('woman has woken up');  // 代码2

// 输出如下:
// man has woken up
// woman has woken up

emit和on都是同步的

删除npm镜像

npm config delete registry

//有淘宝源,发布npm镜像的时候
修改~/.npmrc中的registry字段(命令:vi ~/.npmrc)

Node.js require vs ES6 import/export

  • Importing modules using require, and exporting using module.exports and exports.foo
  • Importing modules using ES6 import, and exporting using ES6 export

Babel converts import and export declaration to CommonJS (require/module.exports) by default anyway

babel把import和export编译为CommonJS的require和module.exports

CommonJS允许你动态加载模块,es6不允许。

Require:

  • 可以进行动态加载,其中加载的模块名称不是预定义的/静态的
  • 加载是同步的,这意味着如果你有多个需求,他们将被逐个加载和处理

Import

  • 你可以使用命名导入来选择性地仅加载所需片段,这可以节省内存
  • Import可以是异步的

babel

Babel默认只转换新的js句法,而不转换新的API,比如Iterator、Generator、Set、Maps等,如果想让这个方法运行,必须使用babel-polyfill,为当前环境提供一个垫片。

babel-cli工具自带一个babel-node命令,提供一个支持ES6的REPL环境。

node复制文件

将读出来的内容通过管道写入到目标文件中

function copy(src, target) {
    fs.createReadStream(src).pipe(fs.createWriteStream(target));
}

代码简洁
没有内存溢出的风险

npm3 和 npm2

npm3 resolves dependencies differently than npm2.(npm3解析依赖关系不同于npm2。)

NPM3对此做了很大改进。简单的来说将传统的嵌套结构改为了平铺结构

当npm2以嵌套方式安装所有依赖项时,npm3会尝试缓解这种嵌套导致的深层树和冗余。

npm-shrinkwrap

前面说过要锁定依赖的版本,但这并不能完全防止意外情况的发生,因为锁定的只是最外一层的依赖,而里层依赖的模块的 package.json 有可能写的是 "mongoose": "*"。为了彻底锁定依赖的版本,让你的应用在任何机器上安装的都是同样版本的模块(不管嵌套多少层),通过运行 npm shrinkwrap,会在当前目录下产生一个 npm-shrinkwrap.json,里面包含了通过 node_modules 计算出的模块的依赖树及版本。上面的截图也显示:只要目录下有 npm-shrinkwrap.json 则运行 npm install 的时候会优先使用 npm-shrinkwrap.json 进行安装,没有则使用 package.json 进行安装。

exportsmodule.exports

exports 和 module.exports 的区别了:

  • module.exports 初始值为一个空对象 {}
  • exports 是指向的 module.exports 的引用
  • require() 返回的是 module.exports 而不是 exports

The double-star character**is supported by default. That is, a/**/b will match a/x/y/b, but a/**b will not.

process.argv返回命令行脚本的各个参数组成的数组

常见API

__dirname

当前执行脚本所在目录的目录名。__dirname实际上并非全局的而是各个模块本地的。

/Users/trigkit4/antd-demo/src/component

__filename

同上。执行脚本所在目录下的文件名,输出完整的路径:

 /Users/trigkit4/antd-demo/src/component/test.js

fs

fs.rename(oldPath,newPath,callback)

fs.rename('test.js','fs.js');//处于同一目录的文件,不需要写完整路径名

fs.stat(path,[callback(err,stats)])

callback 回调,传递两个参数,异常参数err, 文件信息数组 stats

fs.stat('fs.js', function (err, stats) {
  if (err) throw err;
  console.log('stats: ' + JSON.stringify(stats));
});
最后输出结果如下:

stats: {"dev":16777219,"mode":33188,"nlink":1,"uid":501,"gid":0,"rdev":0,"blksize":4096,
"ino":22436422,"size":237,"blocks":8,"
atime":"2016-04-11T08:57:36.000Z","mtime":"2016-04-11T08:57:33.000Z",
"ctime":"2016-04-11T08:57:33.000Z","birthtime":"2016-03-31T09:13:34.000Z"}

fs.readdirSync(path)

同步版的 readdir. 返回文件名数组,其中不包括 '.' 和 '..' .
使用的是相对路径目录,比如输出当前文件所在目录下的所有文件fs.readdirSync('./')

fs.readdir(path,callback)

异步版的readdir。读取path路径所在目录的内容。例如,读取当前目录下的文件名:

 var fs = require('fs');
console.log(fs.readdir('./',function (err,files) {
    if(err){
        console.log(err);
    }
    console.log(files);
}));

fs.readFileSync(filename,[options])

返回文件名为filename的文件内容,会被编码

fs.writeFile(filename,data,[options],callback)

异步地将数据写入一个文件,如果文件原先存在,会被替换。data可以是一个string。

原来在github上任意项目加个"gh-pages"分支,通过github page/你项目的名称就可以访问到那个分支的静态文件

path.join

path.join('src','component','test.js');//src/component/test.js

path.resolve()

path.resolve('src','component','test.js');//Users/trigkit4/antd-demo/src/component/src/component/test.js

// 输出 /foo/bar/baz
console.log( path.resolve('/foo/bar', './baz') );

// 输出 /foo/bar/baz
console.log( path.resolve('/foo/bar', './baz/') );

// 输出 /tmp/file
console.log( path.resolve('/foo/bar', '/tmp/file/') );

path.dirname()

path.dirname('src/component/test.js');//返回该文件所在的目录名:src/component

path.basename()

返回路径中最后一部分

//将不符合规范的路径格式化
path.normalize('/foo/bar//baz/asdf/quux/..');
=> '/foo/bar/baz/asdf'

path.relative('/data/orandea/test/aaa', '/data/orandea/impl/bbb')
=> '../../impl/bbb'

path.basename('src/component/');//component
path.basename('src/component/test.js');//test.js

当你想输出的是例如构造函数这样的单个项目,那么需要使用module.exports。单个的函数适合使用exports

模块以'/'为前缀,则表示绝对路径。
模块以'./' 为前缀,则路径是相对于调用require()的文件。

为了获取调用 require 加载的确切的文件名,使用 require.resolve() 函数。

  • process.cwd():返回运行当前脚本的工作目录的路径。// /Users/trigkit4/antd-demo/src/component
  • process.chdir():改变工作目录。


Node.jspackage.json字符~^的作用分别是:前者波浪号是匹配最近的小版本,例如~1.2.3将会匹配所有的1.2.x版本,而后者会匹配主要的版本,例如^1.2.3将会匹配任意的1.x.x包括最近的1.3.0版本,但不会匹配2.0.0版本

1.兼容模块新发布的补丁版本:~1.1.x
2.兼容模块新发布的小版本:^1.1.01.x
3.兼容模块新发布的大版本、小版本、补丁版本:*


webstorm可以通过鼠标右键选择最后一项,use javascript library来选择Node.js global

Node核心 社区模块 其他
queryString、net、HTTP socket.io、Express、connect、mongoose、node-cgi 数据库驱动,中间件,路由,实时websocket
  • npm install:用于安装本地node_modules文件夹的依赖项目。默认地,该命令会安装所有列在dependencies中的项目。带有--production标记,npm将不会安装列在devDependencies

Node.js中要导出一个对象,需要使用exports.name = object。当我们要为Express.js配置属性时,需要module.exports

    module.exports = function (app) {
        app.set('port',process.env.PORT || 3000);
        app.set('views',__dirname + '/views');
        app.set('view engine','jade');
        return app;
    };

模块module

要输出某个对象,把它加到exports这个特殊对象下即可。

    var PI = Math.PI;
    exports.area = function (r) {
        return PI * r * r;
    };
    exports.circumference = function (r) {
        return 2 * PI * r;
    };

通过 require('path')来加载此模块。


devDependenciesdependencies


package.json所在目录执行npm install的时候,devDependencies里面的模块也会被安装的。


一个node package有两种依赖,一种是dependencies,一种是devDependencies,其中前者依赖的项该是正常运行该包时所需要的依赖项,而后者则是开发的时候需要的依赖项,像一些进行单元测试之类的包。

npm install module-name --save自动把模块和版本号添加到dependencies部分;//NPM5.0不需要--save命令,会自动保存到package.json文件
npm install module-name -D自动把模块和版本号添加到devdependencies部分


npm常用命令

npm install <name> -g 将包安装到全局环境中
npm install <name> --save 安装的同时,将信息写入package.json
npm init 会引导你创建一个package.json文件,包括名称、版本、作者这些信息等
npm remove <name>移除
npm update <name>更新所有npm包
npm ls 列出当前安装的了所有包
npm root 查看当前包的安装路径
npm root -g 查看全局的包的安装路径

与模块相关的全局函数及对象

require.resolve 查询完整模块名

require.resolve('./testModule.js');//不会加载该模块

EventEmitter类

方法:

  • addListener(event,listener)
  • on(event,listener)(addListener方法的别名)
  • once(event,listener)对指定事件绑定只执行一次的事件处理函数

在需要将模块文件定义为一个类的时候,只能使用module.exports

Benchmark.js

Ops/sec 测试结果以每秒钟执行测试代码的次数(Ops/sec)显示,这个数值越大越好。除了这个结果外,同时会显示测试过程中的统计误差,以及相对最好的慢了多少(%)

我们先来实现这三个函数:
首先在根目录通过npm intsall benchmark 来安装benchmark。然后将如下代码写入test.js文件,该文件置于系统根目录下:

    var int1 = function (str) {
      return +str;
    };
    var int2 = function (str) {
      return parseInt(str, 10);
    };
    var int3 = function (str) {
      return Number(str);
    };

然后照着官方的模板写 benchmark suite

    var Benchmark = require('benchmark');
    var suite = new Benchmark.Suite;
    // 添加测试
    suite
        .add('+', function() {
            int1(number);
        })
        .add('parseInt', function() {
            int2(number);
        })
        .add('Number', function () {
            int3(number);
        })
    // 每个测试跑完后,输出信息
        .on('cycle', function(event) {
            console.log(String(event.target));
        })
        .on('complete', function() {
            console.log('Fastest is ' + this.filter('fastest').pluck('name'));
        })
    // 这里的 async 不是 mocha 测试那个 async 的意思,这个选项与它的时间计算有关,默认勾上就好了。
        .run({ 'async': true });

在终端出可见看到:

      ~ git:(master)  node test.js
    + x 22,219,635 ops/sec ±1.26% (93 runs sampled)
    parseInt x 47,826,860 ops/sec ±1.48% (82 runs sampled)
    Number x 41,932,553 ops/sec ±1.47% (91 runs sampled)
    Fastest is parseInt


Node.js提供了exportsrequire两个对象,其中exports是模块公开的接口,require用于从外部获取一个模块接口,即所获取模块的exports对象。可以直接在webstorm运行此类文件。

Express框架

Request 对象 - request 对象表示 HTTP 请求,包含了请求查询字符串,参数,内容,HTTP 头部等属性。常见属性有:

`req.app`:当callback为外部文件时,用req.app访问express的实例
`req.baseUrl`:获取路由当前安装的URL路径
`req.body / req.cookies`:获得「请求主体」/ Cookies
`req.fresh / req.stale`:判断请求是否还「新鲜」
`req.hostname / req.ip`:获取主机名和IP地址
`req.originalUrl`:获取原始请求URL
`req.params`:获取路由的parameters
`req.path`:获取请求路径
`req.protocol`:获取协议类型
`req.query`:获取URL的查询参数串
`req.route`:获取当前匹配的路由
`req.subdomains`:获取子域名
`req.accpets()`:检查请求的Accept头的请求类型
`req.acceptsCharsets / req.acceptsEncodings / req.acceptsLanguages
`req.get()`:获取指定的HTTP请求头
`req.is()`:判断请求头Content-Type的MIME类型

Response 对象 - response 对象表示 HTTP 响应,即在接收到请求时向客户端发送的 HTTP 响应数据。常见属性有:

res.app:同req.app一样
res.append():追加指定HTTP头
res.set()res.append()后将重置之前设置的头
res.cookie(name,value [,option]):设置Cookie
opition: domain / expires / httpOnly / maxAge / path / secure / signed
res.clearCookie():清除Cookie
res.download():传送指定路径的文件
res.get():返回指定的HTTP头
res.json():传送JSON响应
res.jsonp():传送JSONP响应
res.location():只设置响应的Location HTTP头,不设置状态码或者close response
res.redirect():设置响应的Location HTTP头,并且设置状态码302
res.send():传送HTTP响应
res.sendFile(path [,options] [,fn]):传送指定路径的文件 -会自动根据文件extension设定Content-Type
res.set():设置HTTP头,传入object可以一次设置多个头
res.status():设置HTTP状态码
res.type():设置Content-Type的MIME类型

app.use([path],function [,function...])

在目录挂载中间件函数,如果没有指明目录,默认是"/"

var router = express.Router();
router.get('/', function (req, res, next) {
  next();
})
app.use(router);

app.set(name,value)可以通过app.get(name)来获取

res.cookie(name,value [,option])

res.cookie('testCookie', "1024",{ maxAge: 3600, httpOnly: true})

res.json([body])

回传一个JSON响应。这个方法和res.send()一样,用一个对象或者数组作为参数。

res.redirect([status,] path)
重定向URL从指定的路径,带有特定的HTTP状态码。如果你不指明状态,状态码默认是302 Found

res.redirect('../../foo/bar')

使用中间件只需要require进来,然后通过Expressuse方法来使用这个中间件提供的方法。

Express应用生成器

$ npm install express-generator -g
$ express myapp
$ cd myapp
$ npm install

启动这个应用:

$ DEBUG=myapp npm start

然后在浏览器中打开http://localhost:3000/网址就可以看到这个应用了

中间件

在Express框架中,一个中间件是一个用于处理客户端请求的函数。一个HTTP服务器中可能会使用各种中间件。当接收到一个客户端请求时,首先将该请求提交给第一个中间件函数,每一个中间件函数内部封装一个next回调函数。一个最简单的中间件的书写方法如下:

function middleware(req,res,next){ next() }

在Express框架中,使用应用程序实例对象的use方法来调用一个中间件:

app.use([path],function)

next本身也是一个函数,调用next()就会继续执行下一个中间件。
path是可选的字符串,用于指定何种路径应用中间件,function用于指定我们所要调用的中间件函数:

var setHeader = function () {
    return function (req, res, next) {
        res.statusCode = 2000;
        res.header={'Content-Type':'text/html'};
        res.head='<head><meta charset="utf-8" /></head>>';
        next();
    }
};
exports.setHeader = setHeader;

bodyParser中间件

用于解析客户端请求的body中的内容,内部使用JSON编码处理

cookieParser中间件

用于获取web浏览器发送的cookie中的内容。

session中间件
用于为保存用户数据提供一个session管理器。加密后的session数据默认保存在一个cookie中,因此,在使用session中间件之前必须使用cookieParser中间件:

app.use(express.session([options]));

参数值为一个对象,该对象可以使用的属性及属性值如下所示:

  • key:用来保存session的cookie名称,默认connect.sid
  • store:属性值用来保存session数据的第三方存储对象
  • cookie:属性值为一个用来指定保存session数据的cookie设置的对象,默认值为:{path:'/',httpOnly:true,maxAge:14400000},httpOnly指定是否只针对HTTP保存cookie
  • secret:指定对session数据加密的加密字符串。值为字符串

在Express中,可以使用应用程序实例对象的all方法接收客户端提交的各种请求(包括GET、POST、PUT和DELETE请求)
并返回服务器端响应结果:

app.all(path,callback)

req

req.params

一个对象包含属性映射到命名为route的参数。例如:如果你有一个路径:/user/:name,然后name属性可以在req.params.name中找到的:

// GET /user/trigkit4
req.res.name // => "trigkit4"

req.path 包含部分请求URL的路径

// foo.com/users?name=trigkit4
req.path  // => "/users"

路由Routing

路由(Routing)是由一个 URI(或者叫路径)和一个特定的 HTTP 方法(GET、POST 等)组成的,涉及到应用如何响应客户端对某个网站节点的访问。

每一个路由都可以有一个或者多个处理器函数,当匹配到路由时,这个/函数将被执行。


路由的定义由如下结构组成:app.METHOD(PATH, HANDLER)。其中,app 是一个 express 实例;METHOD 是某个 HTTP 请求方式中的一个;PATH 是服务器端的路径;HANDLER 是当路由匹配到时需要执行的函数。

//对网站的首页访问返回"Hello World" 字样
var express = require('express');
var app = express();
app.get('/', function (req, res) {
    res.send('Hello World!');
});

//网站首页接受POST请求
app.post('/', function (req, res) {
    res.send('Got a POST request');
});

// /user节点接受PUT请求
app.put('/user', function (req, res) {
    res.send('Got a PUT request at /user');
});

// /user节点接受DELETE请求

app.delete('/user', function (req, res) {
    res.send('GOT a DELETE request at /user');
});

Express 内置的 express.static 可以方便地托管静态文件,例如图片、CSS、JavaScript 文件等。

假设在public目录放置了图片,css和javascript文件,你就可以访问public目录下面的文件。

app.use(express.static('public'))

express.static(目录,可选项)

视图渲染

res.render(view [, locals] [, callback])

渲染视图并且发送已渲染的HTML字符串到客户端,可选参数:

  • locals:一个为view定义本地变量的对象的属性
res.render('user', { name: 'trigkit4' }, function(err, html) {
  // ...
});

当一个错误发生时,该方法内部将调用next(err)

res.send([body])

发送HTTP响应,参数body可以是一个缓冲对象,一个字符串,一个对象,或者一个数组

渲染模板使用的是res.render(),例如:

app.get('/user', function(req, res) {
    res.render('user', { name: 'trigkit4' });
});

其实,res.render()调用了app.render()。在app.render()中,先创建一个view对象(相关源码为view.js),
然后调用view.render()。如果允许缓存,即app.enabled('view cache')的话,则会优先检查缓存,
如果缓存中已有相关视图,则直接取出;否则才会新创建一个视图对象。

Mongoose

Mongoose是MongoDB的一个对象模型工具,可以工作于异步环境下。

连接Mongoose:

var mongoose = require('mongoose');
var uri = 'mongodb://username:password@hostname:port/database name
mongoose.connect('mongodb://localhost/test'); //其中,test指的是数据库名/文件夹名,或者:
mongoose.connect( uri );

通过Model我们就可以创建,删除,修改mongodb里面的文档,MongoDB提供了SchemaSchema则提供了数据类型和结构的定义

package.json中的

"scripts":{
    "start": "node ./bin/www"
}

意思是启动时执行的脚本,package.json文件dependencies的最后一项都不能有逗号

app.get() app.post() 的第一个参数都为请求的路径,第二个参数为处理请求的回调函数,回调函数有两个参数分别是 reqres,代表请求信息和响应信息 。


通过调用 res.render() 渲染模版,并将其产生的页面直接返回给客户端。它接受两个参数,第一个是模板的名称,即 views 目录下的模板文件名,扩展名 .ejs 可选。第二个参数是传递给模板的数据对象,用于模板翻译。


我们通过 app.use(express.static(path.join(__dirname, 'public'))) 设置了静态文件目录为 public 文件夹
app.use 加载用于处理http請求的middleware(中间件),当一个请求来的时候,会依次被这些 middlewares处理。


ejs 的标签系统非常简单,它只有以下三种标签:

  • <% code %>JavaScript 代码。
  • <%= code %>:显示替换过 HTML 特殊字符的内容。
  • <%- code %>:显示原始 HTML 内容。

cryptoNode.js 的一个核心模块,我们用它生成散列值来加密密码。
app.js:启动文件,或者说入口文件
bin:存放可执行文件


每次我们更新代码后,都需要手动停止并重启应用(node app.js),使用 supervisor 模块可以解决这个问题,
每当我们保存修改的文件时,supervisor 都会自动帮我们重启应用。通过:

$ npm install -g supervisor

通过命令:supervisor app.js来启动

开发Web应用,按照MVC模式,基本也还是几个概念:

  • 模板引擎
  • 路由控制
  • 持久化数据

node_modules目录的外面一层,我们可以直接使用require("express")来代替require('./node_modules/express'),这是node模块加载的一个重要特性,通过查找node_modules 目录来加载模块。

Node.js的模块可以分类核心模块(fs,http,net,vm等)和文件模块(单独文件或文件夹的模块)。

当require遇到一个既不是核心模块,又不以路径形式表示的模块名称时,会试图在当前目录下的node_modules目录来查找模块。如果没找到,则会在当前目录的上一层node_modules目录中继续查找。

node.js 连接mongodb数据库

首先在package.json文件中的dependencies属性中添加一行代码:

{
    "mongodb": ">=3.0"
}

然后运行npm install更新依赖的模块,接下来在目录中创建settings.js文件,用于保存数据库连接信息:

module.exports = {
    cookieSecret: "someName",
    db: "dbName",
    host: "localhost"
}

然后在models子目录中创建db.js,内容如下:

var settings = require('../settings');
var Db = require('mongodb').Db;
var Connection = require('mongodb').Connection;
var Server = require('mongodb').Server;
module.exports = new Db(settings.db,new Server(settings.host,Connection.DEFAULT_PORT,{}));

MongoDB是一个对象数据库,没有表、行等概念。所有数据以文档形式存储。在mac下配置完后,在运行node.js程序时需先运行mongodb数据库,在终端执行mongod,然后执行$ node bin/www或者$ node app.js

connect-mongo模块

我们可以使用connect-mongo模块将会话信息存储在数据库中,便于持久维护、

var MongoStore = require('connect-mongo');
var settings = require('../settings');

app.configure(function () {
    app.set('views',__dirname + '/views');//视图文件的目录,存放模板文件
    app.set('view engine', 'ejs');
    app.use(express.bodyParser());
    app.use(express.cookieParser());
    app.use(express.session({
        secret: settings.cookieSecret,
        store: new MongoStore({
            db: settings.db
        })
    }));
    app.use(app.router);
    app.use(express.static(__dirname + '/public'));
});

app.use([path],function[,function...]): 在path上挂载中间件的函数,如果没有指明路径,默认是/

REST(Representational State Transfer)

REST的意思是表征状态转移,是一种基于HTTP协议的网络应用接口风格,充分利用HTTP的方法实现统一风格接口的服务,HTTP定义了以下8种标准的方法:

  • GET:请求获取指定资源
  • HEAD:请求指定资源的响应头
  • PUT :请求服务器存储一个资源
    根据REST设计模式,这四种方法通常分别用于实现以下功能:
    GET(获取),POST(新增),PUT(更新),DELETE(删除)

app.set是Express的参数设置工具,接受一个键和一个值,可用参数如下:

  • basepath: 基础地址,通常用于res.redirect()跳转
  • views: 视图文件的绝对路径,存放模板文件
  • view engine:视图模板引擎
  • view options:全局视图参数对象
  • view cache:启用视图缓存
  • case sensitive routes:路径区分大小写
  • strict routing:严格路径,启用后不会忽略路径末尾的/
  • jsonp callback:开启透明的JSONP支持

app.configure中启用了5个中间件:bodyParser(解析客户端POST请求内容)、methodOverride(用于支持定制的HTTP方法)、router(项目路由支持)、static(提供静态文件支持)以及errorHandler(错误控制器)。

app.get('/', routes.index)是一个路由控制器,如果用户访问/路径,则由routes.index 来控制
模板引擎的功能是将页面模板和要显示的数据结合起来生成HTML页面。

在MVC架构中,模板引擎包含在服务器端,控制器得到请求后,从模型获取数据,调用模板引擎,模板引擎以数据和页面模板为输入,生成HTML页面,然后返回给控制器,由控制器交回客户端。

严格符合CommonJS规范的包应该具备以下特征:
1.package.json 必须在包的顶层目录下
2.二进制文件应该在bin目录下
3.JavaScript代码应该在lib目录下
4.文档应该再doc目录下
5.单元测试应该在test目录下

  • process.argv是命令行参数数组,第一个元素是node,第二个是脚本文件名
  • process.stdout是标准输出流
  • process.nextTick(callback)为事件循环设置一项任务,Node.js会在下次事件循环调响应时调用callback

util是一个Node.js核心模块,提供常用函数的集合
events.EventEmitter的核心就是事件发射与事件监听功能的封装。

设置路由

在路由中,可以使用: + 参数名的形式来指定一个参数,比如在路由中,我们指定id参数和name参数,当接收到客户端提交的URL请求后,将客户端指定的id参数值与name参数值作为服务器端响应结果返回给客户端:

发布项目到npm上

在设置完 package.json 之后,可以把自己编写的包提交到 npm 去了。通过 npm addusernpm上创建一个输入自己的账户,千万要记住密码!

然后通过 npm publish <folder> 就可以上传 npm 包。如果在当前 package.json 所在的目录,执行$ npm publish ,等待上传好就可以。

上传完,去 npm 得官网,输入自己刚刚注册的账号,可以对 npm 包进行管理。

上面说的是普通的 npm 包,如果想像我一样上传一个可以让用户在本地执行的 shell 包,需要package.json中的 bin 字段中写上需要执行的文件的相对路径。用户安装的时候需要全局安装了$: npm install 项目名称 -g。 安装完在命令行中输入$: 项目名称可以执行你上传的库。

注册自己的bower包

可以注册自己的包,这样其他人也可以使用了,这个操作只是在服务器上保存了一个隐射,服务器本身不托管代码。

bowerregister storejsgit://github.com/jaywcjlove/store.js.git
@annewanghy
Copy link

真好的总结.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants