25

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

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

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

这是我设想的目录结构:

 /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
    

这可能在节点中吗?配置它的正确方法是什么?

我开始如下:

/////////////
// 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 的新手

任何提示表示赞赏。

4

3 回答 3

10

您可以在从同一个脚本启动服务器和客户端时实例化一个connect(的核心)服务器实例,并让它将请求路由到url 开始的时间和其他地方。expressnode-staticpublicconnect

就像是

var connect = require('connect');
server = connect.createServer();
server.use('/public', client.handler_function);
server.use(server.express_handler_function);

应该做。您需要公开function(request, response)inclient.js以便可以通过它来引用它client.handler_function,并对 express 应用程序执行相同的操作(请参阅文档)。

例如,将函数置入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);

其他方法

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

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

  • 使用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)并喂它们来表达(查看有关如何执行此操作的 express 文档)。

评论

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

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

于 2013-01-14T01:08:19.983 回答
8

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

-client
-server
-node_modules
-app.js

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

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

node_modules显然是 Node 所需要的,最好留在项目的根目录,因为这样任何requiresserver都可以向上搜索项目文件夹层次结构,以在根目录找到这个通用的模块存储库

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

于 2013-09-28T18:50:24.570 回答
4

使用反向代理怎么样Nginx

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

http://wiki.nginx.org/Main

于 2013-01-14T01:27:38.950 回答