在 Express 中使用客户端路由为多个 React 应用程序提供服务
Posted
技术标签:
【中文标题】在 Express 中使用客户端路由为多个 React 应用程序提供服务【英文标题】:Serving multiple react apps with client-side routing in Express 【发布时间】:2018-05-05 02:30:21 【问题描述】:我为一项服务提供不同的软件产品,需要将其部署到一台服务器上。客户端使用 react 构建,通过 create-react-app 进行构建设置,而服务器运行 Node.js 和 Express。
当我从服务器提供单个应用程序时,它是通过以下方式完成的:
// App.js
// ...
// Entry point for data routes (API)
app.use('/data', indexRoute);
if(process.env.NODE_ENV !== 'development')
app.use(express.static(path.join(__dirname, 'build-client')));
app.get('/*', function(req, res)
return res.sendFile(path.resolve( __dirname, 'build-client' , 'index.html'));
);
我希望能够从服务器提供多个应用程序。我该怎么做?
我尝试的是为资产连接不同的静态路径,并用不同的名称分隔客户端,尽管它不起作用。像这样:
// App.js
// ...
// Entry point for data routes (API)
app.use('/data', indexRoute);
if(process.env.NODE_ENV !== 'development')
app.use(express.static(path.join(__dirname, 'build-client')));
app.use(express.static(path.join(__dirname, 'build-admin')));
app.get('/client/*', function(req, res)
return res.sendFile(path.resolve( __dirname, 'build-client' , 'index.html'));
);
app.get('/admin/*', function(req, res)
return res.sendFile(path.resolve( __dirname, 'build-client' , 'index.html'));
);
我也尝试过这样做,但是 Express 抛出错误:未指定默认引擎并且未提供扩展:
if(process.env.NODE_ENV !== 'development')
// Admin paths
app.use('/admin', express.static(path.join(__dirname, 'build-admin')));
app.get('/admin/*', function(req, res)
return res.sendFile(path.resolve( __dirname, 'build-admin' , 'index.html'));
);
// Site paths
app.use('/', express.static(path.join(__dirname, 'build-client')));
app.get('/*', function(req, res)
return res.sendFile(path.resolve( __dirname, 'build-client' , 'index.html'));
);
我怎样才能完成这个或类似的事情?
【问题讨论】:
【参考方案1】:在解决这个问题一段时间后,我找到了一个可能的解决方案,而不会影响原始设置。
我们使用Express vhost package 来设置通过虚拟域处理请求。
当您创建应用实例时,您应该使用 express 初始化尽可能多的应用(在我们的例子中是三个独立的应用加上原始应用实例)
// Create an express instance
const app = express();
const appAdmin = express();
const appClient = express();
const appVendor = express();
之后,您需要安装 vhost 并导入它。然后通过为每个应用程序指定静态文件夹,您可以分别处理静态文件,而其余部分分别处理给定子域的请求。
appAdmin.use(express.static(path.join(__dirname, 'build-admin')));
appClient.use(express.static(path.join(__dirname, 'build-client')));
appVendor.use(express.static(path.join(__dirname, 'build-vendor')));
appAdmin.use((req, res, next) =>
return res.sendFile(path.resolve( __dirname, 'build-admin' , 'index.html'));
);
appClient.use((req, res, next) =>
return res.sendFile(path.resolve( __dirname, 'build-client' , 'index.html'));
);
appVendor.use((req, res, next) =>
return res.sendFile(path.resolve( __dirname, 'build-vendor' , 'index.html'));
);
app.use(vhost('domain.com', appClient));
app.use(vhost('www.domain.com', appClient));
app.use(vhost('a.domain.com', appAdmin));
app.use(vhost('b.domain.com', appVendor));
不要忘记在您的域的 DNS 注册表中添加所需的子域。示例:
...records
CNAME vendor @
CNAME admin @
【讨论】:
【参考方案2】:经过一些修改,我能够在不使用虚拟主机的情况下实现这一点。我使用了您在问题中给出的第一个想法,除了我将主应用程序留在了根目录(即/
)。
// when going to `/app2`, serve the files at app2/build/* as static files
app.use('/app2', express.static(path.join(__dirname, 'app2/build')))
// when going to `/`, serve the files at mainApp/build/* as static files
app.use(express.static(path.join(__dirname, 'mainApp/build')))
// These are necessary for routing within react
app.get('app2/*', (req, res) =>
res.sendFile(path.join(__dirname + '/app2/build/index.html'))
)
app.get('*', (req, res) =>
res.sendFile(path.join(__dirname + '/mainApp/build/index.html'));
);
在这之后,我进入mainApp/package.json
并添加了
"proxy": "http://localhost:4141"
:4141
是运行快速服务器的端口。此行将对 fetch('/some/route')
的调用返回到服务器,而不是进入您的 react 应用程序本身。
最后我们去app2/package.json
添加
"proxy": "http://localhost:4141/app2",
"homepage": "/app2"
我相信这里的关键是"homepage"
关键。我理解它的方式是,当 react 启动时,它会在其主页上搜索一些静态文件,而没有 "homepage"
部分,我只能获得空白屏幕或 mainApp。
我希望这对那里的人有所帮助!
编辑
从那以后,我从通过我的 express 服务器为我的 create-react-apps 提供服务更改为通过netlify 为它们提供服务。现在我不需要担心这个快速设置,或者package.json
中的主页键。 express server 独立存在,react 应用程序仍然可以使用相同的 api,并且部署更加容易。使用 netlify 进行设置很简单。
【讨论】:
以上是关于在 Express 中使用客户端路由为多个 React 应用程序提供服务的主要内容,如果未能解决你的问题,请参考以下文章
如何通过 Express 路由到多个 Angular 应用程序?