關於
《Nodejs開發加密貨幣》,是一個加密貨幣產品的詳細開發文檔,涉及到使用Nodejs開發產品的方方面面,從前端到後臺、從服務器到客戶端、從PC到移動、加密解密等各個環節。代碼完全開源、文章免費分享。 相關資源見 http://ebookchain.org
QQ交流羣: 185046161
前言
從本文開始,我們正式進入Nodejs的世界。
本文,將指引您搭建Nodejs開發環境,向您介紹Nodejs的安裝、使用,幫您快速進入Nodejs的世界。
通過本文,讓您對前端開發有一個完整、全新的認知,可以學習到如何將一些第三方平臺的資源爲己所用,比如像巴比特一樣即時顯示交易市場的交易行情。
本文的實例,就是上篇文章提到的加密貨幣開發語言統計分析項目(Statistical Analysis of Cryptocurrency Development Languages,簡稱Sacdl
),點擊這裏,在線體驗。
項目需求
Sacdl
項目需要具備以下幾個功能:
- 方便地讀取第三方網站(這裏是github)的Api,實現項目搜索功能;
- 對讀取的數據集中處理,方便地轉化爲我們需要的信息;
- 通過柱狀圖、矩陣圖、表格等圖表格式,將數據可視化;
- 方便擴展,爲以後添加更多圖表樣式或其他網站Api(比如交易市場的)做好準備。
技術選型
無處不選擇。大方向要選擇,具體到每個開發包都要去甄別,安全嗎?好用嗎?性能高嗎?是否有更好的方案?等等。
僅從上述需求來說,一個html文件,再加一個js文件就基本搞定,第三方包都用不着,Nodejs
更是大才小用。
但事實上,很多僅僅是前端的項目,比如:Bootstrap等,都基於Nodejs
,爲什麼?答案很簡單,它供了諸多方便實用的工具。
比如說:
- 組織方便:js沒有模塊化組織代碼的能力。一個項目,js代碼通常會分割在不同的文件中,以往的方式,處理起來非常頭疼,現在利用
Nodejs
的模塊管理,可以讓您徹底解脫; - 資源廣泛:
Nodejs
的出現,讓js第三方包像雨後春筍一樣遍地開花。需要什麼,一條命令,Nodejs
就幫您辦了,這會帶來極大便利; - 全棧處理:開發完,還有很多事情要做,比如:要對前端代碼js或css文件進行合併、壓縮、混淆,以及項目部署等。體驗過ruby on rails一鍵部署功能的小夥伴,都會印象深刻。
Nodejs
也很容易做到,而且更加自然、流暢。
總之,有了Nodejs
,我們可以像開發後臺程序一樣組織前端代碼和項目了;有了Nodejs
,就有了它背後強大的技術社區支持。
Nodejs簡介
有小盆友說,第一次看到Nodejs
,還以爲就是一個js文件呢。呵呵,其實,很多前端的應用,比如大家吵得最歡的前端開發框架三劍客
,Angular.js, Backone.js, .Ember.js等,其實就是一個js文件。那麼,
Nodejs
是什麼呢?
官方解釋是這樣的:
Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient.
翻譯如下:
Node.js® 是一個搭建在Chrome V8上的JavaScript即時運行平臺,採用事件驅動、非阻塞I/O模型,既輕量又高效。
用句大白話解釋就是,Nodejs是一個可以讓您利用JavaScript語言開發應用的平臺, 是構建運行在分佈式設備上的數據密集型實時程序的完美選擇。
請注意哦,這裏可沒說是Web應用
,很多人認爲Nodejs僅能開發以服務器爲中心的web應用,其實不然,PC端、移動端都可以。當然,我們看到的大部分是Web應用,它是php+apache, jsp+tomcat, ruby on rails + Passenger(或thin) + nginx 等傳統web開發的絕佳替代品。
如果你還沒有直觀感受,那麼,我告訴你一個信息,Nodejs
的作者原本是想開發一種取代apache、nginx、tomcat等產品的傳統服務器軟件的,結果發展成了今天Nodejs
的模樣,你用Nodejs
寫的每一個應用,即可以認爲是一個服務器軟件,也可以認爲是一個web應用,而且它是如此簡單、高效。
什麼是數據密集型、實時應用?
聊天室、即時通信等都是。當然,所有的交易市場(比特幣、股票、基金等),電子商務網站的即時交易等也是。甚至物聯網,比如電器設備的監控和遠程控制。本人剛完成的一個項目,是一家大型連鎖超市的電器設備綜合監控系統,就是使用Nodejs開發的。
開發步驟
下面的過程會有點羅嗦,耐心點,很簡單。
1.搭建環境
對於初學者,建議先去[Nodejs官方網站][]瀏覽一遍。這裏有幣友推薦的一箇中文網站,runoob.com,對於英文不太好的用戶,有一定幫助。
我個人的開發環境是這樣的:
操作系統是
Ubuntu
系統:您可以在現有系統上,使用虛擬機軟件安裝它。我們的全部示例和截圖都是在ubuntu上完成;IDE工具:
Sublime Text
;
(1)Nodejs的安裝
強烈建議參考官網信息([Nodejs官方網站][],見參考資料)
我在Ubuntu上通過nvm
安裝管理Nodejs
,具體方法,這裏有一篇詳細文檔,快速搭建 Node.js 開發環境以及加速 npm,請務必閱讀一遍。這裏摘錄其中關鍵命令(下面的命令都要在Ubuntu的命令行程序下運行):
安裝Nvm
$ curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.29.0/install.sh | bash
用Nvm安裝Nodejs
$ nvm install 5.1.0
$ nvm alias default 5.1.0
說明:5.1.0 是Nodejs版本信息,寫作本文時,最新穩定版是5.4.0,長期支持版是4.2.4
安裝使用CNpm
使用淘寶npm鏡像,可以提高我們的組件下載數度
$ npm install -g cnpm --registry=https://registry.npm.taobao.org
查看版本信息
$ nvm -v
$ node -v
$ npm -v
我的版本信息如下:
nvm 0.29.0
node v5.1.0
npm v3.3.12
2.新建工程
在您電腦上,新建一個文件夾sacdl-project
,作爲工程目錄,路徑如下:
/home/yourname/projects/sacdl-project
我們通常會把前端代碼放在public
目錄下,然後分別建立js
,css
,images
等目錄,最後建立文件index.html
,js/app.js
,用於顯示頁面和寫我們的js代碼,結構如下:
上述結構中,
`js/searcher.js`是搜索框處理代碼,
`js/utils.js`是數據處理代碼,
`js/bar.js`文件是d3.js的柱狀圖代碼,
`js/treemap.js`是樹狀矩陣圖的代碼,
'js/app.js'用戶綜合調用,類似於控制器或路由。
前端第三方組件,比如d3.js等都存放在bower_components
,由bower
自動生成; 後臺第三方模塊在node_modules
,由npm
自動生成。
3.前端組件
在命令行,進入上述工程目錄,安裝前端管理工具bower
cnpm install -g bower # 也可以使用 npm install * 命令,二者一樣,只不過cnpm使用淘寶鏡像,在中國安裝會快些
說明:bower
是一個npm包,是專門用來管理web前端(包含js,css,images,fonts等)依賴包的。我們可以簡單類比,bower用於管理前端包,npm管理後臺庫(包),二者用法十分相似。
初始化
bower init
結果如下:
這樣會生成一個bower.json
文件,這樣我們的代碼就被作爲一個完整的前端組件來管理了。
通過bower
,安裝d3.js
bower install d3 --save
選項--save
將在bower.json
文件裏,寫入下面的信息:
"dependencies": {
...
"d3": "~3.5.12",
...
}
這樣,在另一臺電腦開發時,克隆完代碼,就可以直接運行下面的命令,自動安裝全部依賴的第三方組件了
bower intall
說明:d3.js
是提供了前端顯示的柱狀圖、餅狀圖等,是數據可視化非常出名的前端開發包。國人的有百度的echarts,還有一個highcharts,這三者經常被拿來比較。簡單的區分,就是,d3.js像開發包,可以任由您編程開發,但據說入門較難;其他兩個更像是模板,拿來就用。
這裏,我選擇了d3.js
,純屬個人喜好,一方面,我個人喜歡完全控制代碼;另一方面,在開發電子書版權保護和交易系統,用到了它。
4.前端流程
按照上面的需求,我們的流程大致是這樣的:
1.接受請求:提供一個輸入框,接受用戶輸入,獲得查詢關鍵字,並轉化爲github.com的Api請求地址;
2.獲得數據:根據上述地址,通過ajax請求數據(這裏是d3.js的d3.json()方法),對數據進行處理;
3.展示數據:使用d3.js編寫圖表樣式,將上述數據展示出來。
5.學習Api
第一步非常簡單,只要提供一個輸入框就是了。我們直接從第二步開始研究吧。
github是用ruby on rails開發的,它的api具有典型的ror的restful風格。下面是,官方搜索示例
請求下面的地址
https://api.github.com/search/repositories?q=tetris+language:assembly&sort=stars&order=desc
可以得到對應的json格式的數據。 官方是使用的curl
命令行工具,我們直接使用瀏覽器即可,有圖爲證:
這就是我們得到的原始數據結構。大部分情況下,需要重新整理,不然就不用費勁開發了。這裏,我們先把它轉化爲樹形矩陣圖需要的數據格式,如下:
{
"name": "languages",
"children": [{
"name": "javascript",
"children": [{
"name": "imfly/myIDE",
"watchers_count": 100,
"forks_count": 50
}]
}]
}
這裏的意思是,整個數據根節點就是languages
(自己建就是了), 它以各個語言爲子節點;各語言節點,則以它們的版本庫爲節點,這裏才存儲着我們需要的基本信息。
6.數據整理
我們在public/js
文件夾下,新建utils.js
(名字隨便起),然後使用文本編輯器打開,我使用的是Sublime text
.
(1)模塊化前端代碼
爲了實現模塊化編程,採取下面的格式組織前端代碼(當然,這並不是Nodejs的模塊形式,不過異曲同工),
var Utils = (function(){
//局部變量定義
var a = 0;
//公共方法
return {
settings: function(){},
init: function(){},
...
}
//私有方法
function name(){}
}())
在引入該文件的index.html
文件裏,就可以這樣調用
Utils.init();
而無法這樣調用
Utils.name();
(2)轉換數據格式
如何將api讀取的數據整理成我們想要的格式呢?代碼如下:
// 一定會有一個地方傳入dataset,先彆着急
function getTreeData(dataSet) {
var languages = {};
//新建根節點
var result = {
"name": "languages",
"children": []
}
//循環處理子節點
if (dataSet && dataSet.items) {
var items = dataSet.items;
//先找出涉及到語言
items.forEach(function(item, index) {
if (typeof languages[item.language] === "undefined") {
languages[item.language] = index;
};
})
//根據語言進行整理
for (var language in languages) {
//原來有些版本庫,是沒有語言信息。github的語言識別並不是完美的
if (language === "null") {
language = "others";
};
//每種語言的子節點
var root = {
"name": language,
"children": []
};
//從全局數據中再次查找我們的數據
items.forEach(function(item, index) {
var child = {
"name": item.full_name,
"watchers_count": item.watchers_count,
"forks_count": item.forks_count
};
if (item.language === language || (item.language === "null" && language === "others")) {
root.children.push(child);
};
})
result.children.push(root);
}
}
//返回結果
return result;
}
顯然,這是一個私有方法。因爲類似這樣對數據的整理,每一個圖表都要做。我們是把上面的方法作爲第一步處理,然後把結果緩存,其他格式的數據都以它爲基礎獲得(公共方法)。請參考源碼js/utils.js
,·點這裏。
7.D3.js渲染
數據有了,終於有機會弄成我們想要的樣式了。
(1)瞭解d3.js流程
有人說,對於初學者,d3.js的入門有點困難。如果您嘗試了之後,真覺得難,可以選擇echarts,或xcharts(來自於d3.js,下面有鏈接),方法相同。
d3.js的基本流程是:
- 在html中,提供展示圖表的位置,通常是給一個div#Id;
- 請求並填充數據;
- 渲染圖表,用append()新增元素,用remove()刪除多餘元素;
我們用最簡單的例子,演示一下(代碼在工程源碼的test文件夾下):
在test.html
頁面添加一個div元素,如下:
<div id="testId"></div>
新建test.js文件,寫下如下代碼:
//這是要渲染的數據,可以動態獲得
var dataset = [1, 2, 3, 4];
//填充數據,通常要使用d3.layout提供的數據模板進行處理,然後用data()方法去填
var chart = d3.select('#testId')
.selectAll('p')
.data(dataset, function(d) { return d; });
//渲染視圖,主要是下面2個方法
//data()之後纔可以調用的enter()方法,意思是有數據填充的那部分圖表元素,通常去增加`append`元素
chart
.enter()
.append('p')
.text(function(d, i) {
return [d, i];
})
//data()之後纔可以調用的exit()方法,意思是無法獲得數據填充的那部分圖表元素,通常要刪除`remove`
chart.exit().remove();
比如上面,我們默認提供了dataset的4個數值,第一次渲染,會正常顯示4個元素;接着,數據dataset換成[5,6],再此渲染,enter()方法將獲得原來渲染[1,2]的元素,並將其值換成[5,6],而[3,4]位置的元素因爲沒有了數據,被刪除掉。這樣就實現了圖表動態轉換。
注意:上面提到的d3.layout
可能是一個顛覆三觀的概念。layout
作爲層的概念,通常在html視圖中用作全局共享的模板文件,比如:layout.html, layout.ejs等。但是,這裏d3.js是用在數據上的,提供了d3.layout.treemap()
等方法,用於對各種圖表數據進行計算和處理,即:數據模板
。d3.js的視圖處理,就是使用append()和remove()去增加或刪除元素來處理,配合諸如.style()
元素樣式格式化的方法,實現頁面控制。顯然,這樣做的意義就是真正的數據驅動
。
(2)渲染我們的數據
d3.js提供了d3.json(),d3.csv()等請求數據的方法,我們上述數據是json格式,自然就用前者了
我們以矩陣圖爲例(我也是參考官方的示例,見參考資源),在index.html加入如下元素
<div id="sacdlTreemap"></div>
然後,編寫js/treemap.js
代碼,用於渲染圖表。
最後,在js/app.js
裏,加載數據:
----部分代碼------
d3.json(url, function(err, data) {
if (err) {
...
alert("加載數據失敗,請檢查您的網絡設置。")
};
Utils.getData(data);
Treemap.show();
...
});
----部分代碼------
具體請看源碼。
(3)查看效果
前端不用服務器,因此直接右鍵,選擇在瀏覽器中打開就是了。看看效果如何。
8.代碼調試
如果達到預期效果,如何發現問題所在呢?前端調試和測試也是一門學問,內容所限,無法細說。告訴您本人常用的調試前端代碼的工具,就是火狐瀏覽器的firebug
擴展插件。當然,對於本應用,用火狐或谷歌瀏覽器默認的控制檯就可以了。
具體用法是,在打開的瀏覽器頁面,按下F12
,就會在頁面底部彈出控制檯窗口,如下:
錯誤信息,斷點信息等一目瞭然。
9.部署發佈
經過一番調試,代碼終於達到預期效果。爲了提高頁面加載速度,增強用戶體驗,需要對代碼進行合併、壓縮,如果要保護自己的勞動,不想被別人無償使用,還需要對代碼進行混淆,最好部署到專門的服務器空間上去。這些工作,可以實現一鍵操作。
Nodejs
圈子裏,有2個最爲流行的工具,一個是grunt
,出現的最早。另一個是gulp
,後來居上,號稱是爲了解決前者的問題而生的,目的就是爲了消滅前者。事實證明,gulp
確實很好用,簡單、高效。我們就用它。
(1)原理
gulp
用到的核心概念就是管道流,你可以理解成我們生活中的各種管道的概念,比如自來水管道。文件或數據就是水,gulp
各類插件就是過濾網等水處理器械。
設計一個任務,就是建設一條管道,涉及到5個方法,分別是:
1>構建管道並起個名字用`gulp.task()`,
2>管道入口方法叫`gulp.src()`(src代表源文件),
每一節管道叫`.pipe()`(要用在入口和出口中間,在其中放入各種插件方法,就相當於加了層過濾網),
3>一直流向管道出口,方法叫`gulp.dest()`(dest英文意思是目標),
4>監控水流變化(文件變化)用`gulp.watch`,
5>綜合調度各個管道的運行,用`gulp.run`
最後在命令行啓動管道,就用gulp
或gulp taskname
命令
如圖,看看下面的幾條管道,是不是很容易理解:
注:pipe管道,是linux或Nodejs
等對於文件處理的一個重要概念,我們會在以後的文章中進一步說明。
(2)安裝
首先,
cnpm install gulp --global
這裏使用--global
進行全局安裝,這樣我們纔可以在任何路徑下使用gulp
命令。
然後,
cnpm install gulp --save-dev
這裏安裝在工程目錄下,目的是方便管理。同時,因爲gulp
僅僅是開發輔助工具,只在本地開發機器上使用,因此上述命令添加--save-dev
選項,把gulp
模塊安裝在開發依賴裏。
(3)建管道
gulp
命令默認請求gulpfile.js
文件,手動建一個吧,上面說各類管道(任務)都在這個文件裏,本工程對js進行處理的代碼如下:
----其他代碼-----
// 開建管道,名字叫`js`
gulp.task('js', ['clean'], function() {
// 合併、壓縮、混淆,並拷貝js文件
return es.merge( //這是個workflow插件,是Nodejs模塊,都是Nodejs應用,當然也可以使用了
gulp.src(assets.js.vendor) //管道1入口
.pipe(gulp.dest(settings.destFolder + '/js/')), // 直接流到管道1出口,相當於簡單拷貝
gulp.src(assets.js.paths) //管道2入口
.pipe(order(assets.js.order)) //過濾網1:排序
.pipe(sourcemaps.init()) //過濾網2:建sourcemaps
.pipe(uglify()) //這算是管道中的管道了,過濾網3:混淆處理
.pipe(concat(settings.prefix.destfile + '.js')) //過濾網4:合併處理
.pipe(sourcemaps.write()) //建maps結束,輸出sourcemaps
.pipe(gulp.dest(settings.destFolder + '/js')) //管道2出口
)
.pipe(concat(settings.prefix.mergefile + '.js')) //彙總管道:對上述2個管道的輸出再合併
.pipe(gulp.dest(settings.destFolder + '/js/')) //彙總管道出口
});
----其他代碼-----
詳情請看源碼。
在命令行,輸入如下命令,運行該任務
gulp js
(4)插件
上述代碼中用到的order
,sourcemaps
,uglify
等對應3個gulp
插件,可以從官網找到,本工程涉及到的,算是幾個最常用的插件,如下:
"gulp-concat": "^2.6.0", //合併js,css等
"gulp-cssnano": "^2.1.0", //css壓縮,取代了gulp-minify-css
"gulp-gh-pages": "^0.5.4", //部署到github的`gh-pages`,本工程在線演示就是這麼部署的
"gulp-imagemin": "^2.4.0", //圖片壓縮
"gulp-order": "^1.1.1", //js,css等順序合併等
"gulp-processhtml": "^1.1.0", //將處理完的代碼,替換到.html、.ejs等模板文件裏
"gulp-sourcemaps": "^1.6.0", //產生sourcemaps文件
"gulp-uglify": "^1.5.1", //混淆和壓縮js文件
(5)部署
上面的插件列表裏,有一個gulp-gh-pages
插件,可以幫我們部署到gh-pages
var ghPages = require('gulp-gh-pages');
//Deploy
gulp.task('deploy', function() {
return gulp.src('./dist/**/*')
.pipe(ghPages());
});
運行如下命令,即可
gulp deploy
當然,最好在運行部署命令之前,先運行合併、壓縮等處理命令,如果想省事,就定義在上述部署任務裏。請參考源碼。
總結
寫完這一章,好累。回頭看看,發現上面的每一個小節,其實都可以用一章來說明。缺乏細節,會讓讀者,特別是新手,很辛苦。相反,太注重細節,又會讓我們失去主題。所以,這也是一個很難取捨的過程,歡迎您提供寶貴意見或建議。
這裏提供了完整的程序源碼。源碼提供的功能比文章描述的多,比如對輸入框的處理、事件的監聽、多數據格式的處理,還包括bootstrap
的使用等。但文章僅摘錄了部分核心內容,在閱讀的時候,要注意結合源碼,實在不明白就參考下面提供的資源,或給我留言。
現在,您應該可以自己動手試試,應該能夠輕鬆的把比特時代、okcoin等交易市場的交易行情,即時的顯示在自己的網站上了。如果,掌握些比特幣核心代碼,它也提供了很多Api,能不能像本文這樣直接讀取呢?如果可以的話,豈不是很容易就能開發一個blockchain.info
?
具體分析,請看下一篇:《Nodejs開發加密貨幣》之三:Nodejs讓後臺開發像前端一樣簡單,簡單介紹Nodejs
後臺開發實踐,寫Nodejs
模塊,爲以後的代碼分析打好基礎。
鏈接
項目源碼: https://github.com/imfly/sacdl-project
試用地址:https://imfly.github.io/sacdl-project
本文源地址: https://github.com/imfly/bitcoin-on-nodejs
電子書閱讀: http://bitcoin-on-nodejs.ebookchain.org/
參考
(1)參考用例
d3.layout.treemap: http://mbostock.github.io/d3/talk/20111018/treemap.html
Grouped horizontal bar chart: http://bl.ocks.org/erikvullings/51cc5332439939f1f292
(2)官方網站
Nodejs官方網站: https://nodejs.org/
Bower官方網站: http://bower.io/
d3.js官方網站: https://d3js.org
(3)其他文檔