Express是基于nodejs的web开发框架。优势是易上手、高性能、扩展性强。javascript
易上手:nodejs最初就是为了开发高性能web服务器而被设计出来的,然而相对底层的API会让很多新手望而却步。express对web开发相关的模块进行了适度的封装,屏蔽了大量复杂繁琐的技术细节,让开发者只须要专一于业务逻辑的开发,极大的下降了入门和学习的成本。css
高性能:express仅在web应用相关的nodejs模块上进行了适度的封装和扩展,较大程度避免了过分封装致使的性能损耗。html
扩展性强:基于中间件的开发模式,使得express应用的扩展、模块拆分很是简单,既灵活,扩展性又强。java
首先,须要安装nodejs,这一步请自行解决。接着,安装express的脚手架工具express-generator
,这对于咱们学习express颇有帮助。node
npm install -g express-generator
利用以前安装的脚手架工具,初始化咱们的demo项目。git
/tmp mkdir express-demo /tmp cd express-demo express-demo express create : . create : ./package.json create : ./app.js create : ./public create : ./public/javascripts create : ./public/images create : ./public/stylesheets create : ./public/stylesheets/style.css create : ./routes create : ./routes/index.js create : ./routes/users.js create : ./views create : ./views/index.jade create : ./views/layout.jade create : ./views/error.jade create : ./bin create : ./bin/www install dependencies: $ cd . && npm install run the app: $ DEBUG=express-demo:* npm start
按照指引,安装依赖。并启动服务github
npm install
而后,启动服务器。web
express-demo npm start > ex1@0.0.0 start /private/tmp/ex1 > node ./bin/www
访问浏览器,迈出成功的第一步。正则表达式
看下demo应用的目录结构。大部分时候,咱们的应用目录结构跟这个保持一致就能够了。也能够根据须要自行调整,express并无对目录结构进行限制。shell
从目录结构能够大体看出,express应用的核心概念主要包括:路由
、中间件
、模板引擎
。
express-demo tree -L 1 . ├── app.js # 应用的主入口 ├── bin # 启动脚本 ├── node_modules # 依赖的模块 ├── package.json # node模块的配置文件 ├── public # 静态资源,如css、js等存放的目录 ├── routes # 路由规则存放的目录 └── views # 模板文件存放的目录 5 directories, 2 files
上面提到,express主要包含三个核心概念:路由、中间件、模板引擎。
注意,笔者这里用的是
核心概念
这样的字眼,而不是核心模块
,为何呢?这是由于,虽然express的中间件有它的定义规范,可是express的内核源码中,实际上是没有所谓的中间件这样的模块的。
言归正传,三者简要的来讲就是。
中间件
:能够绝不夸张的说,在express应用中,一切皆中间件。各类应用逻辑,如cookie解析、会话处理、日志记录、权限校验等,都是经过中间件来完成的。
路由
:地球人都知道,负责寻址的。好比用户发送了个http请求,该定位到哪一个资源,就是路由说了算。
模板引擎
:负责视图动态渲染。下面会介绍相关配置,以及如何开发本身的模板引擎。
粗略来讲,express主要支持四种类型的路由,下面会分别举例进行说明
字符串类型
字符串模式类型
正则表达式类型
参数类型
分别举例以下,细节可参考官方文档。
var express = require('express'); var app = express(); // 路由:字符串类型 app.get('/book', function(req, res, next){ res.send('book'); }); // 路由:字符串模式 app.get('/user/*man', function(req, res, next){ res.send('user'); // 好比: /user/man, /user/woman }); // 路由:正则表达式 app.get(/animals?$/, function(req, res, next){ res.send('animal'); // 好比: /animal, /animals }); // 路由:命名参数 app.get('/employee/:uid/:age', function(req, res, next){ res.json(req.params); // 好比:/111/30,返回 {"uid": 111, "age": 30} }); app.listen(3000);
当你用的应用愈来愈复杂,不可避免的,路由规则也会愈来愈复杂。这个时候,对路由进行拆分是个不错的选择。
咱们分别看下两段代码,路由拆分的好处就直观的体现出来了。
路由拆分前
var express = require('express'); var app = express(); app.get('/user/list', function(req, res, next){ res.send('/list'); }); app.get('/user/detail', function(req, res, next){ res.send('/detail'); }); app.listen(3000);
这样的代码会带来什么问题呢?不管是新增仍是修改路由,都要带着/user
前缀,这对于代码的可维护性来讲是大忌。这对小应用来讲问题不大,但应用复杂度一上来就会是个噩梦。
路由拆分后
能够看到,经过express.Router()
进行了路由拆分,新增、修改路由都变得极为便利。
var express = require('express'); var app = express(); var user = express.Router(); user.get('/list', function(req, res, next){ res.send('/list'); }); user.get('/detail', function(req, res, next){ res.send('/detail'); }); app.use('/user', user); // mini app,一般作应用拆分 app.listen(3000);
通常学习js的时候,咱们都会听到一句话:一切皆对象。而在学习express的过程当中,很深的一个感觉就是:一切皆中间件。好比常见的请求参数解析、cookie解析、gzip等,均可以经过中间件来完成。
贴上官网的一张图镇楼,图中所示就是传说中的中间件了。
首先,咱们本身编写一个极简的中间件。虽然没什么实用价值,但中间件就长这样子。
参数
:三个参数,熟悉http.createServer()
的同窗应该比较眼熟,其实就是req(客户端请求实例)、res(服务端返回实例),只不过进行了扩展,添加了一些使用方法。
next
:回调方法,当next()被调用时,就进入下一个中间件。
function logger(req, res, next){ console.log('here comes request'); next(); }
来看下实际例子:
var express = require('express'); var app = express(); app.use(function(req, res, next) { console.log('1'); next(); }); app.use(function(req, res, next) { console.log('2'); next(); }); app.use(function(req, res, next) { console.log('3'); res.send('hello'); }); app.listen(3000);
请求 http://127.0.0.1:3000,看下控制台输出,以及浏览器返回内容。
middleware git:(master) node chains.js 1 2 3
根据做用范围,中间件分为两大类:
应用级中间件
路由级中间件。
二者的区别不容易说清楚,由于从本质来说,两类中间件是彻底等同的,只是使用场景不一样。同一个中间件,既能够是应用级中间件、也能够是路由级中间件。
直接上代码可能更直观。参考下面代码,能够简单粗暴的认为:
应用级中间件:app.use()
、app.METHODS()
接口中使用的中间件。
路由级中间件:router.use()
、router.METHODS()
接口中使用的中间件。
var express = require('express'); var app = express(); var user = express.Router(); // 应用级 app.use(function(req, res, next){ console.log('收到请求,地址为:' + req.url); next(); }); // 应用级 app.get('/profile', function(req, res, next){ res.send('profile'); }); // 路由级 user.use('/list', function(req, res, next){ res.send('/user/list'); }); // 路由级 user.get('/detail', function(req, res, next){ res.send('/user/detail'); }); app.use('/user', user); app.listen(3000);
上面也提到了,中间件的开发是是分分钟的事情,不赘述。
function logger(req, res, next){ doSomeBusinessLogic(); // 业务逻辑处理,好比权限校验、数据库操做、设置cookie等 next(); // 若是须要进入下一个中间件进行处理,则调用next(); }
包括但不限于以下。更多经常使用中间件,能够点击 这里
body-parser
compression
serve-static
session
cookie-parser
morgan
模板引擎你们不陌生了,关于express模板引擎的介绍能够参考官方文档。
下面主要讲下使用配置、选型等方面的内容。
包括但不限于以下模板引擎
jade
ejs
dust.js
dot
mustache
handlerbar
先看代码。
// view engine setup app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'jade');
有两个关于模版引擎的配置:
views
:模版文件放在哪里,默认是在项目根目录下。举个例子:app.set('views', './views')
view engine
:使用什么模版引擎,举例:app.set('view engine', 'jade')
能够看到,默认是用jade
作模版的。若是不想用jade
怎么办呢?下面会提供一些模板引擎选择的思路。
须要考虑两点:实际业务需求、我的偏好。
首先考虑业务需求,须要支持如下几点特性。
支持模版继承(extend)
支持模版扩展(block)
支持模版组合(include)
支持预编译
对比了下,jade
、nunjunks
都知足要求。我的更习惯nunjunks
的风格,因而敲定。那么,怎么样使用呢?
首先,安装依赖
npm install --save nunjucks
而后,添加以下配置
var nunjucks = require('nunjucks'); nunjucks.configure('views', { autoescape: true, express: app }); app.set('view engine', 'html');
看下views/layout.html
<!DOCTYPE html> <html> <head> <title> {% block title %} layout title {% endblock %} </title> </head> <body> <h1> {% block appTitle %} layout app title {% endblock %} </h1> <p>正文</p> </body> </html>
看下views/index.html
{% extends "layout.html" %} {% block title %}首页{% endblock %} {% block appTitle %}首页{% endblock %}
经过app.engine(engineExt, engineFunc)
来注册模板引擎。其中
engineExt:模板文件后缀名。好比jade
。
engineFunc:模板引擎核心逻辑的定义,一个带三个参数的函数(以下)
// filepath: 模板文件的路径 // options:渲染模板所用的参数 // callback:渲染完成回调 app.engine(engineExt, function(filepath, options, callback){ // 参数一:渲染过程的错误,如成功,则为null // 参数二:渲染出来的字符串 return callback(null, 'Hello World'); });
好比下面例子,注册模板引擎 + 修改配置一块儿,因而就能够愉快的使用后缀为tmpl
的模板引擎了。
app.engine('tmpl', function(filepath, options, callback){ // 参数一:渲染过程的错误,如成功,则为null // 参数二:渲染出来的字符串 return callback(null, 'Hello World'); }); app.set('views', './views'); app.set('view engine', 'tmpl');
模板引擎对比:点击这里
express模版引擎介绍:点击这里
开发模版引擎:点击这里
前面讲了一些express的入门基础,感兴趣的同窗能够查看官方文档。篇幅所限,有些内容在后续文章展开,好比下面列出来的内容等。
进程管理
会话管理
日志管理
性能优化
调试
错误处理
负载均衡
数据库支持
HTTPS支持
业务实践
。。。
express官网:http://expressjs.com/