使用node-webkit構建桌面應用程序(一)
Web前端的現狀
目前Web前端的現狀較之5~6年前,簡直不能同日而語:從所使用的技術、工具、框架到開發一個產品所需要付出的工作量,從前端開發從業人員的數量到Web應用的數量,從企業對于Web前端的重要程度的認識到Web實際上為企業帶來的回報,一切都有了翻天覆地的變化。
借助HTML5+CSS3的普及,加上一些開箱即用的CSS框架(如bootstrap,foundation等)支持,人們已經可以非常容易地從 零開始搭建一個Web應用的前端。一個在UI方面非常業余的程序員也可以很快做出一個像模像樣的用戶界面。而另一方面,基于操作系統原生API,要想設計 并實現一個桌面應用,需要的付出則遠遠超過同水平的Web界面。
Webkit瀏覽器內核
Webkit作為最受歡迎的瀏覽器內核,自然有非常多的port。比如GTK+對它的port – WebkitGTK,以及構建在WebkitGTK之上的Python的bind(即Python對WebkitGTK的本地動態庫的一個包裝,可以使用 Python的語法來編寫代碼,但是底層仍然使用WebkitGTK自身的動態庫)。使用WebkitGTK的Python版本,開發人員可以用 HTML+CSS來開發應用,然后寫一點Python腳本,最后將其運行在桌面上。
這里有個早期的例子來教你如何寫一個所見即所得的編輯器。桌面應用開發中,用戶界面的復雜性一直是一個難題,而這種方式可以降低很多用戶界面開發的復雜性,將界面開發交給更加靈活、更加容易編寫和調試的方式——HTML+CSS。
這種模式下基本的開發流程是編寫一個HTML頁面(作為程序入口),然后在這個頁面上引入額外的CSS(界面風格)和JavaScript(動 作),然后將這些資源交給工業級瀏覽器內核Webkit來渲染 。 這個過程和在瀏覽器中訪問該文件并無二致,但是有兩個額外的好處。
-
頁面運行在一個“桌面應用程序”中。
沒有地址欄,狀態欄,菜單欄等,看起來更像是一個桌面應用。
-
用戶界面開發的復雜性被“外包”給一個更簡單的環境。
這就是傳說中的混合(hybrid)開發模式,比如現在移動開發中的cordova就是采用這種模式,使得本來被視為天塹的原生的用戶界面開發變為坦途。
node-webkit簡介
node-webkit是一個基于chromium和node.js的應用程序開發工具。它不但支持使用傳統的HTML5+CSS3+JS方式來開 發應用程序,還支持無縫地與Node.js集成,也就是說,所有的Node支持的與操作系統交互的功能,如網絡連接,文件系統,操作系統資源訪問等,以及 Node之上的第三方庫都可以在node-webkit中進行使用。
更好的是,node-webkit是一個跨平臺的工具,你可以使用它構建出運行在Mac OS,Linux以及Windows下的應用程序。應用程序通過Node.js來進行與系統相關的訪問,而用HTML5+CSS3進行用戶界面部分的設計。
node-webkit未必是未來桌面應用的唯一方式,但是卻是一個非常好的選擇,特別對于已經熟知Web前端開發技術棧的眾多開發者來說,無需學習一門新的語言,一切都在很大程度上得到了簡化。
第一個node-webkit應用程序
開發node-webkit應用程序非常簡單。在這里下載系統對應的版本。并確保對應的二進制文件(nwnw.exe)在系統的PATH之中。
創建一個新的目錄,然后在該目錄中創建一個package.json文件和一個index.html文件:
$ mkdir -p hello-node-webkit $ cd hello-node-webkit $ touch package.json index.html
package.json文件的內容如下:
{
"name": "hello-node-webkit",
"version": "0.1.0",
"main": "index.html"
} index.html文件的內容如下:
<html>
<head>
<title>Hello node-webkit</title>
</head>
<body>
<div>
<h1>Hello node-webkit</h1>
</div>
</body>
</html> 然后將這兩個文件打在一個zip格式壓縮包中:
$ zip -r hello-node-webkit.zip *
然后將這個文件重命名為hello-node-webkit.nw,最后使用node-webkit來啟動這個應用程序。
$ ~/Tools/node-webkit.app/Contents/MacOS/node-webkit hello-node-webkit.nw
添加外部JS/CSS
接下來我們為這個頁面添加一些外部的引用:CSS/JavaScript文件。首先創建兩個目錄style和script,然后分別創建文件如下:
├── index.html
├── package.json
├── script
│ ├── app.js
│ └── jquery.min.js
└── style
└── style.css 其中,style.css定義了h1的簡單樣式:
h1 {
font-size: 20px;
color: #999999;
} 而app.js則注冊了一個簡單的事件處理器:
$(function() {
$("h1").on("click", function() {
alert("Heading 1 is clicked");
});
}); 此時的index.html修改如下:
<html>
<head>
<title>Hello node-webkit</title>
<link rel="stylesheet" type="text/css" href="style/style.css">
</head>
<body>
<div>
<h1>Hello node-webkit</h1>
</div>
<script type="text/javascript" src="script/jquery.min.js"></script>
<script type="text/javascript" src="script/app.js"></script>
</body>
</html> 還是按照上一小節的命令完成打包,改名,啟動之后。點擊h1元素時,會彈出對話框如下:
在這個例子中,我們使用了外部的css文件來添加樣式,還引入了jQuery作為訪問DOM元素的工具,最后還使用了一段調用jQuery的JavaScript代碼。
構建腳本
你可能已經注意到了,使用node-webkit開發非常方便。但是這一系列的動作(修改HTML+CSS,壓縮打包,改名,啟動)等有一部分重復工作,我們可以將其自動化。
好在已經有了一個很好用的grunt的插件:grunt-node-webkit-builder,這個插件可以幫助我們自動執行壓縮打包這些動作。
$ npm install grunt-node-webkit-builder
然后定義一個Gruntfile.js,這個文件中指定源文件(所有的HTML,JavaScript代碼,CSS文件)所在目錄,目標文件所在目錄,需要構建的應用程序指定的操作系統平臺等:
module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
nodewebkit: {
options: {
platforms: ['osx'],
buildDir: 'builds',
},
src: ['app/**/*']
}
});
grunt.loadNpmTasks('grunt-node-webkit-builder');
grunt.registerTask('default', ['nodewebkit']);
}; 這樣,我們修改之后,就可以直接執行:
$ grunt
進行打包了。比如在Mac下,構建出來的應用位于builds/<app-name>/osx目錄下,要啟動該應用只需要在命令行輸入下列命令:
$ open builds/hello-node-webkit/osx/hello-node-webkit.app
或者在Finder中雙擊打開即可。
可以看到上例中的應用程序還有濃重的瀏覽器痕跡,比如地址欄,刷新按鈕,甚至還有一個DevTools的按鈕。
我們可以通過修改package.json來指定:
{
"name": "hello-node-webkit",
"version": "0.1.0",
"main": "index.html",
"window": {
"toolbar": false,
"width": 800,
"height": 600
}
} 這樣的界面就更像是一個桌面應用了:
到目前為止,這個小的應用程序并沒有什么有趣的特性,用戶界面也毫無美感,但是有了這些基本知識和工具之后,我們就可以開始更進一步的開發了。除了使用既有的CSS框架來完成用戶界面的美化,我們還會使用node.js訪問系統資源來構建真實的應用程序。
一個實際的小例子
gist是一個非常好用的代碼片段管理工具,Github的用戶可以將自己的代碼片段保存為一個gist,每個gist中可以包含若干個文件,每個gist可以通過一個唯一的URL指定,比如:https://gist.github.com/abruzzi/44550f2b4cb812b19701。
我們這里將開發一個具體的小例子:通過Node.js請求到一個gist,并將其中的所有文件名都列出來,最終的結果看起來是這樣的:
首先我們需要安裝一個npm的包:gisty,這個包提供的API可以方便地獲取gist。安裝命令如下:
$ cd app/ $ npm install gisty
注意此處的app目錄為我們的應用目錄,其中包含了HTML文件,CSS,及JavaScript等,在這個目錄中執行npm install會創建一個node_modules目錄,gisty會安裝在這個目錄中。
然后我們修改scripts/app.js,內容如下:
var Gisty = require('gisty');
$(function() {
var gist = new Gisty({
username: 'abruzzi'
});
gist.fetch('44550f2b4cb812b19701', function(error, gist) {
if (error) {
throw new Error(error);
}
buildGistItem(gist);
});
function buildGistItem(gist) {
var gists = $("#gists");
for (filename in gist.files) {
var gistItem = $("<li></li>");
gistItem.text(filename);
gistItem.appendTo(gists);
}
}
}); 注意此處的require語句,這正是使用node-webkit的強大之處:可以在“前端”代碼中使用“后端”代碼。gisty需要指定用戶名來 創建一個Gisty對象, 然后在這個對象上調用fetch方法,并將gist的ID傳入來獲取gist對象。gist對象上有files屬性,其中保存該gist對應的文件名和文 件內容。
使用gisty的API獲取到gist列表之后,將其插入在頁面元素上。HTML頁面上聲明了一個ID為gists的ul,然后在app.js中動態的創建li來添加到該ul上。
<html>
<head>
<title>Hello node-webkit</title>
<link rel="stylesheet" type="text/css" href="style/style.css">
</head>
<body>
<div>
<h1>Gist #44550f2b4cb812b19701</h1>
</div>
<div>
<ul id="gists"></ul>
</div>
<script type="text/javascript" src="script/jquery.min.js"></script>
<script type="text/javascript" src="script/app.js"></script>
</body>
</html> 作者簡介
邱俊濤,ThoughtWorks咨詢師,喜歡技術,崇尚輕量級的開發/工作方式,痛恨冗長的會議和各種繁瑣的流程。他還是《JavaScript核心概念及實踐》一書的作者,個人博客是http://icodeit.org,博客上經常會有各種技術的分享。
來自:http://www.infoq.com/cn/articles/using-node-webkit-to-build-desktop-applications-part1