#reactjs #react-router-v4 #hapijs #react-router-dom
#reactjs #react-router-v4 #hapi.js #react-router-dom
Вопрос:
У меня есть требование использовать 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();
index.html файл загружается нормально, когда localhost:5000
он открыт. Я настроил маршрут /dashboard
в react-router
части. Нажатие localhost:5000/dashboard
дает 404.
Вопросы:
- Как мне настроить маршруты в Hapi, чтобы React взял на себя маршрутизацию после index.html визуализируется?
- Текущий серверный код обслуживает приложение из папки сборки после сборки приложения. Как мне настроить его для горячей перезагрузки без извлечения из
create-react-app
Примечание: Маршрутизация работает при запуске приложения react с npm start
помощью . Но это без запуска сервера Hapi.
Я новичок в использовании Hapi, поэтому любые указания приветствуются.
Ответ №1:
Итак, я поиграл с различными комбинациями hapi inert, и это то, что в итоге сработало для меня.
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.
Я не уверен, как react-router
один раз принимает разрешение пути index.html загружается, но это выходит за рамки данного вопроса и, возможно, является темой для обсуждения в другой раз.
Что касается второго вопроса, касающегося горячей перезагрузки, я все еще пытаюсь это выяснить. На данный момент я запускаю как сервер hapi, так и react-app независимо, так как мне нужно /api
для использования в react-app. Любые предложения или ответы приветствуются.
Ответ №2:
Вот как я это сделал. Протестировал это. Версия "@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 amp;amp; req.response.output amp;amp; 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)
})()