将js文件与html和node.js一起使用

10
我正在使用Websockets在运行于node.js的服务器和HTML5客户端之间进行消息传递。自然而然地选择JSON作为消息格式,并因此创建了通用JavaScript代码,定义了各种消息内容类型和转换操作。该JavaScript代码在两个项目之间共享。
我将网络客户端创建为一个git项目,将服务器创建为另一个git项目。部分原因是我使用phonegap构建基于webkit的客户端来适应各种触控环境。这也是各种逻辑的良好分离。
为了共享通用代码,我创建了一个单独的项目用于通用逻辑,并使用git的子项目将代码“导入”到其他两个项目中。
对于基于HTML5的项目,我可以通过以下方式直接包含代码,这个方法很好用:
<script src="common/js/comms.js" type="text/javascript"></script>

然而,使用Node时,我尝试获取代码时遇到了问题。最终,我做了如下操作来获取代码:

var fs = require('fs');
eval(fs.readFileSync('./common/js/comms.js').toString());

虽然我采用的方法是有效的,但当我有依赖关系时(例如,如果我想要a.js,则需要x.js、y.js和z.js),我注意到它变得非常混乱,而且对于每个想要使用这些实体中的任何一个的节点.js js文件,我都必须这样做。

我也不喜欢使用eval方法。我没有安全问题,但我想使用严格模式,我的理解是eval和严格模式像油和水一样不能混合使用。

那么我的问题是,什么是在HTML项目和node.js项目之间包含共享js文件的最佳方法?我希望使用符合strict的东西。

值得注意的是,虽然有几个问题围绕着这个主题,但我找不到任何一个可以解决我提出的具体问题。我还应该补充一点,就是我不希望从“服务器”中“提供”这些文件。 HTML5客户端是“独立”的。


为了澄清,我在“公共js文件”中有类似以下内容:

var Comms = function (options) {
   ...
}
在HTML5中,我可以通过new Comms()来引用它,这也是我想在node.js中做的。

可能是重复的问题,与https://dev59.com/emw05IYBdhLWcg3wUAQ0?rq=1相同。 - mpm
是的,我认为这些问题非常相似,并且我认为它肯定回答了他的问题。 - Ryan Smith
如果不行,你总是可以使用Grunt来合并文件。 - Ryan Smith
如果我在一个被HTML使用的JS文件中使用exports,会不会因为exports未定义而出现错误?@mpm这并不能解决我的问题,因为它会改变JS文件以适应Node.js,据我所知,这将导致它与HTML代码不兼容。 - Metalskin
2个回答

5
你了解Node模块如何工作吗?如果你正在使用这种模式进行开发,那么在服务器上使用require('./ common / js / comms')非常简单,同时也可以在客户端中包含它。
这篇文章应该会指引你正确的方向:https://caolan.org/posts/writing_for_node_and_the_browser.html
以下是泰勒在他的评论中链接的代码。
示例(example.js):
if(typeof exports == "undefined"){
    exports = this;
}

Example = function() {
    this.init();
};

Example.prototype = {
    init: function() {
         console.log('hello world');
    }
};

exports.Example = new Example();

example.js(app.js)的node.js使用方法:

example = require('./example');

example.js(index.html)的HTML用法:

<html>
    <head>
        <title></title>
    </head>
    <body>
        <script src="./example.js"></script>
    </body>

OP所做的更改是将exports.Example分配给Example,而不是新实例。因此,node.js逻辑可以使用以下内容:

var Example = require('./example.js').Example;
var foo = new Example();

因此,原始问题已得到解决。

谢谢Tyler,这很有帮助。我更新了我的问题以展示我目前正在做的事情。根据我给出的例子,那么我的html代码和node.js代码中的模块名称是否需要更改为new <modulename>.Comms()?在这种情况下,模块名称几乎总是与实体名称相同(因为我喜欢将所有内容分开到单独的js文件中),所以我最终会得到像new Foo.Foo()new Bar.Bar()这样的东西?如果是这样的话,那么这似乎有点奇怪。有没有办法解决这个问题? - Metalskin
这是一个带有快速示例的存储库:http://github.com/TylerLH/shared_module_example -- example.js 是模块,app.js 是需要它的 Node.js 脚本。index.html 只是使用简单的脚本标签来包含模块,该模块在全局命名空间中可访问。如果您想传递一些选项,您也可以等待实例化它。 - Tyler Hughes
1
谢谢你的快速示例,但对我来说它不起作用,因为我想要能够使用 var x = new Example()。然而,我认为你已经指引了我正确的方向,所以谢谢你。 - Metalskin
通过你的回复,我终于搞明白了。我的问题在于不理解Node中整个exports和import语句的行为。再次感谢Tyler,非常有帮助。顺便说一下,我正在编辑你的答案以包含你的代码。 :-) - Metalskin
糟糕,Caolan McMahon的链接失效了。这里有一个新的链接 - zipzit
显示剩余2条评论

1

看一下nodeJS模块

将会在comm.js中:

module.exports = function(/* any dependency? */){
   // things
   // you can return some object
}

您需要的文件是comm.js

require('./common/js/comm.js')();
// or you can assign it to a variable if it returned something

希望这能帮到你!

那么添加 module.exports 对包含在 HTML 中的 JS 不会造成问题吗? - Metalskin
首先测试模块是否已定义,然后导出你的模块,这是正确的做法。 - mpm
@Metalskin NodeJS 运行在服务器上。HTML 文件中的脚本在客户端运行。你不会在客户端包含服务器代码。相反,你可以从客户端向服务器代码发送消息,并解释结果。 - talabes
1
@talabes 编程中常见的一种方法是重复使用代码。当代码在不同项目之间是共同的时,一般的做法是编写库。无论是客户端还是服务器端,共同的代码都应该被重复使用,因此在每个项目之间进行共享。否则就会造成不稳定性,即当某人在 y 中更新代码时,如果忘记在 x 中更新代码,则会出现问题。 - Metalskin
@Metalskin,不需要提到DRY,你问的是module.exports是否会在HTML中引起问题,我只是回答“是”,因为module.exports来自node(服务器代码)。 - talabes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接