您好,登錄后才能下訂單哦!
平時做項目中的Web應(yīng)用都是用Asp.Net或者Java,但有時候需要快速做一些小Web的時候,感覺用Asp.Net或者Java都有點(diǎn)重。一開始想學(xué)學(xué)PHP,但實在不喜歡PHP的語法,所只用PHP寫了兩個簡單的Demo之后就寫不下去了。了解到最近Node.js有點(diǎn)熱,前景也不錯,而且JavaScript平時也都在用,所以決定學(xué)習(xí)下Node.js。
準(zhǔn)備入門,習(xí)慣做兩件事,一件是在Google上搜索相關(guān)的入門教程,參考等;二是去官方網(wǎng)站找找Guide或者M(jìn)anual。最后花了一兩天瀏覽了些資料,這兩個夠了:
Node.js入門>>一本全面的Node.js教程
Node.js概述(by 阮一峰)
當(dāng)然還有其它一些資料,比如博客、論壇之類。不過官方網(wǎng)站上只找到API文檔,適合參考不適合入門。所有這些資料主要是瀏覽一遍,認(rèn)識下Node.js,然后還是要在實踐中學(xué)習(xí)。
官方下載,安裝都很順利。不過雖然安裝時修改了PATH,但是安裝好之后命令行不能直接運(yùn)行“node”,想起Windows有個老毛病——經(jīng)常安裝程序修改了PATH之后不會生效,所以自己又去系統(tǒng)環(huán)境變量設(shè)置里重新配置了一下PATH,node命令就可用了。
“Helloworld”還是很簡單的,把各種教程上的示例都試了下,然后準(zhǔn)備寫個小Web。Web Helloworld也很簡單,不過要想寫功能完整的Web,還是得花些精神,所以還是找框架吧。Google出來Express評價不錯,也比較主流,所以決定用Express。仍然是Google+官方文檔,這兩個資料都不錯:
官方的 Express Guide
中文翻譯的 Express 新手指南
簡單實踐之后準(zhǔn)備構(gòu)思自己的第一個Node.js Web應(yīng)用。因為懶得寫HTML,最近又正好經(jīng)常寫Markdown的文檔,所以準(zhǔn)備用Markdown來建個站。Markdown解析當(dāng)然想自己寫,所以仍然是老辦法,Google。Node.js的Markdown包找到兩個,都是Github上:
https://github.com/evilstreak/markdown-js
https://github.com/andris9/node-markdown
也不知道哪個好,所以隨便選一個,就選了第一個。當(dāng)然在建站之前還是需要實驗下的,基本滿足要求,能支持標(biāo)準(zhǔn)的Markdown語法,但有一些小BUG。因為這次目的是熟悉Node.js和Express,所以不糾結(jié)這個問題了,以后有空再找更好的Markdown解析包,實在找不到自己寫個也不是很麻煩的事情。
一切準(zhǔn)備就緒,開始建站,這里記錄下建站的詳細(xì)過程,一步步說明,入門級的。老實說我比較懶,不想自己去準(zhǔn)備Express的結(jié)構(gòu),所以用了傳說中最好的Node.js IDE - JetBrain WebStrom。WebStorm新建項目時有“Node.js Express App”模板
然后在Node.js Express App的選項中,選擇使用EJS模板引擎和LESS樣式引擎。雖然很多人推薦Jade模板引擎,但是這是個新語法,而且也是我不喜歡的那種。還是EJS更貼近ASP和JSP的語法,所以選擇它了。至于LESS,寫起來肯定要比直接寫CSS輕松得多,這個早就有經(jīng)驗了。
Express應(yīng)用信息和依賴包在package.json中配置。先得把markdown加進(jìn)來,所以修改WebStorm生成的package.json:
{ "name": "application-name", "version": "0.0.1", "private": true, "scripts": { "start": "node app.js" }, "dependencies": { "express": "3.5.0", "ejs": "*", "less-middleware": "*", "markdown": "*" } }
最后那句 "markdown": "*" 就是新加的內(nèi)容。package.json是JSON格式,需要使用雙引號把屬性名和字符串值包起來。雖然Node.js規(guī)范推薦大家在編程時使用單引號表示字符串,但這里,單引號是不行的。
Express App的入口是app.js,這個也在package.json中配置:"start"
:
"node app.js"
。WebStorm生成的app.js中是通過3000端口監(jiān)聽服務(wù),因為我的機(jī)器上沒有安裝Web服務(wù)器,80端口空著,所以我把端口號改成了80。然后,看app.js的源碼,在啟動HTTP服務(wù)之前配置了兩行URL Route??紤]到以后的應(yīng)用中URL路由配置可能會很長,再加上我有點(diǎn)潔癖,所以我決定嘗試把URL路由放在一個獨(dú)立的腳本中配置,于是在根目錄下創(chuàng)建了一個app-routes.js,專們用來配置路由:
var routes = require('./routes'); var user = require('./routes/user'); exports.route = function (app) { app.get('/', routes.index); app.get('/users', user.list); };
然后在app.js中引入app-routes,并調(diào)用導(dǎo)出的route方法,順便把上面沒用的require都刪了:
// app.get('/', routes.index); // app.get('/users', user.list); require('./app-routes').route(app);
運(yùn)行了下,效果不錯,路由沒問題。剩下的就是解析Markdown的問題了。Markdown文件我準(zhǔn)備專門建個目錄來保存,所有文件都用其它編輯器(比如Sublime Text)寫好放在里面,然后通過在url中直接輸入“/文件名”的方式來打開解析后的HTML頁面。
然后在routes目錄下添加了一個markdown.js,這個腳本根據(jù)URL參數(shù),在md目錄下選擇對應(yīng)的文件,解析后,通過views目錄下新添加的md.ejs模板顯示成HTML,所以目錄結(jié)構(gòu)就像這個
接著添加路由,將訪問請求交給markdown.js來處理
var routes = require('./routes'); var markdown = require('./routes/markdown'); exports.route = function (app) { app.get('/(:md)?', markdown.show); };
還有md.ejs模板,需要在<body>標(biāo)準(zhǔn)中顯示由Markdown文件轉(zhuǎn)換而來的HTML,所以使用<%- %>標(biāo)記。
<!DOCTYPE html> <html> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"/> <title><%= title %></title> <link rel='stylesheet' href='/stylesheets/style.css'/> </head> <body> <%- content %> </body> </html>
markdown.js中的處理過程是獲取路由參數(shù),再根據(jù)參數(shù)在md目錄下去找對應(yīng)的文件,如果沒找到直接返回404錯誤。如果找到了就將這個文件的內(nèi)容讀出來,解析成HTML,傳遞給md.ejs輸出到瀏覽器。同時考慮如果URL不帶參數(shù),則說明是訪問首頁,markdown.js應(yīng)該直接去解析md/index.md。
var fs = require("fs"); var path = require("path"); var markdown = require("markdown").markdown; exports.show = function (req, res) { // 獲取參數(shù)并將參數(shù)轉(zhuǎn)換成 var mdName = req.params.md || "index"; if (!mdName.match(/\.md$/i)) { mdName += ".md"; } // 根據(jù)當(dāng)前目錄和相對目錄找到參數(shù)對應(yīng)的md文件 var filename = path.resolve(path.join(__dirname, "../md", mdName)); // render函數(shù)定義符合readFile和callback標(biāo)準(zhǔn) // 如果md文件讀取錯誤或者沒有內(nèi)容,向瀏覽器返回404 // 有內(nèi)容則調(diào)用md.ejs渲染HTML頁面 var render = function (err, md) { if (err || !md) { res.status(404).send("Error"); return; } var html = markdown.toHTML(md); res.render("md", { title: "Markdown Content", content: html }); }; // 從md文件讀取內(nèi)容,并將讀到的內(nèi)容交能render函數(shù)處理 fs.readFile(filename, { encoding: "utf8" }, render); };
完工,使用node app.js啟動服務(wù),再在瀏覽器中訪問,一切正常,只是——頁面太丑了,因為沒加樣式。修改public/stylesheets/style.less,加入樣式
body { margin: 24px; font: 14px "微軟雅黑", "Lucida Grande", Helvetica, Arial, sans-serif; } .h { font-weight: normal; } h2 { .h(); font-size: 32px; } h3 { .h(); font-size: 24px; } h4 { .h(); font-size: 18px; } .quote { background-color: #e8e8e8; border-left: 5px solid #cacaca; padding: 3px 0 3px 24px; border-radius: 3px; margin: 0; p { margin: 1px 0; } } code { .quote(); font-family: Consolas, Monaco, "Lucida Console", monospace; padding: 0 5px; margin-left: 2px; margin-right: 2px; border: 1px solid #cacaca; } pre { .quote(); border-left-width: 32px; padding-left: 12px; code { border: 0; padding: 0; margin: 0; } } blockquote { .quote(); code { background-color: #f8f8f8; } } a { color: #666; text-decoration: underline; &:visited { color: #999; } &:hover { color: #000; } } ul, ol { margin: 0; padding: 0; li { margin-left: 1.2em; padding: 0; } } ul li { list-style-type: square; } hr { height: 1px; border: 0; background-color: #999; }
這回才是真正的完工了,看看效果:
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。