2014-03-19 44 views
1

我正在研究面向瀏覽器和NodeJS應用程序的庫。模塊使用AMD慣例,它在理論上足夠靈活,足以映射今天的任何情況。源文件隨後將被轉換爲工具,以便分發給不同的平臺 - 再次是瀏覽器和NodeJS。 順便說一句,有一個很棒的工具叫做uRequire來幫助解決這個問題,但我仍然不確定我的最佳選擇是什麼,所以我在這裏要求相關經驗。NodeJS /瀏覽器交叉開發

以下是文件的層次結構,我有:

- bower_components/ 
    - eventemitter2/ ... 
    - lodash/ ... 

- source/ 
    - library/ 
     - lodash.js -> ../../bower_components/lodash/dist/lodash.js 
     - EventEmitter.js -> ../../bower_components/eventemitter2/lib/eventemitter2.js 

    - Observable.js: 

     define(["lodash", "EventEmitter"], function(Utility, EventEmitter) { 
      function Observable(options) { ... }; 

      return Observable; 
     }); 

最後,瀏覽器和的NodeJS雙方之間的最大區別在於:

  • 瀏覽器端:EventEmitter實現僅僅是eventemitter2瀏覽器被配置爲「library/EventEmitter」的模塊;
  • NodeJS端:EventEmitterrequire("events").EventEmitter獲得,events是本地包,而不是本地文件或模塊;

所以,我的問題是:我該如何使Observable對象與NodeJS一起工作,而無需大量修補?我不知道如何使EventEmitter實現可用於我的模塊,因爲它不是本地模塊(因此我不能寫任何路徑映射),而且它不是直接使用我們將使用的模塊,而是它的「EventEmitter」屬性...

任何幫助/思想,將不勝感激。我相信很多人都遇到類似的情況,我很想知道他們要說些什麼!

+1

考慮使用Browserify。它具有與Node.js模塊兼容的瀏覽器模塊。 – Brad

+1

這是一個很簡短的答案...... :) 你如何處理不同的實現例如XMLHttpRequest在一方和「http」模塊在另一方,例如? –

+0

這些情況非常棘手,需要在代碼中處理。雖然沒有銀彈。 Browserify可以讓你在那裏找到大部分路徑(在某些模塊中,所有的路都在那裏)。 – Brad

回答

1

uRequire可以輕鬆地將使用runtimeInfo和selectivelly在運行時加載替換的相依(你可以隨時選擇有替代構建和replace deps with alternative/mocks在編譯的時候,如果你不想寫這樣選擇的代碼)。

Runtime info適用於所有的模板,包括UMDcombined一樣的,所以無論是如果執行上:與AMD裝載機像requirejs

  • 的NodeJS

  • 瀏覽器

  • 瀏覽器與普通</script>標籤,

你可以選擇每個模塊的依賴性在每種情況下是指動態地,使用__isAMD__isNode & __isWeb運行時變量。

你需要的是:

- bower_components/ 
    - eventemitter2/ ... 
    - lodash/ ... 
    - requirejs/ ... 

- source/ 
    - library/ 
     - EventEmitter.js  
     - Observable.js: 

其中Observable.js是例如

define(["lodash", "EventEmitter"], function(_, EventEmitter) { 
    function Observable(options) { this.myOptions = options }; 

    Observable.EventEmitter = EventEmitter; 
    Observable._ = _; 
    return Observable; 
}); 

EventEmitter.js是:

define(function(){ 
    var EventEmitter2; 
    if (__isNode) { 
    return require("events").EventEmitter; 
    } else { 
    if (__isAMD) { 
     return EventEmitter2 = require("eventemitter2"); 
    } else if (__isWeb) { 
     return window.EventEmitter2; 
    } 
    } 
}); 

**說明**:

具有以下 grunt-urequire配置(在CoffeeScript中)

然後:

module.exports = gruntFunction = (grunt) -> 

    grunt.initConfig gruntConfig = 
    urequire: 
     library: 
     path: "source/library" 
     dstPath: "build/UMD" 
     runtimeInfo: ['EventEmitter'] # dont need it in other files 
     template: 'UMDplain' 

     combined: 
     derive: 'library' 
     main: 'Observable' 
     dependencies: exports: root: {'Observable': 'Obs'} 
     dstPath: "build/almond/Observable.js" 
     template: 'combined' 

    grunt.loadNpmTasks "grunt-urequire" 

你有兩個版本:

A)library:有獨立的UMD文件,在那裏你可以運行,例如從source\test\load_node.js

var Observable = require("../../build/UMD/Observable"); 
console.log(Observable.EventEmitter); 

或來自瀏覽器(source/test/Loader_unoptimized_AMD.html):

<!DOCTYPE html> 
<html> 
    <head><title>test crossdev: RequireJs, UMD</title></head> 
    <body>Check console!</body> 

    <script src="../../bower_components/requirejs/require.js"></script> 
    <script> 
    require.config ({ 
     baseUrl: '../../build/almond', 
     paths: { 
     lodash: "../../bower_components/lodash/dist/lodash.min", 
     eventemitter2: "../../bower_components/eventemitter2/lib/eventemitter2" 
     } 
    }); 

    require(["Observable" ], function(Observable){ 
     console.log(Observable); 
     console.log(Observable.EventEmitter); 
    }); 

    </script> 
</html> 

B)combined所有文件內聯&具有上的NodeJS,網絡/ AMD和Web /腳本作品自身的小型裝載機(almond)。從source/test/Loader_almondJs_plainScript.html運行:

<!DOCTYPE html> 
<html> 
    <head><title>test crossdev: plain script, combined/almond</title></head> 
    <body>Check console!</body> 

    <script src="../../bower_components/lodash/dist/lodash.min.js"></script> 
    <script src="../../bower_components/eventemitter2/lib/eventemitter2.js"></script> 
    <script src="../../build/almond/Observable.js"></script> 

    <script> 
    console.log(window.Obs); 
    console.log(window.Obs.EventEmitter); 
    </script> 
</html> 

或使用RequireJs作爲AMD裝載機(source/test/Loader_almondJs_AMD.html):

<!DOCTYPE html> 
<html> 
    <head><title>test crossdev: RequireJs, combined/almond</title></head> 
    <body>Check console!</body> 

    <script src="../../bower_components/requirejs/require.js"></script> 
    <script> 
    require.config ({ 
     baseUrl: '../../build/almond', 
     paths: { 
     lodash: "../../bower_components/lodash/dist/lodash.min", 
     eventemitter2: "../../bower_components/eventemitter2/lib/eventemitter2" 
     } 
    }); 

    require(["Observable" ], function(Observable){ 
     console.log(Observable); 
     console.log(Observable.EventEmitter); 
    }); 

    </script> 
</html> 

您可以看到測試項目https://github.com/anodynos/nodejs-browser-cross-development