ix - 碁峰資訊epaper.gotop.com.tw/pdfsample/a491.pdf · 本書出版時,node 的current...
TRANSCRIPT
![Page 1: ix - 碁峰資訊epaper.gotop.com.tw/PDFSample/A491.pdf · 本書出版時,Node 的Current 版本是Node.js 6.0.0,並取消以Stable 表示開發中的分支。 Node.js 6.0.x](https://reader030.vdocuments.us/reader030/viewer/2022013002/5ece5bbe73171a196779bcca/html5/thumbnails/1.jpg)
前言 | ix
前言
Node.js已經夠成熟而被一些業界大戶採用(LinkedIn、Yahoo!與 Netflix),但對一般
企業的中階經理人來說卻還有不夠成熟的疑慮,這是推動建構更完整的 JavaScript的動
力,要使這個最新改進的腳本語言可以安心的使用。由於轉變是正確的,新 JavaScript
現在已經成為重新安排 Node.js組織與釋出的推手。
Node.js也重新定義了我們運用 JavaScript的方式,如今的資方可能對伺服器端與瀏覽
器端的 JavaScript開發者有同樣的需求。此外,Node.js建構的伺服器端語言已經引起
了 Ruby、C++、Java與 PHP等伺服器端開發者的注意—特別是已經熟悉 JavaScript的
一群。
對我來說,Node.js很有趣。相較於其他環境,它啟用、建構,與運行應用程式所需的付
出較少。Node專案的需求不像其他環境一樣的複雜,只有 PHP有著一樣簡單的環境,
但它必須與 Apache整合以建構對外服務的應用程式。
雖然如此的簡單,Node.js還是有一點難以深入。學習 Node.js確實是需要深入認識它的
環境與核心 API,但還與找出與掌握這些難以深入的部分有關。
本書對象
我認為本書的讀者有兩類。
第一類讀者是曾經使用過各種函式庫與架構的前端應用程式開發者,想要在伺服器上發
揮 JavaScript技能。
![Page 2: ix - 碁峰資訊epaper.gotop.com.tw/PDFSample/A491.pdf · 本書出版時,Node 的Current 版本是Node.js 6.0.0,並取消以Stable 表示開發中的分支。 Node.js 6.0.x](https://reader030.vdocuments.us/reader030/viewer/2022013002/5ece5bbe73171a196779bcca/html5/thumbnails/2.jpg)
x | 前言
第二類讀者是想要嘗試新技術的伺服器端開發者。他們使用過 Java、C++、Ruby、或
PHP,但現在想要結合過去曾經使用過的 JavaScript與伺服器端知識。
這兩類看似不同的讀者有相同的知識:JavaScript,或更精確的說是 ECMAScript。這本
書要求你非常熟悉 JavaScript。這兩類讀者的另一個共通處是都需要學習相同的 Node基
礎,包括核心 API。
然而,每個讀者對學習體驗有不同的看法與技能。為強化實用性,我會在內容中兼具兩
種方向。舉例來說,C++或 Java開發者可能會對建構 C++的 Node附加元件感興趣,
而前端開發者並不有興趣。同時間,伺服器端開發者可能很熟悉 big-endian之類的概
念,但前端並不知道。我無法對每一種方面深入,但我會確保所有讀者不會看不懂或覺
得無聊。
我不會強迫你機械化的記憶。我們會探索核心模組 API,但不會討論每一個物件與函
式,因為 Node官網(https://nodejs.org/en/)上有說明文件。相對的我會討論每個我認
為對你與其他 Node開發者很重要的核心模組或特定 Node函式的重要概念。當然,熟能
生巧,而這本書是個學習工具,讀過這本書之後你必須繼續進一步的探索特定形態的功
能,例如 Mongo-Express-Angular-Node(MEAN)架構。這本書會給你探索 Node各方
向開發所需的基礎。
Node文件
寫作此書時,我與其他 Node開發者正在討論 Node.js官網的議題,關於 "目前 "Node.js版
本的定義,也就是存取 "說明文件 "時應該有什麼內容。
在我參加討論時,計劃本是在 /docs網頁中列出所有 LTS版本的 Node.js以及最新的 Stable
版本並在每一頁文件頁上方提供 Node文件版本指示。
最終,文件團隊打算在每一頁產生 API的每一個版本的 diff,但這會是充滿挑戰的專案。
本書出版時,Node的 Current版本是 Node.js 6.0.0,並取消以 Stable表示開發中的分支。
Node.js 6.0.x最終會成為下一個 LTS版本。
由於有這些版本,存取 Node.js官網的 API文件時要注意版本符合你的 Node.js。檢查新版
有什麼新東西不會有什麼損失。
![Page 3: ix - 碁峰資訊epaper.gotop.com.tw/PDFSample/A491.pdf · 本書出版時,Node 的Current 版本是Node.js 6.0.0,並取消以Stable 表示開發中的分支。 Node.js 6.0.x](https://reader030.vdocuments.us/reader030/viewer/2022013002/5ece5bbe73171a196779bcca/html5/thumbnails/3.jpg)
前言 | xi
請持續關注本書網站(詳見後述),以了解如何取得實用教材,包括講課用的投影片、作
業題與問題範例、以書中架構為基礎的範例專案說明,還有考題⋯等等。
Node.js 就是 Node
正規的名稱是 Node.js,但沒有人這麼稱呼它,大家都叫它 "Node"。就是
這樣,我們在本書中大多也是這麼叫它。
本書章節的編排
Node 學習手冊是基礎書籍,專注於 Node與組成 Node核心的模組。我有稍微提及第
三方模組並深入討論 npm,但本書主要目標是讓讀者快速上手 Node的功能。打好基礎
後,你可以向其他方面發展。
第 1章介紹 Node,包括如何安裝的簡短說明。你會有機會嘗試跑一下 Node,首先是
建構 Node文件所列出的網頁伺服器,然後使用我提供的程式建構較先進的伺服器。此
外,我還會為 C/C++程式設計師提及建構 Node的附加元件,還有介紹 Node時必備的
歷史概述,討論第一個版本並非 1.0而是 4.0的由來。
第 2章討論 Node的基本功能,包括事件如何處理、建構 Node應用程式必要的全域物
件,與 Node的非同步本質。此外,我還討論了 buffer物件,它是大部分 Node網路服務
所傳輸的資料結構。
第 3章討論 Node的模組系統以及 npm這個第三方模組管理系統。你會在這一章看到應
用程式如何找到 Node模組與如何自行建構 Node模組。最後我會討論更高等的 Node功
能,探索沙盒的支援。為了好玩,我還討論了三個常見的 Node第三方模組:Async、
Commander與 Underscore。
Node的互動控制台稱為 REPL,它是個很好的學習工具與環境,第 4章專門討論它。我
會詳細說明如何使用它以及如何建構自訂的 REPL。
我們在第 5章討論網路 Node應用程式的開發,包括進一步深入的檢視 Node的網路開發
模組。你會看到靜態網頁伺服器的建構以及學習如何在 Apache上透過 proxy執行 Node
應用程式。
![Page 4: ix - 碁峰資訊epaper.gotop.com.tw/PDFSample/A491.pdf · 本書出版時,Node 的Current 版本是Node.js 6.0.0,並取消以Stable 表示開發中的分支。 Node.js 6.0.x](https://reader030.vdocuments.us/reader030/viewer/2022013002/5ece5bbe73171a196779bcca/html5/thumbnails/4.jpg)
xii | 前言
Node可在多種環境執行,包括 Windows與以 Unix為基礎的 OS X以及 Linux等。它透
過一組功能消除系統間的差異,第 6章會討論這些功能。此外,我還會討論 Node的串
流與管道—輸出入的基本元素—以及 Node的檔案系統支援。
第 7章是關於網路,而處理網路時不能忘了安全性,這兩者應該一起進行,如同涼麵
與味噌湯,或辣椒醬與所有食物。我會介紹 Node 的 TCP 與 UDP 支援以及如何實作
HTTPS伺服器。我還會討論數位憑證的機制與 Secure Sockets Layer(SSL)以及其加強
版的 Transport Layer Security(TLS)。最後我們會討論 Node的加密模組並進行密碼加
密。
我最喜歡 Node的一點是它能夠透過子行程操作作業系統功能。有些 Node工具應用程式
可以操作壓縮檔案、利用 ImageMagick這個圖形應用程式、以及建構從網站擷取畫面的
應用程式。它們沒有複雜的介面,但可以用來學習子行程。子行程的討論在第 8章。
本書大部分範例使用 JavaScript,然而 Node.js/io.js分流的主要因素之一是 ES6(或稱為
ECMAScript 2015)等新版 ECMAScript的支援。第 9章討論 Node目前具有的支援、新
功能的影響,與使用新功能的時機。我還會討論使用新版 JavaScript功能相關的陷阱,
唯一未專注在原生功能的討論部分在於 Bluebird這個模組的使用。
第 10章檢視所謂全端 Node 開發的架構與功能。我們會檢視 Express這個 Node開發元
件以及嘗試 MongoDB與 Redis。我們還會探索幾個組成 Node全端開發中 "全端 "的架
構:AngularJs與 Backbone.js。
一旦開始撰寫 Node應用程式,你會想要將它上線。第 11章討論關於 Node開發與上線
的工具與技術,包括單元、負載,與基準測試,以及基本除錯技巧與工具。你還會學到
如何持續執行你的 Node應用程式並於發生問題時復原。
第 12章是甜點,這一章介紹將你的 Node技能帶到新環境的方式,包括微控制器 /微電
腦、物聯網、以及不在 V8上執行的 Node。
![Page 5: ix - 碁峰資訊epaper.gotop.com.tw/PDFSample/A491.pdf · 本書出版時,Node 的Current 版本是Node.js 6.0.0,並取消以Stable 表示開發中的分支。 Node.js 6.0.x](https://reader030.vdocuments.us/reader030/viewer/2022013002/5ece5bbe73171a196779bcca/html5/thumbnails/5.jpg)
| 1
第一章
Node環境
忘掉你曾經聽說過 Node只是伺服器端的工具。沒錯,Node主要用於伺服器應用程式,
但 Node幾乎可以安裝在任何機器上並用於任何目的,包括在你的 PC、平板、手機,或
微電腦上執行應用程式。
我將 Node 安裝在 Linux 伺服器上,但我還將它安裝在 Windows 10 的 PC 以及微電
腦(Raspberry Pi)上。我考慮安裝 Node 在一台 Android 平板上,使用 Node 來控制
Arduino Uno微電腦,透過 IFTTT的 Marker Channel操作智慧家庭。在 PC上,我使用
Node作為 JavaScript的測試環境以及 ImageMagick批次照片編修的介面。Node是我在
PC或伺服器上的批次操作工具。
當我需要 Apache伺服器的網頁介面或網頁應用程式的後台伺服器處理時,我使用 Node
進行伺服器端的程序。
重點是 Node環境有豐富的功能與支援。為了探索此環境,我們必須從頭開始:安裝
Node。
IFTTT
IFTTT網站可讓你使用簡單的 if-then邏輯連接公司主機、服務,與產品
的觸發機制與動作。控制式的每個端點都是個通道,包括前述的 Maker
Channel(https://ifttt.com/maker)。
![Page 6: ix - 碁峰資訊epaper.gotop.com.tw/PDFSample/A491.pdf · 本書出版時,Node 的Current 版本是Node.js 6.0.0,並取消以Stable 表示開發中的分支。 Node.js 6.0.x](https://reader030.vdocuments.us/reader030/viewer/2022013002/5ece5bbe73171a196779bcca/html5/thumbnails/6.jpg)
2 | 第一章:Node 環境
安裝 Node安裝 Node的最佳來源是 Node.js的 Downloads網頁(https://nodejs.org/en/download/),
你可以從這裡下載 Windows、OS X、SunOS、Liunx,與 ARM 架構的二進位檔案
(編譯好的可執行檔)。此網頁還提供特定架構的安裝程序,可大幅簡化安裝程序—特
別是 Windows。如果要安裝的是建構環境,可下載原始碼並直接建構 Node,這是我在
Ubuntu伺服器上的做法。
你也可以使用你的架構的套件安裝程序來安裝 Node。這不只是安裝 Node的一個選項,
也能持續更新版本(見 "Node的 LTS與升級 "一節)。
如果決定在你的機器上直接編譯 Node,你會需要設置適當的建構環境並安裝工具。舉例
來說,在 Ubuntu上,你會需要執行下列命令以安裝 Node所需的工具:
apt-get install make g++ libssl-dev git
在不同架構上首次安裝 Node會有一些不同的行為。舉例來說,在Windows上安裝 Node
時,安裝程序不只會安裝 Node,還會在你的電腦上建構存取用的 Command視窗。Node
是命令列應用程式,沒有一般 Windows程式的圖形 UI。如果想要在 Arduino Uno上使
用 Node,你必須安裝 Node 與 Johnny-Five(http://johnny-five.io/)並使用這兩者控制
裝置。
Windows上接受預設值
在 Windows上安裝 Node時你會想要接受預設安裝位置與功能。安裝程序
會將 Node加到 PATH變數中,這表示你可以輸入 node而不需提供完整的
安裝路徑。
如果要在 Raspberry Pi上安裝 Node,下載適合的 ARM版本,例如原始 Raspberry Pi的
ARMv6或 Raspberry Pi 2的 ARMv7。下載後,解開壓縮檔,然後將應用程式搬到 /usr/
local下:
wget https://nodejs.org/dist/v4.0.0/node-v4.0.0-linux-armv7l.tar.gztar -xvf node-v4.0.0-linux-armv7l.tar.gz
cd node-v4.0.0-linux-armv7l
sudo cp -R * /usr/local/
![Page 7: ix - 碁峰資訊epaper.gotop.com.tw/PDFSample/A491.pdf · 本書出版時,Node 的Current 版本是Node.js 6.0.0,並取消以Stable 表示開發中的分支。 Node.js 6.0.x](https://reader030.vdocuments.us/reader030/viewer/2022013002/5ece5bbe73171a196779bcca/html5/thumbnails/7.jpg)
以 Node 說 Hello World | 3
你也可以設置建構環境並直接建構 Node。
新的 Node環境
說到 Arduino與 Raspberry Pi上的 Node,我會在第 12章討論非傳統環境
中的 Node,例如物聯網。
以 Node說 Hello World安裝完 Node之後你自然會想要試跑一下。傳統上程式設計師在一個語言的第一個應用
程式是 "Hello, World",此程式通常輸出 "Hello, World"到輸出串流中,展示應用程式如
何建構、執行,與處理輸出入。
Node也是一樣:Node.js的官網在應用程式的概要文件中有包括此應用程式,這也是我
們在本書中建構的第一個應用程式,但會加上一點修改。
基本 Hello World應用程式
首先,讓我們看一下 Node 文件所附的 "Hello, World" 應用程式。為重新建構此應用
程式,使用文字編輯工具建構帶有下列 JavaScript的文字檔案。我在 Windows上使用
Notepad++,在 Linux上使用 Vim。
var http = require('http');
http.createServer(function (request, response) { response.writeHead(200, {'Content-Type': 'text/plain'}); response.end('Hello World\n');}).listen(8124);
console.log('Server running at http://127.0.0.1:8124/');
將檔案存為 hello.js。若使用 OS X 或 Linux 則開啟 terminal,或在 Windows 上則開啟
Node Command視窗來執行此應用程式。切換目錄到儲存檔案的位置並輸入下列命令來
執行程式:
node hello.js
![Page 8: ix - 碁峰資訊epaper.gotop.com.tw/PDFSample/A491.pdf · 本書出版時,Node 的Current 版本是Node.js 6.0.0,並取消以Stable 表示開發中的分支。 Node.js 6.0.x](https://reader030.vdocuments.us/reader030/viewer/2022013002/5ece5bbe73171a196779bcca/html5/thumbnails/8.jpg)
4 | 第一章:Node 環境
執行結果透過呼叫 console.log()輸出到命令列上:
Server running at http://127.0.0.1:8124/
打開瀏覽器並在網址列輸入 http://localhost:8124/或 http://127.0.0.1:8124(若 Node
在伺服器上則輸入網域)。網頁顯示 "Hello World",如圖 1-1所示。
圖 1-1:你的第一個 Node應用程式
如果是在Windows上執行你的應用程式,你可能會收到如圖 1-2所示的Windows Firewall
警告。取消 Public Network選項,核選 Private網路選項,然後點擊 Allow按鈕。
圖 1-2:允許存取 Node應用程式
![Page 9: ix - 碁峰資訊epaper.gotop.com.tw/PDFSample/A491.pdf · 本書出版時,Node 的Current 版本是Node.js 6.0.0,並取消以Stable 表示開發中的分支。 Node.js 6.0.x](https://reader030.vdocuments.us/reader030/viewer/2022013002/5ece5bbe73171a196779bcca/html5/thumbnails/9.jpg)
以 Node 說 Hello World | 5
無須在Windows中重複此操作:系統會記得你的選項。
要結束此程式,你可以關閉 terminal/Command視窗(直接從這裡關閉)或輸入 Ctrl-C。
執行此應用程式時,你是在前景操作,這表示你不能在 terminal中輸入其他命令。這也
表示關閉 terminal時會停止 Node行程。【5】
永續執行 Node
目前在前景執行 Node是個好事。你正在學習如何使用工具,還不需要對
所有人開放你的應用程式,且下班時會想要結束程式。第 11章會討論如
何建構更扎實的 Node執行環境。
回到 Hello World程式碼,JavaScript建構出一個在瀏覽器存取時顯示 "Hello World"網頁
的伺服器,這展示了幾個 Node應用程式的關鍵元件。
首先是它包括了執行簡單 HTTP伺服器所需的模組:命名為 HTTP的模組。Node的外部
功能是透過模組匯入可在應用程式(或其他模組)中使用的特定類型功能,它們類似其
他語言中的函式庫。
var http = require('http');
Node模組、核心模組,與 http模組
HTTP模組是 Node的核心模組之一,也是本書的重點。第 3章討論 Node
模組與模組管理,第 5章討論 HTTP模組。
模組以 require陳述匯入,其結果會指派給一個區域變數。匯入之後,區域變數可透過
http.createServer()函式初始化網頁伺服器。在函式的參數中,我們看到一個 Node的基
本結構:callback(範例 1-1)。它是傳遞網頁請求與回應給程式碼以處理網頁請求並提
供回應的不具名函式。
範例 1-1:Hello World的 callback函式
http.createServer(function (request, response) { response.writeHead(200, {'Content-Type': 'text/plain'}); response.end('Hello World\n');}).listen(8124);
![Page 10: ix - 碁峰資訊epaper.gotop.com.tw/PDFSample/A491.pdf · 本書出版時,Node 的Current 版本是Node.js 6.0.0,並取消以Stable 表示開發中的分支。 Node.js 6.0.x](https://reader030.vdocuments.us/reader030/viewer/2022013002/5ece5bbe73171a196779bcca/html5/thumbnails/10.jpg)
6 | 第一章:Node 環境
JavaScript是單執行緒的,而 Node在單執行緒環境中透過事件迴圈與特定事件發生時會
觸發的 callback函式來模擬非同步環境。在範例 1-1中,當收到網頁請求時,callback就
被呼叫。
console.log()訊息在呼叫建構伺服器時立即輸出到終端機上。此程式不會停止或阻斷,
等待著網頁請求。
console.log('Server running at http://127.0.0.1:8124/');
事件迴圈與 callback函式
第 2章會進一步討論支援非同步程式設計的 Node事件迴圈與 callback
函式。
一旦建構出伺服器並接收到請求,callback函式會輸出文字 header與伺服器狀態 200回
到瀏覽器、輸出 Hello World訊息、然後結束回應。
恭喜,你已經在 Node中以幾行程式建構出你的第一個網頁伺服器。當然,這沒什麼用
處,除非你只打算向世界問好。本書讓你學習如何製作更實用的 Node應用程式,但在
結束 Hello World之前,讓我們對此基本應用程式做一些修改以讓它更有趣。
修改 Hello World
只輸出靜態學習可以作為示範,首先是應用程式的運行,其次是如何建構簡單的網頁伺
服器。此基本範例也展示出幾個 Node應用程式的關鍵元件。但它還能夠更有趣,因此
我要加以修改以提供第二個你能嘗試的應用程式,它有多幾個動作。
範例 1-2 是修改過的程式,我修改基本應用程式以解析請求的 query string。字串的
名稱被擷取出並用於判斷回傳內容。幾乎所有名稱都會回傳個人化回應,但若使用
name=burningbird作為 query則會回傳圖像。如果沒有 query string或名稱,則名稱變數
會設成 'world'。
![Page 11: ix - 碁峰資訊epaper.gotop.com.tw/PDFSample/A491.pdf · 本書出版時,Node 的Current 版本是Node.js 6.0.0,並取消以Stable 表示開發中的分支。 Node.js 6.0.x](https://reader030.vdocuments.us/reader030/viewer/2022013002/5ece5bbe73171a196779bcca/html5/thumbnails/11.jpg)
以 Node 說 Hello World | 7
範例 1-2:修改過的 Hello World
var http = require('http');var fs = require('fs');
http.createServer(function (req, res) { var name = require('url').parse(req.url, true).query.name;
if (name === undefined) name = 'world';
if (name == 'burningbird') { var file = 'phoenix5a.png'; fs.stat(file, function (err, stat) { if (err) { console.error(err); res.writeHead(200, {'Content-Type': 'text/plain'}); res.end("Sorry, Burningbird isn't around right now \n"); } else { var img = fs.readFileSync(file); res.contentType = 'image/png'; res.contentLength = stat.size; res.end(img, 'binary'); } }); } else { res.writeHead(200, {'Content-Type': 'text/plain'}); res.end('Hello ' + name + '\n'); }}).listen(8124);
console.log('Server running at port 8124/');
以 ?name=burningbird作為此網頁應用程式的 query string的請求所產生的結果顯示於圖
1-3。
![Page 12: ix - 碁峰資訊epaper.gotop.com.tw/PDFSample/A491.pdf · 本書出版時,Node 的Current 版本是Node.js 6.0.0,並取消以Stable 表示開發中的分支。 Node.js 6.0.x](https://reader030.vdocuments.us/reader030/viewer/2022013002/5ece5bbe73171a196779bcca/html5/thumbnails/12.jpg)
8 | 第一章:Node 環境
圖 1-3:Hello,Burningbird
沒有太多額外的程式碼,但修改過的版本與基本的 Hello World應用程式有幾處不同。從
前面開始,應用程式引用了一個新模組,名稱為 fs,這是 File System模組,接下來幾章
會很常出現。但還有匯入另一個模組,然而與其他兩個的方式不同:
var name = require('url').parse(req.url, true).query.name;
匯出的模組屬性可以鏈接,因此我們可以在同一行匯入模組並使用它的函式。這經常發
生於 URL模組,它的目的只是提供 URL功能。
回應與請求參數變數名稱縮短成 res與 req以方便存取。解析請求以取得 name值後,我
們首先檢查它是否為 undefined。若不是,其值會設給 world。若 name不存在,會檢查是
否等於 burningbird,如果不是則回應與基本應用程式相同,但在回應訊息中插入所提供
的名稱。
![Page 13: ix - 碁峰資訊epaper.gotop.com.tw/PDFSample/A491.pdf · 本書出版時,Node 的Current 版本是Node.js 6.0.0,並取消以Stable 表示開發中的分支。 Node.js 6.0.x](https://reader030.vdocuments.us/reader030/viewer/2022013002/5ece5bbe73171a196779bcca/html5/thumbnails/13.jpg)
以 Node 說 Hello World | 9
如果名稱是 burningbird,則要處理的是圖形而非文字。fs.stat()方法不只檢驗檔案是否
存在,還會回傳檔案資訊物件,其中包括檔案大小,此值用於建構 header。
如果檔案不存在,應用程式會優雅的處理這種狀況:它發出友善的訊息表示檔案不存
在,同時使用 console.error()方法提供錯誤資訊給控制台:
{ [Error: ENOENT: no such file or directory, stat 'phoenix5a.png'] errno: -2, code: 'ENOENT', syscall: 'stat', path: 'phoenix5a.png' }
如果檔案存在,則讀取圖形到變數中並在回應中回傳,同時調整 header的對應值。
fs.stats()方法使用標準的 Node的 callback函式模式,以錯誤值作為第一個參數—通
常稱為 errback。然而,讀取圖形的部分可能會讓你傷腦筋。它看起來不對,不像這一章
(與其他線上範例)的其他 Node函式。不同處在於我使用了同步函式 readFileSync()而
不是非同步版的 readFile()。
Node的大部分 File System函式不同時支援同步與非同步版。一般來說,在 Node的網頁
請求中使用同步操作是個禁忌,但功能還是存在。範例 1-3使用非同步版本。
fs.readFile(file, function(err,data) { res.contentType = 'image/png'; res.contentLength = stat.size; res.end(data, 'binary'); });
為何使用不同版本?在某些情況下,不管使用哪一種函式,檔案 I/O可能不會影響效
能,且同步版比較清楚與容易使用。它也會產生較少套疊的程式—Node的 callback系統
的問題,第 2章會進一步的討論。
此外,雖然我在範例中沒有使用例外處理,但你可以對同步函式使用 try...catch。對非
同步函式無法使用這種比較傳統的錯誤處理(所以錯誤值是非同步 callback函式的第一
個參數)。
第二個範例的重點是並非所有的 Node的 I/O是非同步的。
![Page 14: ix - 碁峰資訊epaper.gotop.com.tw/PDFSample/A491.pdf · 本書出版時,Node 的Current 版本是Node.js 6.0.0,並取消以Stable 表示開發中的分支。 Node.js 6.0.x](https://reader030.vdocuments.us/reader030/viewer/2022013002/5ece5bbe73171a196779bcca/html5/thumbnails/14.jpg)
10 | 第一章:Node 環境
Filesystem與 URL模組、緩衝區、以及非同步 I/O
第 5 章會進一步討論 URL 模組,第 6 章討論 File System。注意 File
System貫穿本書。緩衝區與非同步處理在第 2章討論。
Node命令列選項
在前面兩節中,Node從命令列呼叫而沒有加上任何命令列選項。繼續之前我想要簡短的
介紹一下一些選項,其他選項會在有必要時加以說明。
要列出所有選項與參數時使用 help選項,寫成 -h或 --help:
$ node --help
此選項會列出所有選項並提供執行 Node應用程式時的語法:
Usage: node [options] [ -e script | script.js ] [arguments] node debug script.js [arguments]
要查詢 Node版本,使用下列命令:
$ node -v or --version
要檢查 Node應用程式的語法,使用 -c選項。它會檢查語法而不執行應用程式:
$ node -c or --check script.js
要檢視 V8選項,輸入下列命令:
$ node --v8-options
這會回傳幾個不同的選項,包括 --harmony選項,用於開啟所有 Harmony JavaScript功
能。這包括有實作但尚未進入 LTS或 Current版本的 ES6功能。
我最喜歡的 Node選項是 -p或 --print,它可以對一行 Node腳本求值並輸出結果。這在
檢查第 2章討論的環境變數時特別有用。以下是個範例,它輸出 process.env屬性的所
有值:
$ node -p "process.env"
![Page 15: ix - 碁峰資訊epaper.gotop.com.tw/PDFSample/A491.pdf · 本書出版時,Node 的Current 版本是Node.js 6.0.0,並取消以Stable 表示開發中的分支。 Node.js 6.0.x](https://reader030.vdocuments.us/reader030/viewer/2022013002/5ece5bbe73171a196779bcca/html5/thumbnails/15.jpg)
Node 運行環境 | 11
Node運行環境隨著 Node的學習,你會開始熟悉自己的環境,無論是 Windows、OS X、或 Linux。準
備好開放你的應用程式時,你需要可執行 Node應用程式的環境,像是我使用的 virtual
private network(VPN),或特別提供 Node應用程式支援的主機。前者需要有開放給網
際網路的伺服器經驗,而後者或許會限制 Node應用程式的功能。
在你的伺服器、VPS或服務廠商的主機上運行 Node
由於 Node的需求,在WordPress部落格伺服器上運行 Node可能是個死巷子。你無法取
得必要的 root或 admin權限來執行 Node。此外,許多廠商不希望運行可能會影響系統
的應用程式。
在 virtual private server(VPS)上運行 Node,例如我在 Linode上的 VPN,比較簡單。
你能取得你的 VPS的 root權限並執行任何所需的動作,只要不影響同一台機器上的其他
使用者。大部分 VPS廠商會確保個別帳戶與其他帳戶隔離,且沒有一個帳戶能佔用所有
資源。
然而 VPS的問題與自己架設的伺服器有相同的問題:你必須自行維護伺服器。這包括設
置郵件系統與網頁伺服器,可能是 Apache或 Nginx(https://www.nginx.com/),以處理
防火牆與其他安全設定等,這不是簡單的工程。
還有,就算你願意管理所有的網際網路環境,VPS還是不錯的 Node應用程式運行選
項,至少在準備開放前參考一下雲端上的運行服務。
雲端運行服務
現在的應用程式可能在雲端伺服器上運行如同在個人或公司的電腦一樣。Node應用程式
很適合雲端實作。
在雲端運行你的 Node應用程式時,你通常需要做的是在自己的伺服器或 PC上建構應用
程式、測試、確保符合需求、然後將應用程式上傳至雲端伺服器。Node的雲端伺服器能
讓你建構你想要的 Node應用程式、使用各種資料庫系統或其他系統資源,而不必直接
![Page 16: ix - 碁峰資訊epaper.gotop.com.tw/PDFSample/A491.pdf · 本書出版時,Node 的Current 版本是Node.js 6.0.0,並取消以Stable 表示開發中的分支。 Node.js 6.0.x](https://reader030.vdocuments.us/reader030/viewer/2022013002/5ece5bbe73171a196779bcca/html5/thumbnails/16.jpg)
12 | 第一章:Node 環境
管理伺服器。你可以專注於 Node應用程式而不用擔心 FTP或郵件伺服器,或一般的伺
服器管理。
Git與GitHub:Node開發需求
如果沒有使用過 Git原始碼管理系統,你必須將它安裝在你的環境中並學習如何使用。幾乎
所有 Node應用程式的發佈,包括發佈應用程式到雲端伺服器上,都是透過 Git。
Git開源、免費、且容易安裝。你可以在 Git網站(https://git-scm.com/)取得軟體。GitHub
有個互動指引(https://try.github.io/levels/1/challenges/1)可供你學習基本的 Git指令。
說到 Git通常就要提到 GitHub。Node.js原始碼是放在 GitHub上管理,大部分 Node模組也
是。本書的範例也可從 GitHub取得。
GitHub(https://github.com/)或許是世界上最大的開源程式庫,它是 Node 世界的中
心。它是個營利企業,但對大部分使用者提供免費服務。GitHub組織提供非常好的文件
(https://help.github.com/categories/bootcamp/) 說 明 如 何 使 用, 還 有 一 些 關 於 Git 與
GitHub 的書籍與訓練課程。除了 Git 的免費線上書籍(https://git-scm.com/book/en/v2),還 有 Loeliger 與 McCullough 的 Version Control with Git(O'Reilly), 以 及 Bell 與 Beer 的
Introducing GitHub(O'Reilly)。
在雲端運行 Node應用程式的模式在各個服務之間非常相似。首先在本機或自己的伺服
器上開發 Node應用程式,準備開始在部署環境測試時可尋找雲端伺服器。我所知道的
服務都是建立帳戶、建構新的專案、指定使用 Node環境就好。你或許需要指定其他所
需的資源,例如資料庫。
準備好部署時,你會將應用程式推上雲端,使用 Git或雲端服務廠商提供的工具來推
送。舉例來說,Microsoft的 Azure利用 Git從你的本機環境推送應用程式到雲端,而
Google的 Cloud Platform提供工具執行同樣的工作。
找尋運行服務
雖然沒有完全更新,但 GitHub 有個網頁(https://github.com/nodejs/
node-v0.x-archive/wiki/Node-Hosting)提供 Node運行服務資訊。
![Page 17: ix - 碁峰資訊epaper.gotop.com.tw/PDFSample/A491.pdf · 本書出版時,Node 的Current 版本是Node.js 6.0.0,並取消以Stable 表示開發中的分支。 Node.js 6.0.x](https://reader030.vdocuments.us/reader030/viewer/2022013002/5ece5bbe73171a196779bcca/html5/thumbnails/17.jpg)
Node 的 LTS 與升級 | 13
Node的 LTS與升級2014年時,一群 Node維護者分裂並組成 io.js的事件震驚了 Node圈子(至少有些人感
到驚訝)。分裂的原因是 io.js派認為 Joyent這家維護 Node的公司對 Node的開放不夠積
極,他們還覺得 Joyent對 V8引擎的支援落後。
幸好兩派解決了引發分裂的問題,重新合併成一個產品,還是稱為 Node.js。Node現在
透過 Linux Fundation贊助的非營利的 Node Foundation管理。結果兩派的程式合併,其
第一個官方釋出版本為 Node 4.0而非 Node 1.0:表示原始的 Node 1.0與 io.js的 3.0版。
Node的新版本編號
合併的一項結果是根據 Linux使用者所熟悉的 Semver(http://semver.org/)嚴格制定的
Node版本釋出時間表。Semver版本編號有三群數字,各具有特定的意義。舉例來說,
撰寫本書時,我使用 Node.js的 4.3.2版,它表示:
• 主要版本編號是 4。此數字只會在有重大,與舊版不相容的改變發送時遞增。
• 次要版本編號是 3。此數字在加入與舊版相容的新功能時遞增。
• 批次編號是 2。此數字在安全性或修改錯誤而需要新版本時改變,同樣具有向後
相容。
我目前在 Windows 機器上使用 Stable 版的 5.7.1,測試程式時使用 Linux 機器上的
Current版 6.0.0。
Node Foundation還支援更密集但有點問題的版本釋出週期,它從第一個 LTS(Long-
Term Support)的 Node.js v4這個支援到 2018年 4月的版本開始。然後 Node Foundation
在 2015年 10月釋出第一個 Stable的 Node.js v5。Node 5.x.x只會支援到 2016年 4月,
屆時會被 Node.js v6取代。其策略為每隔六個月釋出新的 Stable(現在稱為 Current),
但每隔兩次才有 LTS,如同 Node v4。
釋出 6.0.0作為 Current
2016年 4月 Node釋出 6.0.0取代 5.x,它會在 2016年 10月轉變為新的
LTS。Node還將代表目前開發中的 Stable重新命名成 Current。
![Page 18: ix - 碁峰資訊epaper.gotop.com.tw/PDFSample/A491.pdf · 本書出版時,Node 的Current 版本是Node.js 6.0.0,並取消以Stable 表示開發中的分支。 Node.js 6.0.x](https://reader030.vdocuments.us/reader030/viewer/2022013002/5ece5bbe73171a196779bcca/html5/thumbnails/18.jpg)
14 | 第一章:Node 環境
2018年 4月後,Node v4將進入維護模式,同時間會有新的向後相容更新(稱為 semver-
major bumps)以及錯誤與安全性修補。
本書涵蓋版本
本書涵蓋長期穩定的 Node.js v4版本,必要時會標註 v4與 v5/v6間的不
同處。
無論你決定使用哪個 LTS版本,每次有新的錯誤 /安全性修補釋出時都必須盡快更新,
但要如何處理新的 semver-major bump則自行決定。這種升級應該是向後相容的,只會
影響底層引擎。無論如何,任何新版都應該放在升級與測試計劃中。
應該使用哪一個版本?在商業或公司環境中,最好使用 LTS版本,也就是 Node.js v4。
然而,若你的環境可快速適應新的改變,你可以嘗試最新的 V8與 Current。
測試與釋出
第 11章會討論 Node的除錯與測試以及其他的開發與釋出程序。
升級 Node
隨著新版釋出,保持 Node更新越來越重要。幸好升級程序很簡單且有替代方案。
你可以使用下列命令檢查版本:
node -v
如果使用了套件安裝程序,則執行套件更新程序以升級 Node與伺服器上的其他軟體
(Windows不需要 sudo):
sudo apt-get updatesudo apt-get upgrade --show-upgraded
如果使用了套件安裝程序,根據 Node官網上相關的指引操作,不然版本會不同步。
![Page 19: ix - 碁峰資訊epaper.gotop.com.tw/PDFSample/A491.pdf · 本書出版時,Node 的Current 版本是Node.js 6.0.0,並取消以Stable 表示開發中的分支。 Node.js 6.0.x](https://reader030.vdocuments.us/reader030/viewer/2022013002/5ece5bbe73171a196779bcca/html5/thumbnails/19.jpg)
Node、V8 與 ES6 | 15
你也可以使用 npm來升級 Node,輸入下列的命令:
sudo npm cache clean -fsudo npm install -gsudo n stable
要在Windows、OS X、或 Raspberry Pi上安裝最新版的 Node,從 Node.js下載安裝程序
並執行,它會以新版蓋過舊版。
Node Version Manager
在 Linux與 OS X環境中,你也可以使用 Node Version Manager(nvm)
工具(https://github.com/creationix/nvm)來更新 Node。
Node package manager(npm,https://www.npmjs.com/)的更新比 Node更勤快。只要更
新它時,執行下列的命令:
sudo npm install npm -g n
此命令安裝最新版本。輸入下列命令檢查版本:
npm -v
但要注意這可能會導致問題,特別是在團隊環境中。若團隊成員使用 Node所安裝的
npm版本,而你手動升級 npm到最新版本,可能會引發難以發覺的不一致。
第 3章會進一步討論 npm,但現在可以用下列命令更新所有 Node模組:
sudo npm update -g
Node、V8與 ES6Node背後是 JavaScript引擎,大部分的實作使用的引擎是 V8,它是 Google為 Chrome
所設計,原始碼在 2008 開源。V8 JavaScript 引擎以 just-in-time(JIT)編譯器將
JavaScript編譯成機械碼而非多年來 JavaScript一般的直譯以提升 JavaScript的速度。V8
引擎是以 C++撰寫。
![Page 20: ix - 碁峰資訊epaper.gotop.com.tw/PDFSample/A491.pdf · 本書出版時,Node 的Current 版本是Node.js 6.0.0,並取消以Stable 表示開發中的分支。 Node.js 6.0.x](https://reader030.vdocuments.us/reader030/viewer/2022013002/5ece5bbe73171a196779bcca/html5/thumbnails/20.jpg)
16 | 第一章:Node 環境
Microsoft的 Node.js
Microsoft的 Node使用 Chakra這個 JavaScript引擎,它是用來支援物聯
網。第 12章會對此版本做進一步的說明。
Node v4.0釋出時,它支援 V8 4.5,與當時的 Chrome使用相同版本的引擎。Node維護
團隊承諾 V8的未來釋出版本,這表示 Node現在支援 ECMA-262(ECMAScript 2015或
ES6)的許多新功能。
Node v6的 V8支援
Node v6支援 V8的 5.0版,新版的 Node會支援新版的 V8。
之前的 Node 要使用新的 ES6 功能時必須在執行應用程式時使用 harmony 旗標
(--harmony):
node --harmony app.js
現在的 ES6功能支援依據下列條件決定(抄自 Node.js文件):
• 所有 V8的穩定版功能在 Node.js中預設為開啟,不需要任何執行旗標。
• V8團隊認為幾近完成但非穩定版的階段功能需要執行旗標:--es_staging(或同義
的 --harmony)。
• 開發中的功能可透過相對應的 harmony旗標(例如 --harmony_destructuring)個別
啟用,但除了測試目的外並不鼓勵這麼做。
第 9章會討論 Node的 ES6支援與如何有效的使用不同功能。現在,知道下列 Node有直
接支援的 ES6功能就好:
• Classes
• Promises
• Symbols
• Arrow函式
• Generators
![Page 21: ix - 碁峰資訊epaper.gotop.com.tw/PDFSample/A491.pdf · 本書出版時,Node 的Current 版本是Node.js 6.0.0,並取消以Stable 表示開發中的分支。 Node.js 6.0.x](https://reader030.vdocuments.us/reader030/viewer/2022013002/5ece5bbe73171a196779bcca/html5/thumbnails/21.jpg)
進階:Node 的 C/C++ 附加元件 | 17
• Collections
• let
• 展開運算子(spread operator)
進階:Node的 C/C++附加元件現在 Node已經安裝好且你有機會進行試驗,你或許會思索你到底安裝了什麼。
雖然建構 Node應用程式使用的是 JavaScript語言,但大部分的 Node是以 C++所撰寫。
通常這資訊隱藏在我們使用的應用程式之後,但若熟悉 C或 C++,你可以使用 C/C++來
建構附加元件以擴充 Node功能。
撰寫 Node附加元件如同撰寫傳統 C/C++應用程式。一方面是 V8 等函式庫,另一方
面,Node的附加元件並非以你通常使用的工具編譯。
Node附加元件的文件有 Hello World範例,如果熟悉 C/C++,你可以參考它。寫好程式
之後,你必須使用 node-gyp工具實際將它編譯成 .node附加元件檔案。
首先是建構出稱為 binding.gyp的組態檔案,它使用類似 JSON的格式來提供附加元件的
資訊:
{ "targets": [ { "target_name": "addon", "sources": [ "hello.cc" ] } ]}
Node的附加元件組態步驟使用下列命令執行:
node-gyp configure
它建構出組態檔案(Unix的 Makefile或Windows的 vcxproj檔案)並儲存在 build/目錄
下。執行以下命令以建構 Node附加元件:
node-gyp build
![Page 22: ix - 碁峰資訊epaper.gotop.com.tw/PDFSample/A491.pdf · 本書出版時,Node 的Current 版本是Node.js 6.0.0,並取消以Stable 表示開發中的分支。 Node.js 6.0.x](https://reader030.vdocuments.us/reader030/viewer/2022013002/5ece5bbe73171a196779bcca/html5/thumbnails/22.jpg)
18 | 第一章:Node 環境
編譯過的附加元件安裝在 build/release目錄,已經可以使用。你可以如同其他 Node所安
裝的元件一樣將它匯入你的應用程式中(見第 3章)。
維護原生模式模組
雖然已經超出本書範圍,但若你有興趣建構原生模式模組(附加元件),
你必須知道不同平台的差異。舉例來說,Microsoft在 Azure上提供原生
模組的特殊指令(https://azure.microsoft.com/en-us/documentation/articles/
nodejs-use-node-modules-azure-apps/),而 node-serialport這個原生模組的
維護者有列出維護模組時所面對的挑戰(http://www.voodootikigod.com/on-
maintaining-a-native-node-module/)。
當然,若你不熟悉 C/C++,你可能會打算使用 JavaScript建構模組,第 3章也會加以討
論。如果你知道這些語言,附加元件能夠有效的擴充功能,特別是特定系統的功能。
注意 Node從 v0.8到 v6.x間有相當大幅度的改變,為應付可能發生的問題,你必須安裝
Native Abstractions for Node.js(NAN,https://github.com/nodejs/nan),此檔案可幫助緩
和不同版本 Node.js間的差異。