Разделение Node.js сервера и клиента - программирование
Подтвердить что ты не робот

Разделение Node.js сервера и клиента

Скажем, я пишу веб-приложение с сервером и клиентом.

  • сервер функционирует как API и использует express framework.
  • клиент - это просто приложение node-static, которое обслуживает статические файлы javascript/html.

Я хочу иметь возможность развернуть их отдельно, независимо друг от друга, или одновременно в обоих случаях.

Вот как я представляю структуру каталогов:

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

Я хотел бы иметь возможность запускать это тремя способами:

  • Запустите сервер (API) на каком-либо порту (скажем 3000):

    my-app/server> node server.js
    ...Server listening on localhost:3000/api
    
  • Запустите только клиент (т.е. выполните статические файлы из каталога/клиента):

    my-app/client> node client.js
    ...Server listening on localhost:4000/client
    
  • Запустите сервер и клиент на одном и том же порту (одним экземпляром node.js):

    my-app> node app.js
    ...Server listening on localhost:5000
    

Возможно ли это в node и как правильно его настроить?

Я начал следующим образом:

/////////////
// 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

Любые советы оценены.

4b9b3361

Ответ 1

Вы можете создать экземпляр connect (кишки express) при запуске как сервера, так и клиента из того же script и запросите маршрут node-static, когда URL начинается с 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);

Другие подходы

То, что я подробно рассмотрел выше, похоже, наиболее близко к тому, что вы хотите (на основе пояснения в вашем последнем редактировании). Существуют и другие варианты:

  • сохранять статические и выраженные URL-адреса, основанные на корне сайта, такие как example.com/a_statically_served_script.js и example.com/api_endpoint; сначала пытается выполнить статический файл, если его невозможно найти, вы отправите запрос в экспресс-приложение

  • используйте app.js script, чтобы запустить оба сервера на разных портах (или сокетах 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 script, которая не устанавливается, когда script запускается напрямую, но это когда требуется script (посмотрите на документацию о том, как модули и экспортируется в node) - когда установлено, next ссылается на функцию, которая принимает (req, res) и передает их для выражения (посмотрите на экспресс-документы о том, как это сделать).

Примечания

Имейте в виду, что это не исчерпывающий ответ: это всего лишь куча указателей на то, какую документацию искать и какие методы вы могли бы использовать для решения проблем.

Что-то стоит вспомнить, так как чаще всего в node обработчик запроса представлен и реализуется function(request, response). Эта идиома расширяется в connect/express до funciton(request, response, next): здесь next представляет следующий доступный обработчик (формы function(request, response)) в цепочке обработчиков, установленных на сервере через server.use(handler).

Ответ 2

У меня были аналогичные требования к OP, но мне не нужно было выполнять отдельные подразделы... Мне нужны только отдельные папки, так как мне не нравится вложенный клиентский код внутри папки кода сервера. Технически невозможно избежать этого, поэтому вместо этого я создал уровень абстракции в файловой системе, чтобы облегчить мою беспокойную душу. Вот корень моего проекта:

-client
-server
-node_modules
-app.js

client содержит все, что обычно public (все клиентские файлы должны быть поданы), то есть не менее index.html.

server может быть или не быть модулем Node (в моем случае это не обязательно). В этом ваш серверный код для вашего приложения. Вы можете восстановить те же файлы, что и в вашем базовом app.js, поскольку это не будет иметь никакого значения и будет работать нормально.

node_modules, очевидно, требуется Node, и лучше всего оставить его в корне проекта, так как любой require в server может искать вверх по иерархии папок проекта до найти этот общий репозиторий модулей в корне.

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

... Итак, как вы видите, в корневом каталоге script есть минимальный код. Все действительно важные, специфичные для приложения

Обратите внимание, что переменная app не объявляется с помощью var. Избегая var, мы делаем его глобальным и позволяем ему получить доступ в server.js без дальнейших церемоний.

Итак, вы сделали бы node app, чтобы запустить это, если это еще не ясно.

Ответ 3

Как использовать обратный прокси, например Nginx?

Вы можете легко связать два приложения node в одном порту, и есть много других преимуществ.

http://wiki.nginx.org/Main