在 Node.js 上使用 Dojo

來源:互聯網
上載者:User

Node.js 最近非常火熱,不僅開源社區對其非常關注,甚至微軟對其也提供了官方的支援,從而讓 Node.js 也能運行於 Windows 系統,這為 Node.js 的進一步流行奠定了基礎。本文將介紹 Node.js 和 Dojo 的模組管理機制,並在此基礎上詳細介紹在 Node.js 上運行 Dojo 架構的方案。最後通過一個例子,示範如何用 Dojo 的 DTL 模組來解析一個基於 Django 範本語言的模板檔案。

一個普遍的看法是 Node.js 讓 JavaScript 成為了伺服器端語言,於是自然很多人都把 Node.js 看成了一個 Web Server。但實際上並非如此,Node.js 只是一個 JavaScript 宿主環境,它解釋並運行 JavaScript,同時提供了很多原生對象(Native Object)讓 JavaScript 可以做更多的事情,例如進行網路通訊、檔案處理等等。就像,您可以用 Perl、Python 寫一個 Web Server 一樣,您也可以用 JavaScript 寫 Web Server。Node.js 適合建立 Web Server,因為它能高效的處理並發請求,但它自身並不是一個 Web Server。澄清這一點,我們就完全可以像用 Perl 一樣來用 JavaScript,讓它成為一種工具語言。當出現產品級的基於 Node.js 的 Web Server 時,我們也就能更加容易的上手進行 Web 服務器端開發。

為什麼要在 Node 上運行 Dojo
JavaScript 本身是一個設計非常精簡的語言,功能相對簡單,因為它的初衷並不是用來開發複雜的應用,而只是用於自動化的來操縱瀏覽器。面對日益複雜的前端應用,已經出現了很多類庫來解決這個問題,比如 jQuery、ExtJs、Dojo、YUI。這些類庫除了實現了瀏覽器安全色的 API,同時還有一大部分功能是純粹的用來增強 JavaScript 的功能。而這部分功能,正是伺服器端和瀏覽器端通用的,我相信如果在這方面提供一致性,一定是廣大 Web 開發人員所喜聞樂見的,這也是我寫這篇文章的目的。
這麼多類庫之中,Dojo 是所有當前類庫中最適合運行於 Node.js 的,原因有四:

  1. Dojo 和 Node.js 都基於 CommonJS 的 Module 規範。
  2. Dojo 天然支援 Node.js,很好的對瀏覽器相關代碼做了隔離。啟動指令碼能自動檢測 Node.js 運行環境檢測,無需任何修改即可直接使用。
  3. Dojo 所採用的單元測試架構和打包工具都是用 JavaScript 寫成,可以直接在 Node.js 上運行。從而,Dojo+Node.js 可以完成整個應用開發的生命週期。
  4. Dojo 有完整的物件導向體系,適合大型應用的開發。

Dojo 一直以來都這樣定義自己:JavaScript toolkit,而並不是 Ajax Library 之類的簡單的以前端應用為目標的架構。可見增強 JavaScript 功能是 Dojo 的一個重要目標,它的強大的物件導向的機制,事件機制,豐富的工具庫,已經為大型前端應用的開發提供了很好的基礎。而現在,它將又能在 Node.js 上發揮作用。

Node.js 和 Dojo 的模組載入機制
Node.js 和 Dojo 都遵循 CommonJS 的模組相關規範。Node.js 支援的是 Module1.0 規範,而 Dojo 支援的是 AMD(Asynchronous Module Definition,即非同步模組定義)規範。雖然是兩個規範,但它們都是描述了模組的定義和載入機制,有很多共同點。這就為 Dojo 運行於 Node 提供了天然的基礎。在規範中,JavaScript 檔案和模組是一一對應的關係,每個檔案就是一個模組,模組之間可以通過相對路徑來引用。
對於 Node.js,要使用一個模組非常簡單,直接用 Module1.0 規範中定義的 require 函數即可,例如:

 var fs = require('fs');  var content = fs.readFileSync('filePath' ,' utf8' ); 

