javascript - Next.js 在 html 标记中渲染应用程序作为字符串

标签 javascript reactjs next.js server-side-rendering html-react-parser

我需要在第三方 html 标记内构建我的 Next.js 应用程序。

标记如下:

标题.txt

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

页脚.txt

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

此文件动态生成到文件夹中。当我渲染 next.js 应用程序时,我需要将它们包装在我的应用程序周围。

我使用名为:html-react-parser 的包创建了一个工作示例

我从 _document.js 中的文件中解析标记,并且正在寻找一个自定义元素 id,我将其替换为下一个 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 的目的,因为它将文件的标记转换为 react 组件,并在转换过程中抛出许多关于错误使用 react 的 html 属性的警告无法使用。

也许解决方案是使用angerouslySetInnerHTML,但在这种情况下我无法注入(inject) and 。

// 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}}/>)

如果有人知道我如何设法将我的下一个应用程序包装在来自文件的标记周围,请给我一些建议。

最佳答案

您可以通过custom server来实现这一点,

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 中的 head 以及下一个的 head 和正文。您可以使用cheerio来帮助你。

关于javascript - Next.js 在 html 标记中渲染应用程序作为字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60357068/

相关文章:

javascript - 'length' 为空或不是对象?浏览器 8

node.js - npm 链接的本地库需要 node_modules 而 git 链接的库(相同)不需要

javascript - 表单提交仅在第二次点击时提交,需要在 ES6 中回调

javascript - ES6 : how to split an async generator function without losing yield ability

javascript - 为什么 { ["abc"] :123} exists?

javascript - 如何在 native react 中在控制台中显示整个对象

node.js - 引用错误 : require is not defined (on my rest api)

reactjs - useSWR 以及特定于经过身份验证的用户的数据

next.js - 接下来JS嵌套路由

next.js - nextjs中的getStaticProps()和getServerSideProps()有什么区别