Маршрутизация с помощью Hapi

#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)
})()