Далее. js Визуализация приложения внутри html разметки в виде строки - PullRequest
1 голос
/ 23 февраля 2020

Мне нужно создать приложение Next. js внутри сторонней html разметки.

Разметка имеет следующий вид:

header.txt

<html>
  <head>
    <title>Some title</title>
  </head>
  <body>
    <header>Some header</header>
    <div>

footer.txt

    </div>
    <footer>Some footer</footer>
  </body>
</html>

Эти файлы динамически создаются в папке. Когда я выполняю рендеринг моего следующего. js приложения, мне нужно обернуть его вокруг моего приложения.

Я создал рабочий пример, используя пакет под названием: html -react-parser

I разобрать разметку из файлов в _document. js, и я ищу пользовательский идентификатор элемента, который я заменяю следующим js приложением следующим образом:

const header = fs.readFileSync(path.resolve(ROOT + '/resources', 'header.txt'), 'utf8');
const footer = fs.readFileSync(path.resolve(ROOT + '/resources', 'footer.txt'), 'utf8');
const shell = `
    ${header}
    <main id="react-app"></main>
    ${footer}
`;


// later in the render method od _document.js:

render() {
        return (
            <React.Fragment>
                {parse(shell, {
                    replace: domNode => {
                        if (domNode.attribs && domNode.attribs.id === 'react-app') {
                            return (
                                <React.Fragment>
                                    <Main/>
                                    <NextScript/>
                                </React.Fragment>
                            )
                        }
                    }
                })}
            </React.Fragment>
        )
    }

Хотя это работает, моя проблема в том, что это не цель html -react-parser, поскольку он преобразует разметку файлов в реагирующие компоненты, и выдает много предупреждений во время преобразования о неправильно используемых html реквизитах, которые реагировать не может.

Возможно, решение было бы использовать опасно SetInner HTML, но в этом случае я не могу ввести и.

// it fails because it wont treat the components as normal html
// <Main/><NextScript/> are not evaluated
      

const header = fs.readFileSync(path.resolve(ROOT + '/resources', 'header.txt'), 'utf8');
const footer = fs.readFileSync(path.resolve(ROOT + '/resources', 'footer.txt'), 'utf8');
const shell = `
    ${header}
      <React.Fragment>
        <Main/>
        <NextScript/>
      </React.Fragment>
    ${footer}
`;

// later in the render method od _document.js:

render(<html dangerouslySetInnerHTML={{__html: shell}}/>)

Если у кого-то есть идея, как мне обернуть мое следующее приложение вокруг моей разметки, исходящей из файлов, пожалуйста, дайте мне несколько советов.

Ответы [ 2 ]

1 голос
/ 23 февраля 2020

Вы можете достичь этого с помощью пользовательского сервера ,

const express = require('express')
const next = require('next')

const header = fs.readFileSync(path.resolve(ROOT + '/resources', 'header.txt'), 'utf8');
const footer = fs.readFileSync(path.resolve(ROOT + '/resources', 'footer.txt'), 'utf8');

const port = parseInt(process.env.PORT, 10) || 3000
const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()

app.prepare().then(() => {
  const server = express()

  server.all('*', async (req, res) => {
    const nextResponse = await handle(req, res);
    return mergeHTML(header, footer, nextResponse); // You will need to "merge" cause nextResponse has `head` & `body` as well.
  })

  server.listen(port, err => {
    if (err) throw err
    console.log(`> Ready on http://localhost:${port}`)
  })
})

mergeHTML должны объединить голову от вашей header & головы и тела следующего. Вы можете использовать cheerio, чтобы помочь вам в этом.

0 голосов
/ 23 февраля 2020

Я решил проблему, используя опасно SetInner HTML. По сути, его не волнует синтаксис строки, который вы передаете в него, поэтому я нашел следующее решение в _document. js:

<Html>
  <html dangerouslySetInnerHTML={{__html: header}}/>
  <Head />
  <body>
      <Main />
      <NextScript />
  </body>
  <html dangerouslySetInnerHTML={{__html: footer}}/>
</Html>

Оба вызова dangerouslySetInner HTML берут нечетное количество элементов и обертывают следующие. js компоненты.

К значению if у кого-нибудь есть другое решение, может быть, без опасения. SetInner HTML, пожалуйста, прокомментируйте его.

...