【问题标题】:Domain and subdomain routing in NodeJS or ReactJsNodeJS 或 ReactJs 中的域和子域路由
【发布时间】:2021-03-22 14:09:04
【问题描述】:

网页的总体思路:

  1. domain.com : 指向管理员和卖家的登录页面。
  2. shop.domain.com : 指向卖家的店铺。
  3. 计划使用 React.js 作为前端,使用 Nodejs (Express Js) 作为后端。
  4. 尚未决定在 Heroku 上托管所有内容,或者仅在 Heroku 和 React.js 上托管 Nodejs 后端,因为我们正在分离开发过程。

如何根据 URL 访问(带或不带子域)将用户重定向到相应页面

事实上,npm 有一个名为express-subdomain-handler 的包,它可以帮助服务器端的域和子域路由,我可以毫无问题地完成并部署到 Heroku。

app.use(subdomainHandler({
    baseUrl: 'localhost',
    prefix: 'subdomain',
    logger: true
}));

app.get('/', function (request, response) {
    response.send('WELCOME TO LOCALHOST');
});

app.get('/subdomain/:shop', function (request, response) {
    response.send('WELCOME TO SUBDOMAIN');
});

我相信上面的路由更倾向于服务器端渲染,因为它只根据访问的 URL(或端点)呈现相应的页面。但是可以通过这种方式渲染 React 应用程序吗?因为我之前所做的基本上只是渲染.ejs 页面,这就是为什么我对此不确定,而且我之前从未使用过 React.js。

其次,如果我将 React 应用程序托管在另一台服务器上,可能是 Vercel 或 NGINX 或其他任何服务器,并使用 REST API 访问 heroku 中的后端服务,这是部署网站的正确方法吗?如果是这样,域和子域路由是在 React 应用程序的托管站点还是在代码本身内部完成,而不是 Heroku 中的 expressjs?因为我相信 expressjs 只会负责创建一系列端点来监听。比如在 express.js 里面:

app.get('/hello', (req, res) => {
   res.send("Hello from domain");
})

app.get('/subdomain/hello', (req, res) => {
   res.send("Hello from subdomain");
})

React 应用只需要访问这些 API,无需考虑后端的子域和域的路由问题。我相信这在某种程度上被称为客户端渲染,因为每个 REST API 都会返回要渲染的 JSON 数据。

那么如果我这样执行,我们如何根据访问的 URL 来确定 React 应用要显示的页面呢?比如domain.com会跳转到dashboard page,shop.domain.com会跳转到shop page?