這裡的 fs 是 Node.js 內建的檔案系統操作的模組,可以通過它的標識“fs”來載入它,從而可以調用其提供的方法。這種模組依賴的方法和傳統程式設計語言類似,例如 Java 的 import,C# 的 use。

但對於 Dojo 支援的 AMD 規範,則定義的是一個非同步載入機制,稍微複雜。因為這個規範強調的是非同步,就需要通過一個回呼函數來使用模組,這個回呼函數會在依賴的模組載入完成之後被調用,例如:

 define(['dojo/date'], function(date){  var zone = date.isLeapYear(new Date());// 擷取當前是否閏年 }); 

這裡的 define 函數是由 AMD 規範定義的,其第一個參數是一個數組,包含了本模組需要依賴的模組,當這些模組載入完成後,會調用第二個參數:一個回呼函數。並按順序將依賴的模組作為參數傳遞給這個回呼函數,供本模組使用。關於 define 函數的詳細用法這裡不多介紹,有興趣的可以去查看相關規範文檔。我們僅需要知道它是一個非同步模組定義和載入機制。

Dojo 中所有的模組都是通過 define 函數定義的,很顯然,不支援 AMD 規範的 Node.js 是不認識 define 函數,不能直接執行這些模組的。因此,Dojo 必須自己維護模組的載入和執行,這也完全符合 Dojo 在瀏覽器端的行為,只是讀模數塊代碼的邏輯從 HTTP 要求轉換到了讀取檔案,其它邏輯維持不變。在 Dojo 的初始化代碼中已經包含了對 Node.js 環境的檢測,會自動根據環境使用不同的方法載入模組。

在 CommonJS 規範的基礎上,Node.js 和 Dojo 還都另外引入了類似的包(package)的概念。所謂一個包就是一個檔案夾,在 Node.js 下可以直接 require('packageIdentifer' ),而 Dojo 則是通過 define(['packageIdentifier' ], callback) 來使用一個包。這時 Node.js 會尋找檔案夾下的 index.js 或者 index.node 模組,而 Dojo 則尋找的是 main.js 模組。同樣,因為應用是運行於 Dojo 架構之下,包的概念以 Dojo 的實現為準。
如果把模組的載入理解為 Java 中的 ClassLoader,那麼 Dojo 就是實現了自己的 ClassLoader,來取代 Node.js 自身的行為。因此,要在 Node.js 上運行一個基於 Dojo 的應用,用的是類似下面的命令:

 node <dojoroot>/dojo.js load=xxx 

這個命令告訴了 Node.js 應該執行 dojo.js 這個模組,從而啟動了 Dojo 架構。而後面的參數 load=xxx 則是告訴 Dojo 應該執行 xxx 這個包(package)。這裡的 xxx 就是您的應用程式的入口位置。因為 Dojo 已經接管了模組的管理,所以這裡啟動並執行就是 xxx 這個包下的 main.js 模組。
理解了這些內容,我們就可以進一步瞭解如何配置 Dojo,讓其在 Node.js 上運行基於 Dojo 的應用程式。

在 Node 上運行 Dojo
下面通過一個簡單的例子來看,如何在 Node 上運行基於 Dojo 的程式。

1. 引入並配置 Dojo
我們知道,在瀏覽器端引入 Dojo 之類的架構,首先需要在頁面中引入架構自身,通常是通過 <script> 標籤引入,在引入的同時,還可以傳遞參數,對於 Dojo 來說,可以通過兩種途徑,一種是在 <script> 標籤中加入屬性,例如:

<script type=”text/javascript” src=”dojoroot/dojo/dojo.js” djConfig="isDebug:true"></script>

這裡的 djConfig 就是傳遞給 Dojo 的配置參數,設定了 isDebug 開啟狀態,從而可以輸出調試資訊。另一種方式是通過定義一個名為 dojoConfig 的全域變數,在其中對 Dojo 對其配置:

 <script type=”text/javascript”>  Var dojoConfig = { isDebug: true };  </script>  <script type=”text/javascript” src=”dojoroot/dojo/dojo.js” ></script> 

在 Node.js 中,方法是類似的,需要一個 Node.js 可啟動並執行模組來引入 Dojo。例如,建立一個 bootstrap.js 檔案,包含如下內容:

 global.dojoConfig = {     isDebug: true  };  require('./dojo/dojo.js'); 

Node.js 中定義全域變數的方法和瀏覽器端略有區別,它是通過為 global 增加一個屬性來定義全域變數。隨後,通過 require 函數引入 Dojo,相當於 HTML 頁面中的 <script> 標籤。因此,在本質上,這個 bootstrap.js 檔案就是包含配置資訊的 Dojo。直接使用下面的代碼就可以在 Node 上運行 Dojo 了:

 node <bootroot>/bootstrap.js 

當然,這行命令什麼也沒有幹,只是運行了一下 Dojo。底下我們來看如何在 Dojo 裡運行自己的 Dojo 程式。

2. 定義應用程式入口
上面提到了通過 dojoConfig 這個全域變數來配置 Dojo,除此之外,其中還可以定義自己的 package,每個 package 都可能是一個應用,或者一個類庫。所有的 package 都放在 packages 數組中:

 global.dojoConfig = {  isDebug: true,  packages: [{  name: 'mynode' ,location: '../mynode' }]  }; 

在這裡我們定義了一個名為 mynode 的 package,並指定了其位置。這是一個相對於 <dojoroot>/dojo/ 的位置。這樣,要執行這個 package,只要運行下面的命令:

 node <bootroot>/bootstrap.js load=mynode 

Dojo 通過 load 參數來獲得應該執行的 package,在這個 package 下的 main.js 模組會被執行,下面將會介紹。

3. 執行應用程式
如前面所述,package 本身並沒有特別的地方,它就是一個檔案夾。當僅指定一個 package,而非具體的模組時,Dojo 就會自動執行其下的 main.js 檔案。這個 main.js 模組和普通的模組本質上也沒有任何區別,但一般這個模組中僅包含應用初始化的邏輯,從而能夠啟動應用的執行。
現在我們先來看一個簡單的“Hello world”的例子。我們不使用任何 Dojo 的模組,而是只用 define 來定義一個自己的模組,讓它列印“Hello world”。我們在 main.js 裡放如下的內容:

 console.log(“Hello world”); 

這樣,當執行上面提到的命令:

 node <bootroot>/bootstrap.js load=mynode 

這樣,我們將會在命令列視窗看到輸出的“Hello world”。這裡我們並沒有用任何的 Dojo 模組,而是僅僅讓 Dojo 去尋找到 main.js 並執行它。那下面來看如何去依賴 Dojo 的模組來實現自己的應用邏輯。

這個例子將使用 Dojo 對 Django 範本語言(DTL)模組的實現來做字串的轉換:

 define(['dojox/dtl', 'dojox/dtl/Context'], function(dtl, DtlContext){  var template = new dtl.Template("Hello {{ place }}!");  var context = new DtlContext({  place: "World" });  console.log(template.render(context));  return null;  }); 

可以看到,通過使用 dojox.dtl 提供的功能,就能夠在伺服器端將一個基於 DTL 模板的字串轉換成 HTML。dojox.dtl 實現了完整的 DTL 文法,結合 Node.js 的 HTTP 模組,就很容易建立一個自己的 Web Server,這在很大程度上得益於 Dojo 的 DTL 實現。

後記
有人曾預言 Node.js 將取代 PHP 成為最流行的伺服器端語言,無論您信不信,Node.js 正在快速的演變和發展,並獲得越來越多的關注。基於 Node.js 的一些 Web Server 已經可以用於商業用途,例如 http://expressjs.com。這讓 JavaScript 這個簡潔而優雅的語言發揮散發出越來越大的魅力。而 Dojo 作為一個功能強大的 JavaScript 架構,在企業級應用中一直備受青睞,藉助其對 Node.js 的完美支援,相信也能發揮出更大的作用。

本文首發於IBM Developerworks,原文地址:http://www.ibm.com/developerworks/cn/web/1203_wangpei_dojonodejs/

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.