前言javascript
Nodejs是一個年輕的編程框架,充滿了活力和無限激情,一直都在保持着快速更新。基於Nodejs的官方Web開發庫Express也在同步發展着,每一年升級一個大版本,甚至對框架底層都作了大手術。在Express4時,替換掉中件間庫connect,而改用多個更細粒度的庫來取代。帶來的好處是明顯地,這些中間件能更自由的更新和發佈,不會受到Express發佈週期的影響;但問題也是很的棘手,不兼容於以前的版本,升級就意味着要修改代碼。css
以前寫過一篇文章「Nodejs開發框架Express3.0開發手記–從零開始」,不少新學Node的朋友都在參考,但因爲Express已經升級,文章中有部分的代碼已經不能使用,因此就有了這篇介紹Express4.x的文章。html
目錄前端
讓咱們從頭開始Express4.x的安裝和使用吧,安裝Node和NPM在本文就很少說了。Linux環境安裝請參考文章,準備Nodejs開發環境Ubuntu,Window環境安裝直接下載Node的安裝文件,雙擊安裝就好了。java
個人系統環境node
首先,咱們須要安裝express庫。在Express3.6.x以前的版本,Express須要全局安裝的,項目構建器模塊是合併在Express項目中的,後來這個構建器被拆分出來,獨立成爲了一個項目express-generator,如今咱們只須要全局安裝express-generator項目就好了。jquery
~ npm install -g express-generator@4 #全局安裝-g C:\Users\Administrator\AppData\Roaming\npm\express -> C:\Users\Administrator\AppData\Roaming\npm\node_modules\express-ge nerator\bin\express express-generator@4.11.2 C:\Users\Administrator\AppData\Roaming\npm\node_modules\express-generator ├── sorted-object@1.0.0 ├── commander@2.6.0 └── mkdirp@0.5.0 (minimist@0.0.8)
安裝好express-generator包後,咱們在命令行就可使用express命令了。git
~ express -V # 檢查express的版本 4.11.2 ~ express -h # 檢查看express的幫助命令 Usage: express [options] [dir] Options: -h, --help output usage information -V, --version output the version number -e, --ejs add ejs engine support (defaults to jade) --hbs add handlebars engine support -H, --hogan add hogan.js engine support -c, --css add stylesheet support (less|stylus|compass) (defaults to plain css) --git add .gitignore -f, --force force on non-empty directory
接下來,咱們使用express的命令,來建立項目了。github
~ cd D:\workspace\javascript # 進入工做目錄 ~ D:\workspace\javascript>express -e nodejs-demo # 建立項目 create : nodejs-demo create : nodejs-demo/package.json create : nodejs-demo/app.js create : nodejs-demo/public/javascripts create : nodejs-demo/public/images create : nodejs-demo/public create : nodejs-demo/public/stylesheets create : nodejs-demo/public/stylesheets/style.css create : nodejs-demo/views create : nodejs-demo/views/index.ejs create : nodejs-demo/views/error.ejs create : nodejs-demo/routes create : nodejs-demo/routes/index.js create : nodejs-demo/routes/users.js create : nodejs-demo/bin create : nodejs-demo/bin/www install dependencies: $ cd nodejs-demo && npm install run the app: $ DEBUG=nodejs-demo:* ./bin/www
進入項目目錄,下載依賴庫,構建項目。express
~ D:\workspace\javascript>cd nodejs-demo && npm install
啓動項目。
~ D:\workspace\javascript\nodejs-demo>npm start > express4-demo@0.0.0 start D:\workspace\javascript\nodejs-demo > node ./bin/www module.js:338 throw err; ^ Error: Cannot find module './routes/users' at Function.Module._resolveFilename (module.js:336:15) at Function.Module._load (module.js:278:25) at Module.require (module.js:365:17) at require (module.js:384:17) at Object. (D:\workspace\javascript\nodejs-demo\app.js:9:13) at Module._compile (module.js:460:26) at Object.Module._extensions..js (module.js:478:10) at Module.load (module.js:355:32) at Function.Module._load (module.js:310:12) at Module.require (module.js:365:17)
第一次啓動發生了錯誤,多是express-generator和express不匹配形成的,找到問題在app.js文件中,註釋第9行和第26行。
.. //var users = require('./routes/users'); .. //app.use('/users', users); ..
再次啓動項目。
D:\workspace\javascript\nodejs-demo>npm start > express4-demo@0.0.0 start D:\workspace\javascript\nodejs-demo > node ./bin/www
項目啓動成功,打開瀏覽器 http://localhost:3000,就能夠看到顯示的頁面了。
這樣很是簡單地,咱們就把一個最基本的Web應用作好了,就是幾條命令而已。
接下來,咱們詳細看一下Express4項目的結構、配置和使用。
package.json用於項目依賴配置及開發者信息,scripts屬性是用於定義操做命令的,能夠很是方便的增長啓動命令,好比默認的start,用npm start表明執行node ./bin/www命令。
查看package.json文件。
{ "name": "express4-demo", "version": "0.0.0", "private": true, "scripts": { "start": "node ./bin/www" }, "dependencies": { "body-parser": "~1.10.2", "cookie-parser": "~1.3.3", "debug": "~2.1.1", "ejs": "~2.2.3", "express": "~4.11.1", "morgan": "~1.5.1", "serve-favicon": "~2.2.0" } }
從Express3.x升級到Express4.x,主要的變化就在app.js文件中。查看app.js文件,我已經增長註釋說明。
// 加載依賴庫,原來這個類庫都封裝在connect中,如今需地注單獨加載 var express = require('express'); var path = require('path'); var favicon = require('serve-favicon'); var logger = require('morgan'); var cookieParser = require('cookie-parser'); var bodyParser = require('body-parser'); // 加載路由控制 var routes = require('./routes/index'); //var users = require('./routes/users'); // 建立項目實例 var app = express(); // 定義EJS模板引擎和模板文件位置,也可使用jade或其餘模型引擎 app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'ejs'); // 定義icon圖標 app.use(favicon(__dirname + '/public/favicon.ico')); // 定義日誌和輸出級別 app.use(logger('dev')); // 定義數據解析器 app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: false })); // 定義cookie解析器 app.use(cookieParser()); // 定義靜態文件目錄 app.use(express.static(path.join(__dirname, 'public'))); // 匹配路徑和路由 app.use('/', routes); //app.use('/users', users); // 404錯誤處理 app.use(function(req, res, next) { var err = new Error('Not Found'); err.status = 404; next(err); }); // 開發環境,500錯誤處理和錯誤堆棧跟蹤 if (app.get('env') === 'development') { app.use(function(err, req, res, next) { res.status(err.status || 500); res.render('error', { message: err.message, error: err }); }); } // 生產環境,500錯誤處理 app.use(function(err, req, res, next) { res.status(err.status || 500); res.render('error', { message: err.message, error: {} }); }); // 輸出模型app module.exports = app;
咱們看到在app.js中,原來調用connect庫的部分都被其餘的庫所代替,serve-favicon、morgan、cookie-parser、body-parser,默認項目中,只用到了最基本的幾個庫,尚未其餘須要替換的庫,在本文最後有詳細列出。
另外,原來用於項目啓動代碼也被移到./bin/www的文件,www文件也是一個node的腳本,用於分離配置和啓動程序。
查看./bin/www文件。
#!/usr/bin/env node /** * 依賴加載 */ var app = require('../app'); var debug = require('debug')('nodejs-demo:server'); var http = require('http'); /** * 定義啓動端口 */ var port = normalizePort(process.env.PORT || '3000'); app.set('port', port); /** * 建立HTTP服務器實例 */ var server = http.createServer(app); /** * 啓動網絡服務監聽端口 */ server.listen(port); server.on('error', onError); server.on('listening', onListening); /** * 端口標準化函數 */ function normalizePort(val) { var port = parseInt(val, 10); if (isNaN(port)) { return val; } if (port >= 0) { return port; } return false; } /** * HTTP異常事件處理函數 */ function onError(error) { if (error.syscall !== 'listen') { throw error; } var bind = typeof port === 'string' ? 'Pipe ' + port : 'Port ' + port // handle specific listen errors with friendly messages switch (error.code) { case 'EACCES': console.error(bind + ' requires elevated privileges'); process.exit(1); break; case 'EADDRINUSE': console.error(bind + ' is already in use'); process.exit(1); break; default: throw error; } } /** * 事件綁定函數 */ function onListening() { var addr = server.address(); var bind = typeof addr === 'string' ? 'pipe ' + addr : 'port ' + addr.port; debug('Listening on ' + bind); }
建立Bootstrap界面框架,直接在index.ejs文件上面作修改。能夠手動下載Bootstrap庫放到項目中對應的位置引用,也能夠經過bower來管理前端的Javascript庫,參考文章 bower解決js的依賴管理。另外還能夠直接使用免費的CDN源加載Bootstrap的css和js文件。下面我就直接使用Bootcss社區提供的CDN源加載Bootstrap。
編輯views/index.ejs文件
<!DOCTYPE html> <html lang="zh-CN"> <head> <title><%= title %></title> <link rel="stylesheet" href="http://cdn.bootcss.com/bootstrap/3.3.2/css/bootstrap.min.css"> <link rel='stylesheet' href='/stylesheets/style.css' /> </head> <body> <div class="well jumbotron"> <h1><%= title %></h1> <p>This is a simple hero unit, a simple jumbotron-style component for calling extra attention to featured content or information.</p> <p><a class="btn btn-primary btn-lg" href="#" role="button">Learn more</a></p> </div> <script src="http://cdn.bootcss.com/jquery/1.11.2/jquery.min.js"></script> <script src="http://cdn.bootcss.com/bootstrap/3.3.2/js/bootstrap.min.js"></script> </body> </html>
效果以下,已經加入了bootstrap的樣式了。
接下來,咱們把index.ejs頁面切分紅3個部分:header.ejs, index.ejs, footer.ejs,用於網站頁面的模塊化。
編輯header.ejs。
<!DOCTYPE html> <html lang="zh-CN"> <head> <title><%= title %></title> <link rel="stylesheet" href="http://cdn.bootcss.com/bootstrap/3.3.2/css/bootstrap.min.css"> <link rel='stylesheet' href='/stylesheets/style.css' /> </head> <body>
編輯footer.ejs。
<script src="http://cdn.bootcss.com/jquery/1.11.2/jquery.min.js"></script> <script src="http://cdn.bootcss.com/bootstrap/3.3.2/js/bootstrap.min.js"></script> </body> </html>
編輯index.ejs。
<% include header.ejs %> <div class="well jumbotron"> <h1><%= title %></h1> <p>This is a simple hero unit, a simple jumbotron-style component for calling extra attention to featured content or information.</p> <p><a class="btn btn-primary btn-lg" href="#" role="button">Learn more</a></p> </div> <% include footer.ejs %>
把頁表和頁底的代碼分離後,讓index.ejs頁面的核心代碼更少,更容易維護。
路由功能,是Express4之後全面改版的功能。在應用程序加載隱含路由中間件,不用擔憂在中間件被裝載相對於路由器中間件的順序。定義路由的方式是不變的,路由系統中增長2個新的功能。
app.route方法會返回一個Route實例,它能夠繼續使用全部的HTTP方法,包括get,post,all,put,delete,head等。
app.route('/users') .get(function(req, res, next) {}) .post(function(req, res, next) {})
express.Router類,則能夠幫助咱們更好的組織代碼結構。在app.js文件中,定義了app.use(‘/’, routes); routes是指向了routes目錄下的index.js文件,./routes/index.js文件中,express.Router被定義使用,路徑/*處理都會由routes/index.js文件裏的Router來處理。若是咱們要管理不一樣的路徑,那麼能夠直接配置爲多個不一樣的Router。
app.use('/user', require('./routes/user').user); app.use('/admin', require('./routes/admin').admin); app.use('/', require('./routes'));
對於剛接觸Express4.x的朋友,能夠直接從Github上面下載本文項目中的源代碼,按照片文章中的介紹學習Express4,下載地址:https://github.com/bsspirit/nodejs-demo/tree/express4
也能夠直接用github命令行來下載:
~ git clone git@github.com:bsspirit/nodejs-demo.git # 下載github項目 ~ cd nodejs-demo # 進入下載目錄 ~ git checkout express4 # 切換到express4的分支 ~ npm install # 下載依賴庫 ~ npm start # 啓動服務器
注:Github上本項目有3分支,express3和master分支都是express3的例子,express4分支是本文的例子。
固然,本文對express4的介紹其實還遠遠不夠,除了文中說到的express改動的部分,其餘的部分都express3相似,因此更詳細的使用說明,還請你們同時參考文章,Nodejs開發框架Express3.0開發手記–從零開始 來一塊兒學習。