【问题讨论】:

    标签: node.js reactjs express heroku


    【解决方案1】:

    1。关于子域

    api/ 和 api/subdomain 可以由 NGINX 虚拟主机实现,但由于您计划虚拟主机为子域,api.domain.com。

    用 api.domain.com/foo,sub.domain.com/bar 似乎更合理!

    例如

    listen 80;
    server_name api.domain.com/api;
    location / {
                 proxy_http_version 1.1;
                 proxy_pass  http://localhost:4000;
    }
    
    listen 80;
    server_name api.domain.com/api/subdomain;
    location / {
                 proxy_http_version 1.1;
                 proxy_pass  http://localhost:4000;
                 #notice that api application is one and you are seperating namespace in it.
                 #you can do the same thing in Node.js with subrouter. ( check out Router API in Nodejs official Site )
    }
    
    api.domain.com/foo, sub.domain.com/bar
    listen 80;
    server_name api.domain.com;
    location / {
                 proxy_http_version 1.1;
                 proxy_pass  http://localhost:4000;#this one is node application listening port 4000
    }
    
    listen 80;
    server_name sub.domain.com/;
    location / {
                 proxy_http_version 1.1;
                 proxy_pass  http://localhost:4001;#and this is node application listening port 4001
    }
    

    第一种情况下的访问。

    
        GET    api.domain.com/api/foo
        GET    api.domain.com/api/subdomain/bar
    
    

    第二种情况下的访问。

    
        GET    api.domain.com/foo
        GET    sub.domatin.com/bar
    
    

    2。如此真实。让每个 CNAME 指向您的 EC2(或任何服务器实例上的任何 Web 应用程序)作为源


    3。您无需为 S3 实例配置服务器引擎。

    S3 不在 EC2 实例中,而是在 AWS 数据中心的某个地方。所以虚拟主机不是路由 S3 存储桶的解决方案。您可以使用 Route53 为您的域路由 S3 存储桶,而不是这样做。

    如果您已经有一个域。您可以将名称服务器配置为指向 AWS 名称服务器。 注册域后,您可以从 Route 53 控制台获取 NS/DNS。

    同时,静态托管react app(S3-like托管)有问题,你必须放弃SSR。因为 S3 是一个静态主机,它不能像 Lambda 或服务器实例那样执行。

    S3 只会为请求检索存储的文件,在这种情况下,它将是 react 应用程序的构建文件。因此,如果我是你,我只会将 S3 用于管理响应应用程序,因为 SEO 在管理应用程序中并不重要。

    用 express 做 SSR

    让您的根域 (www.domain.com) 指向 EC2 中的客户端 nodejs 服务器。并嵌套服务器的反应构建文件。通过 Express 的 React SSR 应用程序解释起来相当复杂,但有很多例子,所以你可能想用谷歌搜索一下。


    题外话,我在 S3 上构建了我的电子商务反应应用程序,我很遗憾这样做,因为 SSR 部分并不容易。关于它有很多解决方案,但其中之一是,next.js 框架似乎是尽快完成 ssr 的最佳选择。

    【讨论】:

    • 感谢您提供信息丰富的回复。所以基本上,如果 SSR:那么我应该在 EC2 中部署所有内容,并在 1 上工作。关于反向代理的子域,否则如果是CSR,我可以将EC2上的部署分离为express和S3上的React,然后借助Route 53,CNAME将直接指向S3存储桶。在这种情况下,根据域和子是否虚拟托管后端无关紧要,因为所有API请求都可以通过第一种情况访问的方法直接指向EC2。而且,坚持企业社会责任意味着放弃搜索引擎优化。我的理解正确吗?
    • 是的,这就是我在说的兄弟,我认为这对你来说很好!
    • 嘿伙计,感谢您提供这么多信息!我确实从您的回复中学到了很多东西,我真的很感激,希望我能够成功部署应用程序。谢谢。
    • 祝您发展顺利,很高兴我的回答对您有所帮助!
    【解决方案2】:

    首先,我从未使用 Heroku 进行托管,因此我的解决方案可能会因您的环境而异 但是,我认为整个概念对你有用。

    您的问题没有固定答案,但我现在的想法可能对您有所帮助:) 你的问题有很多子问题,所以我把它分开了。

    而且我的英语不太流利,所以你和我之间可能会出现一些误解, 如果我对您的问题的理解有误,请告诉我。

    问。但是这种方式可以渲染 React 应用吗?

    (我的理解是:react 应用可以由 SSR 托管)

    A.您可以使用代码拆分和服务器端渲染为带有 SSR 的 React 应用程序提供服务,您最好使用服务器端渲染 对于某些元标记和 SEO 所需的页面,除非您需要完整的 SSR 应用程序。 如果您需要完整的 ssr,也有适合它的精美框架 Next.js。 通过您提到 Vercel,您可能已经知道这一判断。

    问。如果我将 React 应用程序托管在另一台服务器上,可能是 Vercel 或 NGINX 或任何其他服务器,并使用 REST API 访问 heroku 中的后端服务会怎样

    (我的理解是:React 应用程序可以托管在另一台服务器上吗? NGINX = 使用服务器实例, Vercel:使用无服务器架构 )

    A.它也可以像这样托管。似乎这个更像反应。 但我不推荐 Vercel 托管,因为电子商务服务需要很多端点, 查看 Vercel 的定价政策。

    问。那么,假设我将 Heroku 用于 Express 后端,是否意味着我需要分别创建 2 个应用程序而不是将它们组合在一起

    A.您可以为计算机资源托管多个主机,也可以不托管。如果您计划多主机,您可能需要代理服务器来指向其他服务器, 相反,对于单主机,反向代理指向每个应用程序。

    问。 express-subdomain-handler vs. vhost

    A.没有固定的答案。你可以使用 vhost 或 express-subdomain-handler 来实现你想要的。或两者兼有。

    我的解决方案概念是使用带有反向代理的单个服务器实例。 让 Nginx 在单个服务器中虚拟托管您的多个应用程序。

    我的建议:

    应用列表。

    1. react 主机 - nodejs 应用程序
    2. 客户端 api 主机 - nodejs 应用程序
    3. 管理员反应主机 - nodejs 应用程序
    4. 客户端 api 主机 - nodejs 应用程序

    我使用 AWS S3 来托管 React 应用程序和 用于 API 应用的 EC2。

    结构概念。

    ( NS / DNS ) : domain.com points your-ip
        |
        ( Server instance )
            |
            ( Nginx ) - virtual hosting
                |
                ( www.domain.com ) --- > client react host : ( node app for server side rendering ) : React rendered file for each route. 
                                                           Or you can just respond with index.html for all route for skipping SSR
                |
                ( api.domain.com ) --- > clinet api host : api.domain.com/what, api.domain.com/what/ever?you=want
                |
                ( admin.domain.com ) ---> admin react host : admin.domain.com/* : sending index.html  //static hosting and let all route point for index.html
                |
                ( admin-api.domain.com ) ---> admin react host : Only if you want to seperate. Or you can combine this with api.domain.com using subrouter
    

    如何构建结构。

    第 1 步。服务器托管。

    I don't know much about Heroku but I guess there are aws ec2-like service(cloud computing) and s3-like service(static file service),
    This can be single or multiple depending your choice. let's say you wanna go with single server and use virtual host for multiple service end point.
    

    Step 2. 网络层设置

    let's say name-server and DNS server part is network layer. I used AWS Route 53 for this.
    
        2.1 Buy an domain
        www.your-service.com 
        
        2.2 Add some CNAME to point your web-server host
        - your-service.com,
        - www.your-service.com
        - api.your-service.com,
        - admin.your-service.com    
    .
    .
    .
    

    Step 3.创建nodejs应用(应用层)

    I'm assuming that you had one already judging by code in your question.
    
    
    ubuntu@ip-your-ip:~/project$ ls
    api  cli   admin   admin-api   config   libraries  middlewares  models  node_modules   package.json 
    
    ubuntu@ip-your-ip:~/project$ cd api
    
    ubuntu@ip-your-ip:~/project/api$ ls
    README.md  app.js  bin  config.json  pm2.config.js  node_modules  package.json  routes
    
    ubuntu@ip-your-ip:~/project/api$ pm2 start pm2.config
    
    

    PM2 是节点应用程序 deamonizer,您可以为此使用任何守护程序。

    PM2 参考。 https://pm2.keymetrics.io/docs/usage/application-declaration/

    步骤 3. nodejs 应用程序的 Nginx 点

    
    nano /etc/nginx/nginx.conf
    
    listen 80;
    server_name client.domain.com;
    location / {
                 proxy_http_version 1.1;
                 proxy_pass  http://localhost:3000;
    }
    
    listen 80;
    server_name api.domain.com;
    location / {
                 proxy_http_version 1.1;
                 proxy_pass  http://localhost:3001;
    }
    
    listen 80;
    server_name admin.domain.com;
    location / {
                 proxy_http_version 1.1;
                 proxy_pass  http://localhost:4000;
    }
    
    listen 80;
    server_name admin-api.domain.com;
    location / {
                 proxy_http_version 1.1;
                 proxy_pass  http://localhost:4001;
    }
    
    

    我希望这个解决方案对你有帮助:)

    【讨论】:

    • 非常感谢您为回答我的问题所做的努力!我想我将使用具有多个服务端点的单个服务器(顺便说一句,现在考虑将 EC2 作为后端),但我确实对您的回复有一些疑问。 multiple service endpoints 是否意味着我创建到不同的端点,api/ 用于 domain.com,/api/subdomain 用于 subdomain.domain.com 来处理不同的请求?
    • 所以我相信 NGINX 是在 EC2 内部设置的,它运行在后端服务器的前面。这意味着,在 Web 托管站点上,我只需创建不同的 CNAME 并指向 EC2 的 IP/实例,然后让 NGINX Web 服务器决定请求的目标 URL?
    • 如果我的 React App 部署在 S3 中,那么我只需将 location / { proxy_pass http:// } 更改为我的 S3 存储桶的 IP 或 URL?
    【解决方案3】:

    我认为这不是反应部分。 React 是浏览器库,无法处理域部分。

    我也不建议用express处理这部分,因为这需要使用反向代理,你最好使用Nginx,Apache,其他一些服务器引擎来处理子域。

    你计划的可以这样托管,

    1. 创建 domain.com
    2. 将 cname 添加到 shopping.domain.com

    服务器

    1. 创建管理服务器、客户端服务器
    2. 反向代理那些服务器

    客户

    1. 创建 2 个反应项目。
    2. domain.com 为管理员响应构建文件提供服务。
    3. shop.domain.com 服务商店反应构建文件。

    如果您不这样做,我还建议为管理员反应应用程序托管静态文件 需要公开搜索引擎的管理页面。

    【讨论】:

    • 哦,我忘记了路由部分。大多数 React 应用程序都使用浏览器路由而不是服务器路由
    • 那么,假设我正在使用 Heroku for Express 后端,这是否意味着我需要分别创建 2 个应用程序而不是将它们组合在一起,这样会导致:来自域的 API 将指向foo.herokuapp.com 和来自子域的 API 将指向 bar.herokuapp.com?或者我应该将它们组合在一起并使用vhost 确定它?在这种情况下,我们应该在哪里设置 NGINX 进行反向代理?
    • 这是否意味着我需要在静态文件托管站点上设置 nginx 并对其进行反向代理以提供管理员响应或商店响应,然后所有 API 都将指向 Heroku 应用程序?所以在这种情况下,我们可以将 Heroku 应用程序、指向 foo.herokuapp.com/bar.herokuapp.com/ 的 API 分开,或者我们只是将它们组合起来并在 REST Api 设计中添加一些工作。例如,/ 用于来自管理员反应的所有请求,/shop/ 用于来自商店反应的所有请求?
    • 我想澄清一下我的想法:首先,使用 build-pack link 创建一个 Heroku 应用程序,然后我们推送我们的前端 repo,其中包含 2 个不同的 React 应用程序,admin 和shop react 应用,到我们创建的 Heroku 应用。然后我们在 build-pack 中配置 NGINX 设置(不确定在哪里或如何配置,仍然需要阅读),以便我们可以根据传入的 URL 类型(域或子域)提供不同的 React 应用程序。
    • 然后将 express 后端部署到另一个 Heroku 应用程序(或者可能是 2 个用于微服务架构的 Heroku 应用程序)并处理所有 REST API,然后将 JSON 数据返回给 React 应用程序。是吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-18
    • 2011-04-09
    • 2014-02-27
    相关资源
    最近更新 更多