在 Node.js 上用 Dojo 做“面向對象 Web 應用”,核心不是把 Dojo 變成後端框架,而是把它當成一套可複用的 <span style="color:red">模塊體系</span> + <span style="color:red">類模型</span>:前後端共享同一套業務對象(DTO/校驗/權限規則),Node 負責 I/O(HTTP、文件、數據庫),Dojo 負責 <span style="color:red">AMD</span> 組織、依賴加載與 <span style="color:red">declare</span> 面向對象封裝。Dojo Toolkit 的最新穩定版本在官方下載頁標註為 <span style="color:red">1.17.3</span>。(Dojo Toolkit 下載) 這套打法屬於“穩、可控、便於漸進改造”的企業級路線。🚀
1)總體架構:用 Dojo 的 <span style="color:red">AMD Loader</span> 在 Node 裏跑 AMD 模塊
Dojo 的 Loader 原生支持 <span style="color:red">node 環境</span>,並通過配置把 loader 強制切到“無 DOM + host-node”模式。(Dojo Toolkit)
官方也明確:在 Node 裏應使用 <span style="color:red">源碼發行版</span>,而不是構建壓縮版,否則會因為“假設瀏覽器環境”導致不兼容。(Dojo Toolkit)
推薦目錄(最利於“共享業務層”)
src/app:前後端共享(領域模型、校驗、常量、序列化)src/app-server:僅服務端(路由、數據訪問、SSR)src/app-client:僅客户端(頁面、Widget、交互)
這一拆分與官方建議一致。(Dojo Toolkit)
2)Node 啓動引導:server.js 先把 Loader “立起來” 🧱
// server.js(項目根目錄)
// 1) 先定義全局 dojoConfig,讓 Dojo Loader 接管 AMD 世界
var loadModule = "app-server/server";
dojoConfig = {
baseUrl: "src/",
async: 1,
hasCache: {
"host-node": 1,
"dom": 0
},
packages: [
{ name: "dojo", location: "dojo" },
{ name: "app", location: "app" },
{ name: "app-server", location: "app-server" }
],
deps: [ loadModule ]
};
// 2) 再加載 Dojo Loader,本質是把 Node 的 require 變成 AMD require
require("./src/dojo/dojo.js");
逐段解釋(務必看懂這幾行,它決定你項目是否“可運維”):
loadModule:指定“服務端入口模塊”,交給deps自動引導加載。(Dojo Toolkit)dojoConfig.baseUrl:AMD 模塊的根路徑;你後續app/**都從這裏解析。(Dojo Toolkit)async: 1:切到 <span style="color:red">AMD 模式</span>(現代 Loader 行為);避免舊式同步加載陷阱。(Dojo Toolkit)hasCache.host-node/dom:明確運行時特徵:<span style="color:red">host-node=1</span>、<span style="color:red">dom=0</span>,防止模塊誤以為有瀏覽器 DOM。(Dojo Toolkit)packages:聲明命名空間到目錄的映射,企業項目裏這一步相當於“依賴治理的註冊表”。(Dojo Toolkit)- 最後一行
require("./src/dojo/dojo.js"):真正把 Loader 拉起;之後你寫的require([...], fn)都是 AMD 版本。(Dojo Toolkit)
3)在 Node 里加載原生模塊:用 <span style="color:red">dojo/node!</span> 橋接 CommonJS 🔌
AMD 環境下,Node 原生 require() 已被 AMD require 接管;要加載 Node 內置模塊,用 Dojo 的 AMD 插件 <span style="color:red">dojo/node</span>。(Dojo Toolkit)
// src/app-server/server.js
require([
"dojo/node!http",
"dojo/node!url"
], function (http, url) {
http.createServer(function (req, res) {
var u = url.parse(req.url, true);
res.writeHead(200, { "Content-Type": "application/json; charset=utf-8" });
res.end(JSON.stringify({ ok: true, path: u.pathname }));
}).listen(3000);
});
逐段解釋:
dojo/node!http/dojo/node!url:!後面跟的就是 Node 原生模塊名;Dojo 負責把它“注入”到 AMD 回調裏。(Dojo Toolkit)createServer:保持 Node I/O 能力;Dojo 不替你做網絡棧,它只負責讓模塊體系一致。- 返回 JSON:這是最小可運行的“Web 應用骨架”。如果你後續接數據庫、鑑權、限流,都可以繼續用 Dojo 組織模塊、用 Node 執行 I/O。
(一句實話:把 Dojo 當後端 MVC 用會很擰巴;把它當“共享業務層 + 統一模塊化”就很香。)
4)面向對象建模:用 <span style="color:red">dojo/_base/declare</span> 做領域對象(可前後端複用) ✅
下面示例把“用户對象”做成可複用類,既能在瀏覽器用,也能在 Node 用。
// src/app/model/User.js
define([ "dojo/_base/declare" ], function (declare) {
return declare(null, {
id: null,
name: "",
constructor: function (args) {
args = args || {};
this.id = args.id || null;
this.name = args.name || "";
},
isValid: function () {
return !!this.id && this.name.length >= 2;
}
});
});
逐段解釋:
define([...], fn):AMD 定義模塊,保證同一份代碼可被 Loader 在不同環境加載。(Dojo Toolkit)declare(null, {...}):創建“類”;null表示無父類(也可傳 mixin/父類實現繼承)。constructor(args):統一對象裝配入口,企業項目裏相當於“領域對象的裝配器”。isValid():把校驗邏輯內聚到模型裏;你在 Node 的 API 校驗、在前端表單校驗都能複用,減少“雙寫”和口徑不一致。
5)工作流程圖:一眼看懂“Dojo in Node”的運行鏈路 🧠
原理解釋表:你真正需要掌握的“關鍵控制點”
| 控制點 | 作用 | 你要堅持的口徑 |
|---|---|---|
| <span style="color:red">async:1</span> | 切到 AMD 模式,依賴異步加載,避免舊式同步模式副作用 (Dojo Toolkit) | 生產統一啓用 |
| <span style="color:red">host-node</span> + <span style="color:red">dom:0</span> | 明確在 Node 且無 DOM,避免加載到瀏覽器假設代碼 (Dojo Toolkit) | 服務端必設 |
| <span style="color:red">packages</span> | 模塊命名空間治理(依賴可控、結構可維護)(Dojo Toolkit) | 顯式聲明,不靠隱式路徑 |
| <span style="color:red">dojo/node!</span> | 在 AMD 世界裏加載 Node CommonJS 模塊 (Dojo Toolkit) | 統一用插件,不混寫原生 require |
| <span style="color:red">app/app-server/app-client</span> | 分層讓共享代碼“可複用、可構建、可發佈”(Dojo Toolkit) | 共享邏輯只放 app |
最後給你一句務實建議
如果你的目標是“快速交付現代前端”,Dojo Toolkit 這條線更適合“存量系統演進、需要強一致業務模型複用”的場景;你把共享域模型做紮實了,後續不管前端換殼還是服務端換框架,資產都不會白做。😄(代碼能複用的,才算資產;只能跑起來的,叫演示。)
如果你願意,我可以按你現有項目(比如控制枱、API、鑑權、日誌)給你一套“Dojo 模塊分層 + OOP 領域模型規範 + Node 入口引導模板”,讓團隊後續擴展不再靠“拍腦袋”。