首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >NodeJS/浏览器交叉开发

NodeJS/浏览器交叉开发
EN

Stack Overflow用户
提问于 2014-03-19 16:38:46
回答 1查看 1K关注 0票数 2

我正在开发一个针对浏览器和NodeJS应用程序的库。模块使用AMD公约,这是足够灵活的理论,以地图几乎任何今天的情况。然后将源文件与要分发给不同平台的工具进行转换--再一次使用浏览器和NodeJS。顺便说一句,有一个很棒的工具叫做uRequire来帮助它,但是我仍然不知道我最好的选择是什么,所以我在这里询问相关的经验。

下面是我的文件层次结构:

代码语言:javascript
复制
- 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端:EventEmitter是从require("events").EventEmitter获得的,events是一个本地包,而不是本地文件或模块;

所以,我的问题是:我如何让Observable对象在不进行大规模修补的情况下与NodeJS一起工作?我不确定如何使模块可以使用EventEmitter实现,因为它不是本地模块(因此我不能编写任何路径映射),而且它不是我们将要使用的模块本身,而是它的"EventEmitter“属性.

任何帮助/思考都将不胜感激。我相信很多人在类似的情况下跑步,我很想知道他们要说些什么!

EN

回答 1

Stack Overflow用户

发布于 2014-04-11 12:45:22

uRequire使得在运行时使用runtimeInfo并选择性地加载替代依赖项变得非常简单(如果不想编写这样的选择性代码,则始终可以选择在构建时使用替代构建和http://urequire.org/masterdefaultsconfig.coffee#bundle.dependencies.replace )。

运行时信息在所有模板(包括UMD组合 )中的工作方式相同,因此,如果在以下两种模板上执行:

  • nodejs
  • 带有AMD加载程序的浏览器,如所需
  • 带有普通标记的</script>浏览器

您可以使用__isAMD__isNode__isWeb运行时变量动态地选择每个模块依赖项在每种情况下的含义。

你需要的是:

代码语言:javascript
复制
- bower_components/
    - eventemitter2/ ...
    - lodash/ ...
    - requirejs/ ...

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

例如,Observable.js在哪里

代码语言:javascript
复制
define(["lodash", "EventEmitter"], function(_, EventEmitter) {
  function Observable(options) { this.myOptions = options };

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

EventEmitter.js是:

代码语言:javascript
复制
define(function(){
  var EventEmitter2;
  if (__isNode) {
    return require("events").EventEmitter;
  } else {
    if (__isAMD) {
      return EventEmitter2 = require("eventemitter2"); 
    } else if (__isWeb) {
      return window.EventEmitter2;
    }
  }
});

**附注**:

  • 您不需要担心"events"试图加载在AMD方面,因为它是一个已知的节点dep (否则您需要列出它)
  • 需要EventEmitter2 = require(...)来建立导出依赖标识符的推断 EventEmitter2 to window。最后一种情况是,由于这一点,Web/脚本使用了window.EventEmitter2!或者,您可以使用在depsVars中列出它

然后使用以下咕噜声配置(在coffeescript中):

代码语言:javascript
复制
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运行):

代码语言:javascript
复制
var Observable = require("../../build/UMD/Observable");
console.log(Observable.EventEmitter);

或来自浏览器(source/test/Loader_unoptimized_AMD.html):

代码语言:javascript
复制
<!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、Web/AMD和Web/Script上工作。从source/test/Loader_almondJs_plainScript.html运行:

代码语言:javascript
复制
<!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):

代码语言:javascript
复制
<!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中看到测试项目。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22512486

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档