Next.js 在 html 内呈现应用程序标记作为字符串
Next.js render app inside html markup coming as string
我需要在第三方 html 标记中构建我的 Next.js 应用程序。
标记如下:
header.txt
<html>
<head>
<title>Some title</title>
</head>
<body>
<header>Some header</header>
<div>
footer.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 的目的,因为它将文件的标记转换为反应组件,并在转换过程中抛出许多关于错误使用 html 无法使用 react 的道具。
也许解决方案是使用 dangerouslySetInnerHTML,但在这种情况下我无法注入和。
// 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
和下一个的头部以及 body 的头部。您可以使用 cheerio
来帮助您。
我使用 dangerouslySetInnerHTML 解决了这个问题。基本上它不关心你传递给它的字符串语法,所以我在 _document.js 中想出了以下解决方案:
<Html>
<html dangerouslySetInnerHTML={{__html: header}}/>
<Head />
<body>
<Main />
<NextScript />
</body>
<html dangerouslySetInnerHTML={{__html: footer}}/>
</Html>
dangerouslySetInnerHTML 的两次调用都采用奇数个元素并环绕 next.js 个组件。
如果有人有另一个解决方案,也许没有 dangerouslySetInnerHTML,请发表评论。
我需要在第三方 html 标记中构建我的 Next.js 应用程序。
标记如下:
header.txt
<html>
<head>
<title>Some title</title>
</head>
<body>
<header>Some header</header>
<div>
footer.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 的目的,因为它将文件的标记转换为反应组件,并在转换过程中抛出许多关于错误使用 html 无法使用 react 的道具。
也许解决方案是使用 dangerouslySetInnerHTML,但在这种情况下我无法注入和。
// 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
和下一个的头部以及 body 的头部。您可以使用 cheerio
来帮助您。
我使用 dangerouslySetInnerHTML 解决了这个问题。基本上它不关心你传递给它的字符串语法,所以我在 _document.js 中想出了以下解决方案:
<Html>
<html dangerouslySetInnerHTML={{__html: header}}/>
<Head />
<body>
<Main />
<NextScript />
</body>
<html dangerouslySetInnerHTML={{__html: footer}}/>
</Html>
dangerouslySetInnerHTML 的两次调用都采用奇数个元素并环绕 next.js 个组件。
如果有人有另一个解决方案,也许没有 dangerouslySetInnerHTML,请发表评论。