Next.js 在 html 标记中呈现应用程序作为字符串 [英] Next.js render app inside html markup coming as string

查看:29
本文介绍了Next.js 在 html 标记中呈现应用程序作为字符串的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

标记如下:

header.txt

<头><title>一些标题</title><身体><header>一些标题</header>

页脚.txt

 </div><footer>一些页脚</footer></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 = `${头}<main id="react-app"></main>${页脚}`;//稍后在渲染方法 od _document.js 中:使成为() {返回 (<React.Fragment>{解析(壳,{替换:domNode =>{如果(domNode.attribs && domNode.attribs.id === 'react-app'){返回 (<React.Fragment><主要/><NextScript/></React.Fragment>)}}})}</React.Fragment>)}

虽然这有效,但我的问题是,这不是 html-react-parser 的目的,因为它将文件的标记转换为反应组件,并在转换过程中抛出许多关于错误使用的 html props 反应的警告不能用.

也许解决方案是使用危险的SetInnerHTML,但在这种情况下我不能注入和.

//失败,因为它不会将组件视为普通的 html//<Main/><NextScript/>不被评估const header = fs.readFileSync(path.resolve(ROOT + '/resources', 'header.txt'), 'utf8');const footer = fs.readFileSync(path.resolve(ROOT + '/resources', 'footer.txt'), 'utf8');const shell = `${头}<React.Fragment><主要/><NextScript/></React.Fragment>${页脚}`;//稍后在渲染方法 od _document.js 中:render(<html risklySetInnerHTML={{__html: shell}}/>)

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

解决方案

您可以使用 自定义服务器,

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) ||3000const dev = process.env.NODE_ENV !=='生产'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);//您将需要合并",因为 nextResponse 有 `head` &身体"也是如此.})server.listen(端口,错误 => {如果(错误)抛出错误console.log(`> Ready on http://localhost:${port}`)})})

mergeHTML 应该从您的 header & 合并头部下一个头&身体.您可以使用 cheerio 来帮助您.

I need to build my Next.js app inside a third-party html markup.

The markup is given as follows:

header.txt

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

footer.txt

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

This files are dynamically generated into a folder. When I render my next.js application, I need to wrap them around my application.

I created a working example using the package called: html-react-parser

I parse the markup from the files in the _document.js and I am looking for a custom element id which I am replacing with the next js app as follows:

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

Although this works, my problem is, that this is not the purpose of the html-react-parser because it converts the markup of the files to react components, and throws many warnings during the conversion about wrongly used html props which react can not use.

Maybe the solution would be to use dangerouslySetInnerHTML, but in this case I can not 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}}/>)

If anybody has an Idea how could I manage to wrap my next app around my markup coming from the files, please give me some advice.

解决方案

You can achieve that with 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 should merge head from your header & next's head & the body. You can use cheerio to help you with that.

这篇关于Next.js 在 html 标记中呈现应用程序作为字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