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/