我有一个要求将Hapi与create-react-app
一起使用,其中Hapi充当api请求的代理,并且还服务于React应用。
我正在尝试使路由正常工作,但似乎不适用于当前的Hapi配置。
这是我的服务器代码:
const Path = require('path');
const Hapi = require('hapi');
const Inert = require('inert');
const init = async () => {
const server = new Hapi.Server({
port: process.env.PORT || 5000,
routes: {
files: {
relativeTo: Path.join(__dirname, '../build')
}
}
});
await server.register(Inert);
server.route({
method: 'GET',
path: '/{param*}',
handler: {
directory: {
path: '.'
}
}
});
const options = {
ops: {
interval: 1000
},
reporters: {
myConsoleReporter: [
{
module: 'good-console',
args: [{ request: '*', response: '*' }]
},
'stdout'
]
}
};
await server.register({
plugin: require('good'),
options,
});
await server.start();
console.log('Server running at:', server.info.uri);
};
init();
打开localhost:5000
时,index.html文件加载正常。我在/dashboard
部分中配置了路由react-router
。击中localhost:5000/dashboard
会得到404。
问题:
create-react-app
注意:使用npm start
运行react应用时,路由有效。但这没有运行Hapi服务器。
我是使用Hapi的新手,因此欢迎使用任何指针。
答案 0 :(得分:0)
所以我玩了各种hapi +惰性组合,这才对我有用。
server.js
const Path = require('path');
const Hapi = require('hapi');
const Inert = require('inert');
const routes = require('./routes');
const init = async () => {
console.log('Routes are', routes);
const server = new Hapi.Server({
port: process.env.PORT || 5000,
routes: {
files: {
relativeTo: Path.join(__dirname, '../build')
}
}
});
await server.register(Inert);
server.route(routes);
/**
* This is required here because there are references to *.js and *.css in index.html,
* which will not be resolved if we don't match all remaining paths.
* To test it out, comment the code below and try hitting /login.
* Now that you know it doesn't work without the piece of code below,
* uncomment it.
*/
server.route({
method: 'GET',
path: '/{path*}',
handler: {
directory: {
path: '.',
redirectToSlash: true,
index: true,
}
}
});
const options = {
ops: {
interval: 1000
},
reporters: {
myConsoleReporter: [
{
module: 'good-console',
args: [{ request: '*', response: '*' }]
},
'stdout'
]
}
};
await server.register({
plugin: require('good'),
options,
});
await server.start();
console.log('Server running at:', server.info.uri);
};
init();
/routes/index.js
/**
* Use this for all paths since we just need to resolve index.html for any given path.
* react-router will take over and show the relevant component.
*
* TODO: add a 404 handler for paths not defined in react-router
*/
const fileHandler = {
handler: (req, res) => {
console.log(res.file('index.html'));
return res.file('index.html');
}
}
const routes = [
{ method: 'GET', path: '/login', config: fileHandler },
]
module.exports = routes;
这里要观察的关键是,对于任何命名路径(在本例中为/login
),我们总是返回index.html
文件。对于所有其他路径,我们告诉hapi从build
目录中返回文件,以便解决对*.css
中对*.js
或index.hml
文件的任何引用,而我们不这样做不会遇到404。
我不确定一旦装入index.html后react-router
将如何接管路径解析,但是它超出了此问题的范围,也许是下一次讨论的话题。
至于有关热装的第二个问题,我仍在设法解决。现在,我需要同时运行hapi服务器和react-app,因为我需要/api
才能在react-app中使用。欢迎任何建议或答案。
答案 1 :(得分:0)
这是我如何做到的。测试了一下。版本 "@hapi/hapi": "^20.0.1"
。
const path = require("path")
const Hapi = require('@hapi/hapi')
const Boom = require('@hapi/boom');
const server = Hapi.server({
port: 3000,
host: '0.0.0.0',
routes: {
files: {
relativeTo: path.join(__dirname, 'YOU BUILD REACT DIR')
}
}
});
(async () => {
await server.register([
require('vision'),
require('inert')
]);
server.route(
[{
method: 'GET',
path: '/{path*}',
options: {
ext: {
onPreResponse: {
method(req, h) {
//for other path prefix /Api
const isApi = req.path.substr(1)
.toLowerCase()
.trim()
.split('/')[0]
.replace(/\//g, "") === "api"
const response = req.response
if (response && req.response.output && req.response.output.statusCode === 404) {
if (isApi)
return Boom.notFound("Not Found")
return h.file('index.html');
}
return h.continue
},
}
}
},
handler: {
directory: {
path: ".",
listing: false,
index: true
}
}
},
{
method: 'GET',
path: '/Api/test',
handler: () => "OK"
}
])
await server.start();
console.log('Server running on %s', server.info.uri)
})()