2013年5月9日星期四

NPK 釋出!打包你的 Node.js 程式!

NPK』是什麼?一個打包 Node.js 程式的工具,之所以會有這個工具,完全是拜下周(5/18 - 5/19)將在中研院舉行的 JSDC 所賜。因為這次筆者也有個 Talk,將探討如何去編譯我們寫出來的 Node.js 程式,所以過程中便寫出了這樣一個工具。

https://github.com/cfsghost/npk

事實上,目前的 NPK 不是個新東西。JavaScript 經過多年的發展,早已經有非常多合併 JavaScript 程式碼的工具可以使用,對於前端工程師來說,是再尋常不過。不過,針對 Node.js 的程式碼,這樣的工具卻相對來說非常少。

如果你想嘗試使用看看,可以立即用 NPM 來安裝 NPK:

npm install npk -g

以 NPK 裡的範例專案為例,你可以直接下命令打包該專案:
npk tests/purejs/

接著你可以在輸出的資料夾中找到打包好的檔案:
tests/purejs/out/app.js/

甚至是直接執行他:
node tests/purejs/out/app.js/app.js

NPK 工具定義了一個新的屬性『npk_target』在 package.json,用來讓程式人員自行決定要合併和連結哪些 JavaScript 程式(像過去為 C/C++ 等語言寫 Makefile),可以參考 NPK 內附範例專案的 package.json。

最終目標『編譯』成二進位格式(Binary)

在與一些企業以及同業分享 Node.js 技術和其未來發展時,時不時會有人提出一個問題:『我們能不能編譯自己寫的 Node.js 程式?』這個問題,往往會開始引發一長串的討論,有一些人為終止這個問題,甚至會開始引用 JavaScript 語言的設計宗旨:『明碼保存,不需要預先編譯』,來強調我們不應該把 JavaScript 的優勢給閹掉。當然,這樣一廂情願的說法,是不可能消除許多人的疑慮,尤其是和 Open Source 路線不熟的企業,或是被『壞客戶欺負』的工程師。

有些眼睛比較亮的人,或許已經發現到,這其實是個複合性的命題,會提出這個問題的人,多半想要知道或得到的是:
  • 能否透過預先編譯 JavaScript 程式,讓執行效能提升。
  • 想要打包自己寫的程式,讓他合併成一個,以方便釋出或管理。
  • 保護自己的程式碼。

這些都將會是 NPK 的目標,但現在暫且不提 Node.js 程式碼被編譯的可行性,更多細節將會在 JSDC 的議程上有更近一步的探討。但若只是要達到第二項,打包自己的程式,將 Node.js 程式碼合而為一,你現在就已經可以用『NPK』工具做到。

後記

為了準備 JSDC 的 Talk,過程中筆者原本使用了一個 NPM 上現成的模組『nld』,完成合併 Node.js 程式碼的工作,但由於該模組有一些問題,而且有一年以上沒有維護。種種因素,才促使自己動手做一個新的 Node.js Linker 給 NPK。

此外,有興趣的人可以試著用編輯器打開打包成功的 JavaScript 檔案,你除了會看到所有的 Source Code 已經被合併,而且會發現程式碼都經過 Uglify 處理過,某種程度上可以算是被加密了。

2013年4月22日星期一

OSDC.TW 2013 簡報釋出!使用 JavaScript 大搞桌面應用和嵌入式系統!

OSDC.TW 2013 順利在中央研究院國際會議廳閉幕,但一如往年,失落感接踵而來。為了這次的 Talk,可說是花了不少工夫,除了研究 Webkit 的內部實作,以及 V8 JavaScript Engine 之外,最後也發表了一個新的 JavaScript 作業系統『Stem』,一個可以完全用 JavaScript 和 Web 技術去開發應用程式的嵌入式作業系統。Stem 落實了用 JavaScript 語言開發嵌入式系統的理想,並簡化嵌入式應用開發,讓人人都能輕鬆躍過以往嵌入式系統開發的艱澀門檻。

這邊釋出當天的簡報檔,有興趣者可自行參閱:


此外,對 Stem 有興趣的人,可以拜訪專案網站:

http://stem.mandice.org/

也可以在 IRC 上交流:

英文頻道:irc.freenode.net #stemos
中文頻道:irc.freenode.net #stemos-zh

註:目前 Stem 已釋出 x86 版本的安裝鏡像檔,近期內將會釋出 ARM 的版本,敬請期待。有興趣參與開發者,歡迎來信一同交流。

2013年4月1日星期一

這年頭,你只需要懂 node-webkit !

