npm install
例如npm install express 就会默认安装express的最新版本,也可以通过在后面加版本号的方式安装指定版本,如npm install [email protected]
npm install
但是代码中,直接通过require()的方式是没有办法调用全局安装的包的。全局的安装是供命令行使用的,就好像全局安装了vmarket后,就可以在命令行中直接运行vm命令
npm install
项目路径中如果有package.json文件时,直接使用npm install方法就可以根据dependencies配置安装所有的依赖包,所以移交项目时不用吧node_modules文件一起了
这样代码提交到github时,就不用提交node_modules这个文件夹了。
npm init 会引导你创建一个package.json文件,包括名称、版本、作者这些信息等
npm remove
npm update
npm ls 列出当前安装的了所有包
npm root 查看当前包的安装路径
npm root -g 查看全局的包的安装路径
npm help 帮助,如果要单独查看install命令的帮助,可以使用的npm help install
使用npm init 指令会生成一个package.json,如下所示。然后执行 npm install --save express 后package.json文件中的dependencies字段发生变更
{
"name": "easy_express",
"version": "0.1.0",
"description": "my express test",
"main": "index.js",
"scripts": {
"test": "make test"
},
"keywords": [
"node",
"esay"
],
"author": "feng",
"license": "MIT",
"dependencies": {.
"express": "^4.13.3"
}
}
express.static是Express内置的唯一一个中间件,负责托管express应用内的静态资源。它可以将一个或多个目录指派为包含静态资源的目录,其中的资源不经任何特殊处理直接发送给客户端(如css文件、js文件等)。因为这个目录完全开放,所以我们一般设置这个静态资源文件夹为public
app.use(express.static(__dirname + '/public'));
接下来我们在public下面创建一个子目录Img,并把logo.png放到其中,现在我们可以直接指向/img/logo.png(注意路径中并没有public,这个目录对客户端来说是隐形的),static中间件会返回这个文件,并正确设定内容类型
或者干脆在浏览器里这么访问
http://localhost:3000/images/kitten.jpg
req.params:
·一个数组,包含命名过的路由参数
· app.get('/student/:name',function(req,res){ var name = req.params.name}); 路由中使用了:name,他会跟任何字符串匹配(不包括反斜杠),并将其跟键name一起放到req,params对象中
前端页面拼接请求字符串:url = '/apple/detail/'+code+'/'+miniCode;
设置路由: app.get('/apple/detail/:code/:miniCode', controller.product.p2pMiniDetail);
在对应的p2pMiniDetail中读取参数: var code = req.params.code; var miniCode = req.params.miniCode;
req.query
`一个对象,包含以键值对存放的查询字符串(通常称为GET请求参数)
前端页面拼接请求字符串:url = '/apple/detail/'+'?uid='+uid+'&kind='+kind;
设置路由: app.get('/apple/detail/', controller.product.p2pMiniDetail);
在对应的p2pMiniDetail中读取参数: var uid = req.query.uid; var kind = req.params.kind;
req.body
`一个对象,包含POST请求参数(一般用于解析表单中的值,需要中间件能够解析请求内容类型)
req.cookies
`一个对象,包含从客户端传递过来的cookies值
req.headers
`从客户端接收到的请求报头
req.ip
`客户端的IP地址
req.path/req.host/req.protocol/
`请求路径(不包含协议、主机、端口或查询字符串)/返回客户端报告的主机名(这些信息可以伪造,所以不应该用于安全目的)/协议
req.xhr
`一个简便属性,如果请求有Ajax发起将会返回true
req.url/req.originalUrl
`返回路径和查询字符串(不包含协议、主机、端口)
res.status(code)
`设置HTTP状态代码,如 function(req,res){ res.status(404.render('not-found'))}
res.cookie(name,value,[options])/res.clearCookie(name,[options])
`设置或者清楚客户端cookies值,需要中间件支持
res.redirect([status],url)
`重定向浏览器,默认重定向代码是302。通常你经过该尽量减少重定向,除非永久移动一个页面,这时候状态码301
res.send(body)/res.send(status,body)
·向客户端发送响应及可选状态码,如果body是一个对象或者一个数组,响应将会以JSON发送(这种情况为什么不使用res.json呢?)
res.json(status)/res.json(status,json)
·向客户端发送JSON以及可选的状态码
res.sendFile(path,[option],[callback])
·这个方法根据路径读取指定文件并将内容发送到客户端
res.locals,render(view,[locals],callback)
·res.locals是一个对象,包含用于渲染视图的默认上下文。
· res.render使用配置的模板引擎渲染视图,默认响应码为200
app.get('/',function(req,res){
res.render('index',{
message:'welcome',
style:req.query.style,
userid:req.cookie.userid
})
})
在静态页面中(以ejs模板引擎为例)使用<%= message%>输出welcome。render中的第二个参数就是所谓的context(上下文环境),当你渲染一个模板(静态页面如html格式),便会传递给模板引擎一个对象,叫做上下文对象,它能让替换标志运行。刚才我们就是用上下文对象中的message对象的值替换掉<%= message%>中的占位符,从而实现了前台页面上的动态数据的渲染
Nodejs使用exports和module.exports来完成功能的组织及重用。Nodejs模块允许你从被引入文件中选择要暴漏给程序的函数和变量。如果模块返回的函数或变量不止一个,那他可以通过设定exports对象的属性来指明他们;但如果模块只返回一个函数或变量,则可以设定module.exports属性。这样做可以选择把什么跟程序共享而不污染全局命名空间。
在moduleName.js文件内使用exports.something = function(){}类似的代码将函数导出,然后在目标文件内引入模块的该函数:var muModule = require('moduleName.js') muModule.somthing();//可以用exports导出多个函数
但是如果只是想用exports导出一个变量或函数,你可能会以为只要把exports设定成你想要的东西就行。但是这样是不行的,因为Node觉得不能用任何其他对象、函数或变量给exprts赋值。例如不能使用exports = something;应该用module.exports替换掉exports。用module.exports可以对外提供单个变量、函数或对象。如果创建了一个既有exports又有module.exports的模块,那么他会返回module.exports而exports则会被忽略
记住三点:
1.exxports是指向module.exports的引用,module.exports初始值为一个空对象,所以exports的值也为{},所以exports.myFun只是module.exports.myFun的简写
2.当我们想让模块道出的是一个对象时,exports和module.exports都可以用;而当我们导出非对象接口时,就必须也只能覆盖module.exports
3.如果把exports设置为别的,就打破了module.exports和exports之间的引用关系。那样exports就不能用了,因为他不在指向module.exports。如果想维持链接,需要让module.exports再指向exports:module.exports = exports
创建模块系统的注意事项
第一:如果模块是目录,在模块目录中定义的模块的文件必须命名为index.js,除非你在这个目录下一个叫package.json的文件里特别说明(其中一个名为main的键)
第二:Node能把模块作为对象缓存起来-》“猴子补丁”
app.post('/process',function(req,res){
console.log('color from filed : '+ req.body.color);
res.redirect('303','/thank-you')
})
5.上传文件:使用Formidable模块(Express4.0开始不支持Connect的内置中间件multipart)
安装:npm install --save formidable
引用:var formidable = require('formidable')
路由:
app.post('/contest/photos',function(req,res){
var form = new formidable.IncomingForm();
form.parse(req,function(err,fields,files){
if(err) return res.redirect(303,'/error');
console.log('recieved fields: ');
console.log(fields);
console.log('received files');
console.log(files);
res.redirect(303,'/thank-you')
});
})
//拦截所有未匹配路由的请求,如果请求流到了这里,则创建一个404状态的error,next(err)给下一个中间件
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
//这个中间件可以处理err请求,捕捉然后按照不同的环境处理
if (app.get('env') === 'dev' || app.get('env') === 'staging') {
app.use(function(err, req, res, next) {
res.render('error_dev', {
message: err.message,
error: err
});
});
}else {
app.use(function(err, req, res, next) {
res.render('error');
});
}
那么请求在管道中如何终止呢?这是又传给每个中间件的next函数来实现的如果不调用next(),请求就在那个中间件中终止了。这个时候你应该发送一个响应到客户端(res.send、res.json、res.render),如果你不这样做,客户端会被挂起并最终导致超时;切切相反,如果调用了next(),一般不宜在发送响应到客户端了。如果你发送了,管道中后续的中间件火炉有处理器还会执行,但是他们发送的任何响应都会被被忽略。
module.exports = {
/**
* 登陆状态检查
*/
authorize: function (req, res, next) {
if (!req.cookies.userId) {
res.redirect('/user/login');
} else {
next();
}
}
}
当用户点击个人资产按钮时,进行身份验证
app.get('/assets', controller.user.authorize, controller.assets.index);
用户请求/assets路径,首先调用user.authorize验证是否登陆,已登录则next()反之则重定向到/user/login路由
var app = require('../app');
var cluster = require('cluster');
var numCPUs = require('os').cpus().length;
if (cluster.isMaster) {
// Fork workers.
for (var i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on('exit', function(worker, code, signal) {
console.log('worker ' + worker.process.pid + ' died');
});
} else {
// Workers can share any TCP connection,in this case its a HTTP server
app.set('port', process.env.NODE_PORT || 9099 );
var server = app.listen(app.get('port'), function() {
console.log('Express server listening on port ' + server.address().port);
});
}
这样你只需执行node bin/www,nodejs就会为你当前系统的每一个内核开启一个线程,充分利用当前服务器的硬件资源,