標籤:des style class blog code http
express
正如ASP.NET MVC 在作為.net平台下最佳的 Mvc架構的地位一樣,express 在 node.js 環境也有著相同的重要性。在百度上 "nodejs express" 會跑出一大堆關於怎麼用開發 express 來開發mvc文章 ,相同的內容在這裡我不想重複敘述,關於express的入手文章大家到百度上搜就好了。這隻是一篇隨筆不是教程, 我是想用ASP.NET MVC與 express 來在他們擅長的方面上做一些比較,從中看看我們作為開發人員能得到什麼,哪一個對於我們更能帶來好處。
express 與 OWIN
OWIN 全名為:Open Web Interface for .net , 是一套可以讓你在IIS中開闢中一套獨立運行環境,按需配置模組可獨立的應用程式架構。我不知道我的解釋是否準確,更多的內容可以參考:"Getting Started with OWIN and Katana" 和 Katan 在Codeplex上的項目。 簡單點理解就是你可以通過純程式碼,在一個開機檔案內配置一些已有的“中介軟體(middel ware) ” 來配置你的Web的功能。下面來看一段代碼,這段代碼是從asp.net上截取的,是向網站加入一個 日誌的中介軟體實現日誌記錄
日誌中介軟體實現
public class LoggerMiddleware : OwinMiddleware{ private readonly ILog _logger; public LoggerMiddleware(OwinMiddleware next, ILog logger) : base(next) { _logger = logger; } public override async Task Invoke(IOwinContext context) { _logger.LogInfo("Middleware begin"); await this.Next.Invoke(context); _logger.LogInfo("Middleware end"); }}
開機檔案
public class Startup{ public void Configuration(IAppBuilder app) { app.Use<LoggerMiddleware>(new TraceLogger()); var config = new HttpConfiguration(); // configure Web API app.UseWebApi(config); // additional middleware registrations }}
到此,如果你是一位MVC開發人員那麼請先不要往下看,現在需要一點點的時間給你思考一下,這個東東的意義在哪裡,與我們使用的常規MVC有何區別?這個代碼跑起來要比運行在MVC快得多得去了,起碼IIS不會起動IIS模組載入機制,也不會先行編譯頁面。
我認為OWIN在ASP.NET MVC內是一個很了不起的架構,他可以簡化掉現在MVC內很多不必要的模組。這些不必要的模組在讓我們的程式變得臃腫、龐大。明明一個小小的Web如果用MVC來做的話,你會發現用php或者直接用ASP.NET PAGES 做會比它快好多。 有可能OWIN是未來ASP.NET MVC版本發展的一個走向,作為開發人員我們有權利確定哪些東西是我們要的,哪些是我們不要的,而不是一股腦地將“強大”的功能塞到我們的項目裡面。
接下來我們看看相同的功能在 node.js中是怎麼做的,然後大家來評估一下哪個更好:
app.js (express啟動的必備檔案)
var express = require(‘express‘);var logger = require(‘morgan‘);app.use(logger(‘dev‘));app.listen(3001);
在代碼之間對比實際大家在app內寫的東西都不多,但值得注意的是express一個成熟的架構,而OWIN是個新生兒。OWIN內做的事都要你自己一個一個地實現,而express內可能只是到npm上找找有哪些好用的模組裝一下就完事了。現在asp.net官網上找到的所有關於OWIN的範例在node.js加構下早就有出了名的現成模組了,就好像OAUTH 這個苦B功能,在asp.net上有非常多的內容在說它,你可以試試在express上做,簡直就是手至擒來的。
SignalR
說說 SignalR ,關於這個內容開始接觸時解得他真的非常贊,但看了google在對 WebRTC 上的技術示範以後就覺得 SignalR 是一個大忽悠。 SignalR實際上只是通過 WebStocket 來做反向通訊的一種機制(服務端->用戶端)。微軟稱為 伺服器與瀏覽器的"即時通訊",其中的內容並不難實現,但可惜的是WebStocket正在被WebRTC技術所取締,SignalR 做的一大堆東西我們都可以在 nodejs 下 安裝一個非常著名的模組: socket.io 一下搞定,而且socket.io不單可以做到伺服器與用戶端之間做即時通訊,還可以做很多即時通訊的功能,功能極其強大!
var app = require(‘express‘)();var server = require(‘http‘).Server(app);var io = require(‘socket.io‘)(server);io.on(‘connection‘, function(){ /* … */ });server.listen(3000);
這就是一個使用socket.io 在express構建的最簡單的通訊伺服器代碼。SignalR的那點事就不想說了,實在連解釋它也覺得很累。(^_^ 我是一個很懶很喜歡簡單的人)。 建議如果想入手 SignalR 的朋友可以先看看關於 socket.io , 現在的微軟與以前不一樣了,老鮑將MS玩爛了將很明明很簡單的東西都做成了沒人願意用的龐然大物,甚至連我們跟隨MS做技術的也同時遭殃。
路由 Routing
我更喜歡 epxress 在Routing的使用,它的定義處理方式都比較簡單易懂,而且他更容易擷取當前啟動並執行路由對象,用代碼說話吧:
var express = require(‘express‘);var router = express.Router();router.get(‘/invoice/:id‘, function(req, res) { var id= req.params.id; ...}).post(function(req,res) { //直接控制POST方法 var postData=req.body; ...});
1. 對參數和的定義會比在ASP.NET中使用Regex更簡單(當然這裡也可以直接寫Regex)
2. 注意 req.body 這個對象(需要先引入body-parser 模組),這個是由瀏覽器端Post過來的Form而且已經是一個JSON對象,不像MVC內要搞ODATA才能正常處理JSON
3. 一邊定義一邊編碼,這是我喜歡的。當一個項目中路由多了,這樣做的話找起來非常容易。
再回頭看看MVC對Router的定義:
首先是RouteConfig.cs (最讓人討厭的是每個 Route都需要有名稱!)
public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Invoice", action = "Index", id = UrlParameter.Optional } ); } }
然後是:InvoiceController.cs
public class InvoiceController : Controller { public ActionResult Index(int id) { return View(); } }
當我的項目中有超過 50個路由定義,我就要老在找路由與控制的關係....... 苦B啊....
視圖引擎
我在ASP.NET MVC項目中基本上不會使用其它的視圖引擎,因為覺得沒有其它的比Razor更好更快。第一次使用node.js的時候我是有點懵,因為express 上能支援的視圖引擎實在是太多了!我認為選擇多對開發人員來說並不是一件很實在的大好事,因為對於一個小白的話選誰才是最好的,這個才是一個大難題。 經過一番google, 最後也就找到了它— jade. 與Jade齊名的還有: EJS , CoffeeKup . 最終還是覺得jade的代碼量是最少的,最容易懂的。經過一兩個小時的閱讀與實驗基本上就學會了。從代碼量來說可以比Razor少上一半,運行速度極高。還有我最喜歡的一點是他可以支援動態編譯與輸出。這要在Razor做的話那就得實現一個VirtualProvider類將頁面嵌入到assembily中才能實現了,過程非常痛苦。這裡只想show兩段代碼,一段是對jade的一瞥,另一段是動態編譯頁面。(這裡我就懶一點了,不帖asp.net MVC的實現了,有興趣的話你自己可以嘗試一下用ASP.NET MVC實現一下,由其是第二步)
看看jade
定一個與asp.net MVC中類似的layout.jade(母板)
doctype htmlhtml head title= title include ./includes/head link(href="/styles/style.css" , rel="stylesheet") block head body.page block header block content block footer
然後搞一個login.jade
extends ../layoutblock content .row div(class="col-lg-4 col-md-8 col-sm-12 col-lg-centered") form.text-center(style="padding:20px;") div img(src="/logo.png") p .input-group span.ctrl-addon i.icon-user-3 input#userName(type="text" name="userName" required="required" autofocus="autofocus" placeholder="Enter your user account or email") p label input(type="checkbox" name="rememberMe") span Remember me span.pull-right a Forgot your password? p button(class="primary fill-width") Login div a.fill-width(role="button") Sign up
對比一下Razor就知道到底少了多少代碼。
動態編譯 - 動態輸出一個能支援markup格式的網頁內容
app.use("/dynamic-page/",function(req,res){ var lines=[]; //讓引擎直接格式化markup的輸出 lines.push("markup:"); lines.push(" **粗體** 字"); lines.push("p."); lines.push(" 這裡是一段最為簡單的段落文字");
lines.push("#{model.name}") ;
var _fn=jade.compile(lines.join("\n"));
res.send(_fn({ model:{ name:"我是動態編譯的內容物件名" } } ));
在ASP.NET MVC中在Action內動態輸出文本絕無問題,但如果要傳入一個內容物件然後再動態編譯輸出那就是件極痛苦的事了。這個功能由其是在做郵件模板時是非常有用的,我在ASP.NET MVC內只能再找一個動支援Razor文法的類庫再重編譯輸出這個網頁內容,這種做法想想都夠腦殘的。
小結
搞好好幾天覺得nodejs+express就是一個字:爽! 而更多關於express的功能我就不在這裡說了,大家去官網看吧。如果你有不同的看法或者認為express還有更玄的功能,那就給我留言吧。
相關資源:
安裝 : npm install express
官網:http://expressjs.com/