極為幸運,今年初的投稿被 [OSDC 2013] 錄取,本次主題是『node-webkit』,將於 4/20(六)早場起,全面進攻。

你可能在問什麼是『node-webkit』?完全搞不清楚頭緒?身為 JavaScript 和 Node.js 的重度使用者,問問自己內心吧!不用懷疑,你最想要的東西,就在眼前。試著想像,一個沒有邊框又可獨立執行的瀏覽器,裡面跑著你用 JavaScript + HTML5 寫的應用程式,有如原生的桌面應用程式,當你想發行並釋出程式時,還能打包成一個獨立運作的執行檔,令人垂涎三尺呀!

『node-webkit』顧名思義就是將 Node.js 整合進 webkit(Chrome/Chromium/Sarfari 所用的網頁排版引擎)之中,讓你可以在網頁程式中使用功能強大的 Node.js。這意味著,你完全可以用 Node.js + HTML5 等 Web technology 開發跨平台『桌面應用程式』。由於『node-webkit』狹著 Node.js 以及其強大的第三方模組支援,而使用者介面採用了 Chromium(Google Chrome 的開放源始碼版本)核心當做繪圖引擎,能完全支援當前最新的各種網頁技術(如:HTML5、CSS3、WebGL 等)。因此,只要身為一個前端網頁開發者,都能輕易利用它設計出優雅、炫麗的圖形化介面,然後完成一支獨立運行的桌面應用程式。

如官方網站的範例,在前端網頁程式中使用 Node.js:

<html>
<head>
<title>Hello World!</title>
</head>
<body>
<h1>Hello World!</h1>
We are using node.js <script>document.write(process.version)</script>
</body>
</html>

這年頭,你真的只需要懂 node-webkit!我們 OSDC 2013 中研院國際會議廳見!

2013年3月11日星期一

歡迎洽詢!Node.js on Embedded System 專業技術服務!

經過一年多的孕釀,我們的團隊【Mandice】已有萬全的準備,在此正式對外宣布提供 Node.js on Embedded System 的專業技術服務,歡迎立即來信洽詢。

嵌入式系統開發生態已經改變,今天的 Node.js 已為嵌入式系統帶來全新的面貌,其高效開發的優勢,以及不俗的效能和數不清的現成模組,讓嵌入式系統的產品開發周期以及技術門嵌大大降低。導入使用 Node. js 能讓產品設計者,更能專注於創新和使用者體驗,因應這時代的快速發展。

我們的團隊在這一年間,已經深耕各類 Node.js 相關技術,更結合團隊過去的系統技術和產品經驗,提供了整套的系統軟體平台以及顧問服務給許多合作夥伴和大廠,讓其開始以 Node.js 開發自家產品。至今,已有一些面世或即將面世的產品,使用了 Node.js 的技術開發嵌入式系統,甚至已經著手準備第二代產品,成效相當不錯。

若您也想趕上這班列車,歡迎與我們聯繫,我們將提供您最好的服務。

有意請來信至電子郵件信箱,我們會立即與您聯繫:
fred@mandice.com

2013年2月22日星期五

Node.js EventEmitter 事件管理神器

如果你已經相當熟悉 JavaScript 的開發,那就肯定對其事件機制不陌生。我們等待一個物件產生事件,去觸發我們設定的 callback 函式,是最常見不過的東西了。不過,如果你想要設計一個自己的物件,並容許別人可以監聽它的事件,要怎麼做呢?

如果你什麼都沒有,你肯定是在自己的物件中宣告一個 event handler 的表,當別人想要針對特定的事件掛上 callback function 時,就記錄在該表內。然後在事件被產生時,去呼較對應事件的所有 callback function。然後,你會設計像 .on() 、off() 和 emit() 之類的方法,讓別人可以使用。

是的,很累。既然事件機制是我們在 JavaScript 中常用的功能,每個物件都寫一次這樣簡單的事件管理,真的很浪費時間。其實,Node.js 本來就有實作這樣的機制『EventEmitter』讓開發者直接使用。

EventEmitter 的使用方法很簡單:

var util = require('util');
var events = require('events');

var MyClass = function() {
};

util.inherits(MyClass, events.EventEmitter);

MyClass.prototype.ping = function() {
    this.emit('response', 'pong');
};

實際使用這個 Class 建立物件,然後監聽事件,最後觸發事件:
var myClass = new MyClass();

myClass.on('response', function(msg) {
    console.log(msg);
});

myClass.ping();

後記

把 EventEmitter 的繼承寫在 Class 宣告和 prototype 宣告之間很彆扭,但在 Class 宣告後立即使其繼承 EventEmitter 是正確的邏輯行為,所以,勉強接受他吧。