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

IT技术 javascript node.js
2021-01-14 13:34:31

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

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

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

我还尝试使用 JS.Class 来获得更严格的 OO 模型,但我放弃了,因为我无法弄清楚如何让提供的 JavaScript 文件与 require() 一起使用。我在这里遗漏了什么吗?

6个回答

如果你想编写一个可以同时使用客户端和服务器端的module,我有一篇关于快速简便方法的简短博客文章:为 Node.js 和浏览器编写,本质如下(this与 相同window) :

(function(exports){

    // Your code goes here

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

})(typeof exports === 'undefined'? this['mymodule']={}: exports);

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

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

双子座链接已死。
2021-03-16 13:34:31
真的很棒的文章草栏。我明白了,它奏效了,现在我又开始了。极好的!
2021-03-31 13:34:31
在自己的项目中使用RequireJs,这将允许我在客户端和服务器上共享我的module。我们会看看它是如何运作的。
2021-03-31 13:34:31
当现有网站有一个全局计数器时会发生什么window.exports = 123;我不确定测试typeof .. 'undefined'是否是最好的方法,测试阳性案例会更好吗?
2021-04-02 13:34:31
优秀的。谢谢你的信息,曹兰。
2021-04-08 13:34:31

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));

在服务器端只需使用:

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

share.test();

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

share.test();
@broesch 这在 ES6 中如何工作?我已经将此作为一个新问题提出来了,有一些 ES6 特定的问题,但我很高兴在这里看到编辑!
2021-03-23 13:34:31
我比接受的答案更喜欢这个答案,因为它为像我这样的新手解释得更好。
2021-03-24 13:34:31
这个解决方案 + git subtree == 很棒。谢谢!
2021-04-10 13:34:31
在我的 Express 文件夹中,除了静态(公共)文件夹之外,我还有一个名为“共享”的文件夹,它也可以从客户端访问,就像“公共”文件夹一样: app.use(express.static('public')) ; app.use(express.static('shared')); 您的帖子扩展了我与客户端和服务器共享文件的想法。这正是我所需要的。谢谢!
2021-04-11 13:34:31

查看在 Node.js module模式、AMD module模式和浏览器中全局运行的 jQuery 源代码:

(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)
这是最好的方法(对于我需要的)。这是我创建的一个工作示例:gist.github.com/drmikecrowe/4bf0938ea73bf704790f
2021-03-13 13:34:31

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

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

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

我从未想过将 javascript 函数序列化为字符串。谢谢你的提示。
2021-03-13 13:34:31

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

有异步库
2021-03-27 13:34:31