我正在开发一个针对浏览器和NodeJS应用程序的库。模块使用AMD惯例,这在理论上足够灵活,几乎可以映射到今天的任何情况。然后使用工具转换源文件,以便为不同的平台 - 浏览器和NodeJS分发。 顺便说一下,有一个很棒的工具叫uRequire来帮助解决这个问题,但我仍然不确定我的最佳选择是什么,所以我在这里要求相关的经验。
以下是我拥有的文件层次结构:
- 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”; EventEmitter
来自require("events").EventEmitter
,events
是本地包,而不是本地文件或模块; 所以,我的问题是:如何在不进行大规模修改的情况下让Observable
对象与NodeJS一起使用?我不确定如何使EventEmitter
实现可用于我的模块,因为它不是本地模块(因此我不能写任何路径映射)而且它不是直接模块本身我们'我会使用它的“EventEmitter”属性......
任何帮助/思考都将不胜感激。我相信很多人都遇到过类似的情况,我很想知道他们要说些什么!
答案 0 :(得分:1)
uRequire使得使用runtimeInfo并在运行时选择性地加载替代依赖项变得微不足道(如果你不这样做,你总是可以选择在构建时使用替代版本和replace deps with alternative/mocks想写这样的选择性代码)。
Runtime info在所有模板中的工作方式相同,包括UMD和combined,因此,如果在以下位置执行:
nodejs
浏览器
浏览器,内容为</script>
标记,
您可以使用__isAMD
,__isNode
&amp;运动来动态选择每种模块依赖关系在每种情况下的含义。 __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;
}
}
});
**笔记**:
您不必担心"events"
尝试加载AMD端,导致其known node dep (otherwise you would need to list it)。
EventEmitter2 = require(...)
需要建立 inference of exported dependency identifier EventEmitter2
到window
。最后一种情况,Web / Script使用window.EventEmitter2
,这要归功于此!您也可以list it in depsVars。
然后使用以下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
内嵌所有文件&amp;拥有自己的迷你加载器(almond),适用于nodejs,Web / AMD和Web / Script。从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
中查看测试项目