简体   繁体   English

Apache 代理到 reactjs 页面

[英]Apache proxy to reactjs page

I have 2 websites php and reactjs我有 2 个网站 php 和 reactjs

  1. php site running on http://localhost php 站点运行在 http://localhost
  2. react site running on http://localhost:3000在 http://localhost:3000 上运行的反应站点

I'd like to access http://localhost:3000/funds page when user visit URL http://localhost/funds.当用户访问 URL http://localhost/funds 时,我想访问 http://localhost:3000/funds 页面。 I tried with apache proxy but it is showing blank react site as images and css missing on path.我尝试使用 apache 代理,但它显示空白反应站点作为图像,路径上缺少 css。 Any other suggestion to achieve this, Thanks.任何其他实现这一目标的建议,谢谢。

ProxyPass /funds http://localhost:3000/funds
ProxyPassReverse /funds http://localhost:3000/funds

dockerized demo on Github Github上的码头化演示

Solution解决方案

1. Apache server must be configured to load ProxyPass modules. 1. Apache服务器必须配置为加载ProxyPass模块。

It is unclear from the question if the LoadModule is set up accordingly.从问题中不清楚是否相应地设置了LoadModule

# httpd.conf
# proxy_http_module should be loaded before use
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
# rewrite is necessary for an SPA web app. this will be explained below.
LoadModule rewrite_module modules/mod_rewrite.so

2. Apache server must be configured to redirect(rewrite) every request to index.html 2. Apache 服务器必须配置为将每个请求重定向(重写)到 index.html

A react app is a javascript app that runs on a single page(aka SPA), normally on /index.html of host. React 应用程序是一个 javascript 应用程序,它在单个页面(又名 SPA)上运行,通常在主机的/index.html上。 Except the case of server-side rendered react apps, any react app paths implemented via react router libraries(ig react-router-dom ) are merely virtual.除了服务器端呈现的 React 应用程序之外,任何通过 React 路由器库(ig react-router-dom )实现的 React 应用程序路径都只是虚拟的。 The paths only exist inside javascript code and not understood by reverse proxy servers.这些路径仅存在于 javascript 代码中,反向代理服务器无法理解。

To make SPA paths to work, every request should be redirected to /index.html with subpaths.要使 SPA 路径正常工作,每个请求都应使用子路径重定向到/index.html That's what rewrite is.这就是重写 Let me illustrate this in a simpler way.让我用一种更简单的方式来说明这一点。

✅ this request succeeds because it is redirected to index.html by default config
request to / -> /index.html
❌ automatically redirected to path/index.html and it fails because the file does not exist
request to /path -> /path/index.html

--- with rewrite setting ---

✅ this works
request to / -> /index.html
✅ this also works, because it reaches /index.html first
request to /path -> /index.html/#/path
# httpd.conf

# reverse proxying
# service name should be used for docker-compose, but it is not necessary to do the same.
# the host name can be ignored.
ProxyPass "/" "http://react-frontend:3000/"
ProxyPassReverse "/" "http://react-frontend:3000/"

# rewrite for SPA app
<IfModule mod_rewrite>

  RewriteEngine On
  RewriteBase /
  RewriteRule ^index\.html$ - [L]
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteCond %{REQUEST_FILENAME} !-l
  RewriteRule . /index.html [L]

</IfModule>

在此处输入图像描述

My working demo on github works for both http://localhost:8080/funds and http://localhost:8080 . 我在 github 上的工作演示适用于http://localhost:8080/fundshttp://localhost:8080 The dockerized solution here is forwarding port 80 to 8080 but it can be set up to use port 80 if needed.这里的 dockerized 解决方案是将端口 80 转发到 8080,但如果需要,可以将其设置为使用端口 80。

Still can't figure out what's the problem!还是想不通是什么问题!

try check Apache log files .尝试检查Apache 日志文件 if the basics of reverse proxying SPA apps is well understood, just reading logs can solve most problems easily.如果反向代理 SPA 应用程序的基础知识很好理解,只需阅读日志就可以轻松解决大多数问题。

Edit: Serving A React App and PHP(or anything else) Together.编辑:一起提供 React 应用程序和 PHP(或其他任何东西)。

A react app cannot be served at subpaths.不能在子路径中提供 React 应用程序。 The javascript code for react basically assumes that it's from the root path( / ). React 的 javascript 代码基本上假定它来自根路径 ( / )。 If it is served from other sub paths(such as /funds ), it will fail to reach other necessary resources such as .css, .js ...etc.如果它是从其他子路径(例如/funds )提供的,它将无法到达其他必要的资源,例如.css, .js ...等。

The failure process:失败过程:

  1. react bootstrap index page at /subpath/index.html/subpath/index.html反应引导索引页
  2. without modifying the setting, it'll try to get all resources from / : /bundle.js , /styles.css , /favicon.ico在不修改设置的情况下,它会尝试从/ /favicon.ico所有资源/styles.css /bundle.js
  3. requests fail, because they exists at /subpath/bundle.js , subpath/styles.css and so on...请求失败,因为它们存在于/subpath/bundle.jssubpath/styles.css等等...

This is not easily solved unless environment specific setting is used.除非使用特定于环境的设置,否则这不容易解决。 the discrepancy between local and production environment will make things more complicated later.本地环境和生产环境之间的差异会使以后的事情变得更加复杂。

Solution 2: using subdomain解决方案 2:使用子域

The best solution in this case, is to use subdomain.在这种情况下最好的解决方案是使用子域。 Apps do not have to change at all because they are all served from the root path.应用程序根本不需要更改,因为它们都是从根路径提供的。 However, it requires hosts file modification to run from a local machine.但是,它需要修改主机文件才能从本地计算机运行。

let's say I want to use sample.test as domain.假设我想使用sample.test作为域。

  • php will be served at sample.test php 将在sample.test中提供
  • react app will be served at react.sample.test React 应用程序将在react.sample.test中提供服务
# hosts file
127.0.0.1   sample.test
127.0.0.1   react.sample.test
# httpd.conf

# Custom Reverse Proxy /w subdomains

# this setting is no more needed.
# ProxyPass "/react" "http://react-frontend:3000/"
# ProxyPassReverse "/react" "http://react-frontend:3000/"
# ProxyPass "/" "http://php-frontend:80/"
# ProxyPassReverse "/" "http://php-frontend:80/"

# resolve to different service by subdomain.
<VirtualHost *:80>
ServerName react.sample.test
RewriteEngine On
ProxyPass "/" "http://react-frontend:3000/"
ProxyPassReverse "/" "http://react-frontend:3000/"
<Directory "/">
    RewriteRule ^index\.html$ - [L]
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-l
    RewriteRule . /index.html [L]
</Directory>
</VirtualHost>

<VirtualHost *:80>
ServerName sample.test
ProxyPass "/" "http://php-frontend:80/"
ProxyPassReverse "/" "http://php-frontend:80/"
</VirtualHost>

I've updated Github source .我已经更新了 Github 来源 Try run the dockerized demo.尝试运行 dockerized 演示。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM