交叉共享/浏览器开发的最佳实践

时间:2011-07-12 14:26:54

标签: javascript node.js cross-platform commonjs

目前,我通过Google Closure Compiler使用definesIS_CJS一行IS_BROWSER,并且只有不同的文件构建(browser.myproject.jscjs.myproject.js等。)

这是标准的做事方式吗?如果没有,它是什么,有什么优势?

3 个答案:

答案 0 :(得分:2)

我一直在我的所有项目中使用以下序言,对于由浏览器和服务器代码加载的库:

if (define === undefined) {
    var define = function(f) {
            require.paths.unshift('.');
            f(require, exports, module);
        };
}

define(function(require, exports, module) {
    ...
    // main library here
    ...
    // use require to import dependencies
    var v = require(something);
    ...
    // use exports to return library functions
    exports.<stuff> = { some stuff };
    ...
});

这适用于在我的节点服务器上运行require(<library>)调用加载库,以及require(<library>)RequireJS调用。在浏览器上,嵌套require调用在库执行之前由RequireJS预先获取,在节点上同步加载这些依赖项。由于我没有将我的库用作独立脚本(通过html中的脚本标记),并且仅作为通过脚本标记加载的脚本的依赖项,因此这对我很有用。


然而,看看独立的库,看起来下面的序言似乎是最灵活的。 (来自Q promise库的剪切和粘贴

(function (definition, undefined) {

    // This file will function properly as a <script> tag, or a module
    // using CommonJS and NodeJS or RequireJS module formats.  In
    // Common/Node/RequireJS, the module exports the Q API and when
    // executed as a simple <script>, it creates a Q global instead.

    // The use of "undefined" in the arguments is a
    // micro-optmization for compression systems, permitting
    // every occurrence of the "undefined" variable to be
    // replaced with a single-character.

    // RequireJS
    if (typeof define === "function") {
        define(function (require, exports, module) {
            definition(require, exports, module);
        });
    // CommonJS
    } else if (typeof exports === "object") {
        definition(require, exports, module);
    // <script>
    } else {
        Q = definition(undefined, {}, {});
    }

})(function (serverSideRequire, exports, module, undefined) {

    ...
    main library here
    ... 


/*
 * In module systems that support ``module.exports`` assignment or exports
 * return, allow the ``ref`` function to be used as the ``Q`` constructor
 * exported by the "q" module.
 */
for (var name in exports)
    ref[name] = exports[name];
module.exports = ref;
return ref;

});

虽然罗嗦,但它具有令人印象深刻的灵活性,而只需,无论您的执行环境是什么。

答案 1 :(得分:1)

您可以使用uRequire通过模板系统将AMD或CommonJS中编写的模块转换为AMD,CommonJS或UMD。

可选uRequire将整个包构建为combinedFile.js,在所有环境(nodejs,AMD或无模块浏览器&lt; script /&gt;)中运行,使用rjs优化器和almond引擎盖

uRequire 使您不必在每个模块中维护任何样板 - 只需编写普通的AMD或CommonJS模块(如.js,.coffee,.coco,.ls等),而不需要噱头。

另外,您可以声明性地将标准功能(例如exporting a module)添加到全局,例如window.myModule以及noConflict()方法,或者runtimeInfo (eg __isNode, __isAMD) selectively或替换/删除/注入构建时的依赖性,自动缩小,操作模块代码等等。

所有这些configuration options都可以打开或关闭每个模块或每个模块,并且您可以拥有彼此派生(继承)的不同构建配置文件(开发,测试,生产等)。

通过grunt-urequire或独立版本可以很好地使用grunt,并且它有一个很好的watch选项,可以仅重建已更改的文件。

答案 2 :(得分:0)

你试过这个:https://github.com/medikoo/modules-webmake#modules-webmake

这是我正在采取的方法,而且效果非常好。代码中没有样板,您可以在服务器端和客户端上运行相同的模块