使用 NW.js 構建跨平臺桌面應用程序
NW.js 是一個使用 Web 技術創建本地應用的框架,如 HTML、JavaScript 和 CSS。簡單地說,當你在使用普通的流程開發一個 Web 應用時,開發完成后,運行一個生成器,將所有東西編譯成一個本地應用,它會像一個瀏覽器一樣運行你的 Web 應用。這種應用就被稱為“Hybrid 應用(一種混合本地編程和 Web 編程技術的應用)”。
Hybrid 應用的偉大之處,不僅在于它可以使用你熟悉的語言(HTML、JavaScript 和 CSS)來開發,還因為它比普通的 Web 應用更有優越性:
-
控制瀏覽器和瀏覽器版本(你知道你的應用是調用的什么瀏覽器)。NW.js hybrid 應用使用 Chromium 來顯示— 這是一種開源瀏覽器,也是 Google Chrome(谷歌瀏覽器)的核心。因此,能在 Chrome 中運行的應用也能在 NW.js 中運行。
-
控制視窗。例如,你可以定義一個固定大小,或者最小化/最大化的視窗。
-
對本地文件的訪問不會受 同源策略 的約束。如果你想在瀏覽器通過 XMLHttpRequest 打開一個不在相同目錄的本地文件,請求會阻止。而 NW.js 應用中關閉了這樣的行為。
它們也提供了 API,帶來如下優點:
-
整合 Node.js
-
訪問剪貼板
-
訪問文件系統
-
訪問硬件(比如獲取打印機列表)
-
托盤圖標
-
自定義文件選擇對話框
-
整合 shell(在默認的資源管理器或瀏覽器中打開文件或 URL)
-
自定義主窗口的選項(關閉按鈕、菜單欄)和上下文菜單
-
設置和獲取綻放等級。
看起來不錯?那讓我們開始吧。在這篇文章中,我們會通過練習熟悉 NW.js,并學習如何創建一個 Hybrid 應用。
NW.js 與 Electron 相比之下的優勢
首先要說的是,NW.js 并不是唯一的 Bybrid 應用框架。另一個這樣的框架叫 Electron 。它誕生于 2013年,比 NW.js 晚兩年,不過因為它來自于 GitHub,很快就被大家所認識。現在你可能對它們之間的區別感興趣。這里列舉了與 Electron 相比,NW.js 的優勢:
-
支持 chrome.* API。這些 API 可用于與瀏覽器交互。
-
支持 Chrome 應用 。Chrome應用是使用 Web 語句編寫并打包的應用。這些應用與 NW.js 不同,因為它們沒有整合 Node.js,而且通過 Chrome Web Store 發布。(Chrominum 會在2018年8月取消對它的支持。不過因為 這篇文章 所說的原因,NW.js 仍然會支持 Chrome 應用。)
-
支持 NaCl (Native Client,本地客戶端) 和 PNaCl (可移植的本地客戶端) 應用。它們致力于性能,因此使用 C 和 C++ 編寫。
-
擁有 V8 的映像源碼保護,保護你的應用程序源碼。使用 nwjc 工具可以將你的代碼編譯為本地代碼。
-
擁有一個內建的 PDF 閱讀器。
-
允許打印預覽。
-
支持 Node.js 整合 Web Workers 。這用于編寫多線程應用。
不過,Electron 也有值得一提的優點:
-
內建自動更新
-
自動向遠程服務器報告程序崩潰。NW.js 只會把錯誤信息寫入一個本地文件,需要手工提交。
還有一個重要的區別。NW.js 應用的入口是一個 HTML 文件中的 Form。這個 HTML 文件會直接在 GUI 中打開。
另一方面,Electron 應用使用一個 JavaScript 文件作為入口。這個 JavaScript 文件由另一個主進程打開,然后由它在 GUI 中打開 HTML。這樣的話,理論上你可以不通過 GUI 運行 Electron 應用。同樣的道理,關閉 GUI 不會關閉主進程;你需要調用一個 API 來終止主進程。
雖然 Electron 不使用 GUI 來啟動 JavaScript 寫的桌面應用,但 NW.js 應用卻更容易建立示基于顯示 HTML 的應用。
創建一個演示應用
來,開始創建我們的應用,稍后我們會把它編譯成本地應用。因為創建 Web 應用的方式多種多樣——使用不同的 JS 語言(TypeScript、CoffeScript 等),模塊加載器(RequireJS、webpack、SystemJS 等),框架(AngularJS、React、Vuew.js 等)和(樣式表)預處理器(SCSS、LESS、Haml 等)——每個人都有自己的偏好,我們只使用基本的技術,HTML、CSS 和 JS(ES6 標準)。
NW.js 沒有樣板 (初始項目) 來完成初始的設置。它們都通過特定的框架、模塊加載器或預處理器來創建。然而,我們從頭開始實現一個簡單的 NW.js 應用程序。它會比較易懂,之后你可以很容易按自己的需求定制,或者把它變成樣板。
項目結構
首先,我們需要創建項的目錄結構和文件:
nw.js-example/
├── src/
│ ├── app/
│ │ └── main.js
│ ├── assets/
│ │ └── icon.png
│ ├── styles/
│ │ └── common.css
│ ├── views/
│ │ └── main.html
│ └── package.json
└── package.json
說明:
-
src/ 應用程序源文件。
-
src/app/ JavaScript 文件。
-
src/assets/ 圖片,在我們的例子中只有 icon.png 文件,它將作為一個窗口圖標來顯示。
-
src/styles/ 通常包含 SCSS 或 LESS 文件,在我們的例子中,僅僅是一個簡單的 CSS 文件。
-
src/views/ 包含 HTML 視圖文件。
-
src/package.json NW.js 應用程序清單文件,我們也可以在這個文件中為應用程序指定特殊的依賴項。
-
package.json 是一個 npm 包文件 ,我們用它來構建工作流,也可以指定特殊的依賴,這在實際的 NW.js 應用程序中不是必須的,例如根據依賴構建。
創建清單文件
現在,我們已經創建了項目結構和文件,可以從 NW.js 的清單文件 src/package.json 開始了。根據 文檔 ,這個文件基本上僅需要兩個屬性:name,一個應用程序名稱,和 main,一個作為入口的 HTML 文件的路徑。但是我們需要添加更多信息,如窗口的圖標的路徑,以及最小寬度和高度,以確保用戶不會看到任何奇怪的事情:
{
"name":"nw.js-example",
"main":"views/main.html",
"window":{
"min_width":400,
"min_height":400,
"icon":"assets/icon.png"
}
}
就是這樣!應用程序在開始運行后,將打開 src/views/main.html,main 的路徑是以清單文件( manifest file )為參考的相對路徑。
創建主視圖
在這個時候我們可以編寫一個待辦事項程序。但是我們要專注于 NW.js 和它本身的功能。因此,我更傾向讓你自己來決定我們的應用程序的功能。 我在 GitHub 上創建了一個示例項目 NW.js-示例 來演示幾個 NW.js功 能,例如,Node.js 集成和剪貼板訪問。 您隨時可以在應用程序中用它來測試和研究。當然你也可以使用其他的功能。
不管你作何決定,你都必須要創建 thesrc/views/main.html 文件。因為它是我們應用程序的入口點。文件內容如下:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>NW.js-example | main</title>
<link rel="stylesheet" href="../styles/common.css">
</head>
<body>
<h1>Hello World :-)</h1>
<script src="../app/main.js"></script>
</body>
</html>
在真正的應用程序中,你可能有個多個其他的視圖文件并用 Ajax 加載它們。
為了簡單起見,您還可以創建本地超鏈接并引用其他 HTML 文件。 例如:
<a href="something.html">Something</a>
然后,在 src / views / 中創建 something.html 文件。
安裝 NW.js
現在我們創建了 NW.js 項目,包括清單和主視圖。最終我們需要一個方法直接在開發中運行 NW.js,并通過構建過程生成可運行于多個系統的本地應用。
為達此目的,我們需要兩個包:
-
nw (開發)
-
nw-builder (生產)
既然它們與我們的應用功能無關(使用它們只是為了開發和生產目的),我們在第二個,即放在根目錄下的 package.json 中創建 devDependencies 配置 ,加入它們。這個配置與 必須的 name 和 version 字段并列:
{
"name":"nw.js-example",
"version":"1.0.0",
"devDependencies":{
"nw":"^0.18.2",
"nw-builder":"^3.1.2"
}
}
現在只需要在項目的根目錄下運行下面的命令來安裝 devDependencies:
$ npm install
搞定!可以構建了。
打包和發布
我們在 package.json 中加入 npm 腳本來讓打包變得簡單。npm 腳本在右邊定義要運行的 CLI 命令,在左邊定義它的快捷方式,然后允許我們通過 npm run 來運行指定的快捷方式。現在添加兩個腳本,一個用于開發,一個用于生產:
{
"name":"nw.js-example",
"version":"1.0.0",
"devDependencies":{
"nw":"^0.18.2",
"nw-builder":"^3.1.2"
},
"scripts":{
"dev":"nw src/",
"prod":"nwbuild --platforms win32,win64,osx64,linux32,linux64 --buildDir dist/ src/"
}
}
直接運行 NW.js
直接運行 NW.js 應用,只需要這個命令:
$ npm run dev
這個快捷方式會調用我們定義在 script 下 dev 對應的命令以 使用 nw 包 。開發機器上直接打開一個新窗口,顯示著 src/views/main.html。
生產構建
要進行生產構建需要使用 nw-builder ,它支持針對 Windows、Linux 和 macOS 進行輸出。在我們的例子中,我們會針對所有這些平臺打包,并且包含32位和64位版本。對于 macOS 來說,目前只能在以前的模式下構建 32位的版本。所以,我們只構建64位版本。
運行如下命令進行生產構建:
$ npm run prod
和直接運行 NW.js 一樣,它也使用我們定義在 scripts 中的 CLI 命令。
然后得等一會兒 …
完成之后,看看你的 dist/ 目錄,就像這樣:
dist/
└── nw.js-example/
├── linux32/
├── linux64/
├── osx64/
├── win32/
└── win64/
非常好,我們差不多完成了!
測試和調試
手工測試
既然 NW.js 是基于 Chrominum 的,那么它的手工測試和 Chrome 一樣簡單。如果你遇到一個BUG——可視效果或者功能性的——你都可以通過 快捷鍵F12 或者下面的程序打開開發者工具:
nw.Window.get().showDevTools();
注意這需要 SDK build flavor [譯者注:flavor 可以理解為插件或者功能擴展]。如果你想在生產構建的時候去掉開發者工具,你可以使用另一個 flavor 或者直接阻止F12事件。
自動化測試
自動化的單元測試(幸好有你)廣泛用于確保不同的實現能正確工作,這避免了總是進行手工測試。
如果你的應用不使用 NW.js API 提供的特有方法,理論上來說你可以停留在一般的Web應用工作流上——例如,把 Karma 作為一個運行器與作為框架的 Jasmine 聯合使用。
但是如果你使用 NW.js API 特有的方法,你需要在 NW.js 應用中運行測試,這才能確保使用到的 API 方法存在。一種方法是使用 NW.js 的 Karma 啟動器插件,比如 karma-nodewebkit-launcher 。它和其它瀏覽器的 Karma 啟動器插件一樣:在 NW.js 容器中打開應用并進行檢查,完成之后再自動關閉應用。
不過既然 NW.js 不是 headless (就像 PhantomJS 那樣的) [譯者注:Headless 瀏覽器就是沒有 GUI 的瀏覽器] , 它總是需要顯示出來。換句話說,它不能在純 CLI 服務器上運行測試。幸運的是,這種情況下可以使用 Xvfb 來模擬顯示。
希望本文介紹已讓你熟悉 NW.js 的優點及使用環境。使用混合應用程序,要比分發包含 HTML 文件的壓縮文件夾然后運行好得多,有很多因素可以證明這一點。NW.js 可以用來代替本地的應用程序,因為你不再需要專注于復雜的 GUI,并且,它有很多內置的功能,如視頻播放器。 由于可以檢測運行環境,你可以用 NW.js 開發既能在常規 Web 服務器上使用,又能在客戶端計算機上使用的應用程序。配合使用一些小技巧,再加上有強大的 Chromium 引擎,用戶體驗幾乎與本機應用程序無異。
當創建一個新的 NW.js 項目時,你首先要明確想使用的框架、模塊加載器和預處理器——這取決于你對這些工具的熟悉度——否則只能是從頭開始。做好決定之后,您可以尋找一個適合您需求的 NW.js 樣板文件。
來自:https://www.oschina.net/translate/cross-platform-desktop-app-nw-js