分离Node.js服务器和客户端

时间:2013-01-14 00:30:49

标签: node.js express

假设我正在编写一个带有服务器和客户端的Web应用程序。

  • 服务器用作API,并使用express框架。
  • 客户端只是一个提供静态javascript / html文件的node-static应用。

我希望能够单独部署它们,彼此独立地部署它们 - 或者两者同时部署它们。

以下是我设想目录结构的方法:

 /my-app
     app.js
     /server
         server.js
     /client
         client.js

我希望能够以3种不同的方式运行它:

  1. 在某个端口(比如3000)上运行服务器(API):

    my-app/server> node server.js
    ...Server listening on localhost:3000/api
    
  2. 只运行客户端(即从/ client目录提供静态文件):

    my-app/client> node client.js
    ...Server listening on localhost:4000/client
    
  3. 在同一端口上运行服务器和客户端(通过单个node.js实例):

    my-app> node app.js
    ...Server listening on localhost:5000
    
  4. 这可能在节点中,配置它的正确方法是什么?

    我开始如下:

    /////////////
    // server.js
    /////////////
    // Run the server if this file is run as script
    if(module.parent){
       app.listen("3000/client")  
    }
    
    /////////////
    // client.js
    /////////////
    var static = require('node-static');
    var file = new(static.Server)('.');
    var app = require('http').createServer(function (request, response) {
      request.addListener('end', function () {
        file.serve(request, response);
      });
    });
    if(module.parent){
       app.listen("4000/client");
    }
    
    /////////////
    // app.js
    /////////////
    server = require("server/server.js")
    server.app.listen("5000/api")
    
    client = require("client/client.js")
    client.app.listen("5000/client")  <--- ?????
    

    我不确定如何在我的 app.js 中连接客户端服务器,以便它们都可以同时提供端口/进程/线程等...

    注意:请原谅代码,它未经过测试,可能不正确。我是node.js的新手

    任何提示赞赏。

3 个答案:

答案 0 :(得分:8)

当您从同一个脚本启动服务器和客户端时,您可以实例化connectexpress)服务器实例的内容,并将请求路由到node-static网址以public开头,否则以connect开头。

这样的东西
var connect = require('connect');
server = connect.createServer();
server.use('/public', client.handler_function);
server.use(server.express_handler_function);

应该这样做。您需要在function(request, response)中公开client.js,以便可以通过client.handler_function引用它,并对快速应用执行相同操作(请参阅文档)。

例如,在client.js中设置函数会涉及到:

var static = require('node-static');
var file = new(static.Server)('.');
var handler = function (request, response) {
  request.addListener('end', function () {
    file.serve(request, response);
  });
};
var app = require('http').createServer(handler);
if(module.parent){
   app.listen(4000);
   console.log("Server (static) listening on 4000")
}
module.exports = { handler_function: handler };

这样你就可以通过以下方式进入handler

var client = require('client'); // this returns the object you've set to `module.exports` in `client.js`
[...]
server.use('/public', client.handler_function);

其他方法

我上面详述的内容似乎与您想要的最接近(基于您上次编辑中的说明)。不过还有其他选择:

  • 保留基于网站根目录的静态和快速生成的网址,例如example.com/a_statically_served_script.jsexample.com/api_endpoint;首先尝试提供静态文件,如果找不到,则将请求发送到基于快速的应用程序

  • 使用app.js脚本启动不同端口(或unix域套接字)上的两台服务器并使用node-proxy(或类似的东西,甚至nginx / apache作为反向代理)他们面前

相同的根

对于第一种方法,您需要向file.serve添加错误处理程序,例如

file.serve(request, response, function(e, res) {
    if (e && (e.status == 404)) {
        // if the file wasn't found
        if (next) {
            next(request, response);
        }
    }
}

next应该是client.js脚本中的一个变量,在脚本直接运行时未设置,但是在需要脚本时(请查看有关模块和导出的文档)在节点工作中) - 设置时,next引用一个函数,它接受(req, res)并将它们提供给它们表达(看看如何做的快速文档)。

说明

请记住,这不是一个详尽的答案:它只是关于要查找哪些文档以及可以使用哪些技术来解决问题的一堆指示。

值得记住的是,在节点中,请求处理程序通常由function(request, response)表示和实现。这个习惯用法在connect / express扩展到funciton(request, response, next):此处next表示安装的处理程序链中的下一个可用处理程序(function(request, response)形式)通过server.use(handler)到服务器。

答案 1 :(得分:8)

我对OP有类似的要求,但不需要单独执行子部分...我只想要单独的文件夹,因为我不喜欢在服务器的代码文件夹中嵌套客户端代码。从技术上讲,这是不可能避免这样做的,所以我在文件系统中创建了一个抽象级别来缓解我困扰的灵魂。这是我项目的根源:

-client
-server
-node_modules
-app.js

client包含public通常会提供的所有内容(所有客户端文件都要提供),即至少index.html

server可能是也可能不是Node模块(在我的情况下,它不一定是)。这是您的应用程序特定的服务器代码。您可以重新require与基础app.js中相同的文件,因为它不会有任何区别,并且可以正常工作。

Node显然需要

node_modules,最好留在项目的根目录,因为require中的任何server都可以向上搜索项目文件夹层次结构find this common repository of modules at the root

app.js只包含以下内容:

var path = require('path');
var express = require('express');
app = express();
require('./server/server.js');

app.use(express.directory(path.join(__dirname, '/'))); //optional, directory browsing
app.use(express.static(path.join(__dirname, '/')));
app.use(express.errorHandler());

app.listen(process.env.PORT || 5000);

...正如您所看到的,根脚本中的代码很少。一切都非常重要,特定于应用程序

请注意,使用app声明变量var 。通过避免var,我们将其设为全局,并允许在server.js内进行访问,而无需进一步操作。

所以,如果还不清楚的话,你会node app让它运行起来。

答案 2 :(得分:4)

如何使用Nginx等反向代理?

您可以轻松地在一个端口绑定两个节点应用程序,还有许多其他优势。

http://wiki.nginx.org/Main