如何在Node.js和浏览器之间共享代码?

Sim*_*ave 236 javascript node.js

我正在使用JavaScript客户端(在浏览器中运行)和Node.js服务器创建一个小应用程序,使用WebSocket进行通信.

我想在客户端和服务器之间共享代码.我刚刚开始使用Node.js,至少可以说,我对现代JavaScript的了解有点生疏.所以我仍然围绕CommonJS的require()函数.如果我使用'export'对象创建我的包,那么我无法看到如何在浏览器中使用相同的JavaScript文件.

我想创建一组在两端使用的方法和类,以便于编码和解码消息,以及其他镜像任务.但是,Node.js/CommonJS打包系统似乎阻止我创建可以在双方使用的JavaScript文件.

我也尝试使用JS.Class来获得更紧密的OO模型,但我放弃了,因为我无法弄清楚如何让提供的JavaScript文件与require()一起使用.这里有什么我想念的吗?

Cao*_*lan 166

如果你想编写一个可以在客户端和服务器端使用的模块,我有一个简短的博客文章,快速简单的方法:编写Node.js和浏览器,基本上如下(其中this相同window) :

(function(exports){

    // Your code goes here

   exports.test = function(){
        return 'hello world'
    };

})(typeof exports === 'undefined'? this['mymodule']={}: exports);
Run Code Online (Sandbox Code Playgroud)

或者,有一些项目旨在在客户端实现Node.js API,例如Marak的gemini.

您可能还对DNode感兴趣,它允许您公开JavaScript函数,以便可以使用简单的基于JSON的网络协议从另一台计算机调用它.

  • @Caolan那个链接已经死了 (5认同)
  • 双子座的链接已经死了. (5认同)
  • 真的很棒的文章曹兰.我理解它,它有效,现在我再次滚动.太棒了! (2认同)
  • 我在自己的项目中使用[RequireJs](http://requirejs.org/docs/node.html),这将允许我在客户端和服务器上共享我的模块.我们会看到它是如何运作的. (2认同)

小智 43

Epeli在这里提供了一个很好的解决方案http://epeli.github.com/piler/即使没有库也可以使用,只需将其放在名为share.js的文件中即可.

(function(exports){

  exports.test = function(){
       return 'This is a function from shared module';
  };

}(typeof exports === 'undefined' ? this.share = {} : exports));
Run Code Online (Sandbox Code Playgroud)

在服务器端只需使用:

var share = require('./share.js');

share.test();
Run Code Online (Sandbox Code Playgroud)

在客户端只需加载js文件然后使用

share.test();
Run Code Online (Sandbox Code Playgroud)

  • 我比这个答案更喜欢这个答案,因为对于像我这样的新手来说,这个答案会更好. (10认同)

wli*_*gke 14

检查jQuery源代码,使其在Node.js模块模式,AMD模块模式和浏览器中的全局工作:

(function(window){
    var jQuery = 'blah';

    if (typeof module === "object" && module && typeof module.exports === "object") {

        // Expose jQuery as module.exports in loaders that implement the Node
        // module pattern (including browserify). Do not create the global, since
        // the user will be storing it themselves locally, and globals are frowned
        // upon in the Node module world.
        module.exports = jQuery;
    }
    else {
        // Otherwise expose jQuery to the global object as usual
        window.jQuery = window.$ = jQuery;

        // Register as a named AMD module, since jQuery can be concatenated with other
        // files that may use define, but not via a proper concatenation script that
        // understands anonymous AMD modules. A named AMD is safest and most robust
        // way to register. Lowercase jquery is used because AMD module names are
        // derived from file names, and jQuery is normally delivered in a lowercase
        // file name. Do this after creating the global so that if an AMD module wants
        // to call noConflict to hide this version of jQuery, it will work.
        if (typeof define === "function" && define.amd) {
            define("jquery", [], function () { return jQuery; });
        }
    }
})(this)
Run Code Online (Sandbox Code Playgroud)

  • 这是最好的方法(满足我的需要)。这是我创建的一个工作示例:https://gist.github.com/drmikecrowe/4bf0938ea73bf704790f (2认同)

Dag*_*bit 13

不要忘记JavaScript函数的字符串表示形式表示该函数的源代码.您可以简单地以封装的方式编写函数和构造函数,以便它们可以是toString()并发送到客户端.

另一种方法是使用构建系统,将公共代码放在单独的文件中,然后将它们包含在服务器和客户端脚本中.我正在通过WebSockets将这种方法用于简单的客户端/服务器游戏,其中服务器和客户端基本上运行相同的游戏循环,并且客户端每次打勾都与服务器同步以确保没有人作弊.

我的游戏构建系统是一个简单的Bash脚本,它通过C预处理器运行文件,然后通过sed来清理一些垃圾cpp离开,所以我可以使用所有正常的预处理器东西,如#include,#define,#ifdef等

  • 将javascript函数序列化为字符串从未发生过.谢谢你的提示. (2认同)

Hus*_*sky 13

我建议查看Node.jsRequireJS适配器.问题是默认情况下Node.js使用的CommonJS模块模式不是异步的,这会阻止在Web浏览器中加载.RequireJS使用AMD模式,只要您使用r.js适配器,它就是异步的并且兼容服务器和客户端.


Mar*_*son 11

也许这不完全符合这个问题,但我想我会分享这个.

我想制作几个简单的字符串实用程序函数,在String.prototype上声明,可用于节点和浏览器.我只是将这些函数保存在一个名为utilities.js的文件中(在子文件夹中),并且可以从我的浏览器代码中的脚本标记和我的Node.js脚本中使用require(省略.js扩展名)轻松引用它. :

my_node_script.js

var utilities = require('./static/js/utilities')
Run Code Online (Sandbox Code Playgroud)

my_browser_code.html

<script src="/static/js/utilities.js"></script>
Run Code Online (Sandbox Code Playgroud)

我希望这对我以外的人有用.


Yuc*_*uci 6

如果使用webpack之类的模块捆绑器捆绑JavaScript文件供浏览器使用,则只需将Node.js模块重用于浏览器中运行的前端即可。换句话说,您的Node.js模块可以在Node.js和浏览器之间共享。

例如,您具有以下代码sum.js:

普通的Node.js模块:sum.js

const sum = (a, b) => {
    return a + b
}

module.exports = sum
Run Code Online (Sandbox Code Playgroud)

使用Node.js中的模块

const sum = require('path-to-sum.js')
console.log('Sum of 2 and 5: ', sum(2, 5)) // Sum of 2 and 5:  7
Run Code Online (Sandbox Code Playgroud)

在前端重用

import sum from 'path-to-sum.js'
console.log('Sum of 2 and 5: ', sum(2, 5)) // Sum of 2 and 5:  7
Run Code Online (Sandbox Code Playgroud)