歡迎加群交流,群號 197339705。
入門簡介
Express是基於nodejs的web開發框架。優點是易上手、高效能、擴充套件性強。
- 易上手:nodejs最初就是為了開發高效能web伺服器而被設計出來的,然而相對底層的API會讓不少新手望而卻步。express對web開發相關的模組進行了適度的封裝,遮蔽了大量複雜繁瑣的技術細節,讓開發者只需要專注於業務邏輯的開發,極大的降低了入門和學習的成本。
- 高效能:express僅在web應用相關的nodejs模組上進行了適度的封裝和擴充套件,較大程度避免了過度封裝導致的效能損耗。
- 擴充套件性強:基於中介軟體的開發模式,使得express應用的擴充套件、模組拆分非常簡單,既靈活,擴充套件性又強。
環境準備
首先,需要安裝nodejs,這一步請自行解決。接著,安裝express的腳手架工具express-generator
,這對於我們學習express很有幫助。
npm install -g express-generator複製程式碼
第一個demo
利用之前安裝的腳手架工具,初始化我們的demo專案。
/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複製程式碼
按照指引,安裝依賴。並啟動服務
npm install複製程式碼
然後,啟動伺服器。
express-demo npm start
> ex1@0.0.0 start /private/tmp/ex1
> node ./bin/www複製程式碼
訪問瀏覽器,邁出成功的第一步。
目錄結構介紹
看下demo應用的目錄結構。大部分時候,我們的應用目錄結構跟這個保持一致就可以了。也可以根據需要自行調整,express並沒有對目錄結構進行限制。
從目錄結構可以大致看出,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複製程式碼
應用級中介軟體 vs 路由級中介軟體
根據作用範圍,中介軟體分為兩大類:
- 應用級中介軟體
- 路由級中介軟體。
兩者的區別不容易說清楚,因為從本質來講,兩類中介軟體是完全等同的,只是使用場景不同。同一個中介軟體,既可以是應用級中介軟體、也可以是路由級中介軟體。
直接上程式碼可能更直觀。參考下面程式碼,可以簡單粗暴的認為:
- 應用級中介軟體:
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
- nunjunks
配置說明
先看程式碼。
// 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
的風格,於是敲定。那麼,怎麼樣使用呢?
支援nunjucks
首先,安裝依賴
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官網:expressjs.com/