javascript - nodejs & react:根据请求渲染另一个 HTML 文件
问题描述
我正在尝试在我们的项目中实现 amp 页面。
到目前为止,我已经得出以下解决方案:如果 url 中有查询,例如:myurl.com?amp=1
,则在必要的标记下完全重绘页面。问题是,目前,我们的服务器配置为在 2 个 html 文件之间进行选择,如果有错误,则标记有错误,如果没有,则使用通常的索引。它是这样工作的:
yield this.render('index', {
state: encodeURIComponent(JSON.stringify(state)),
body: renderToString(
<Provider store={store}>
<RouterContext {...props}/>
</Provider>
)
});
和错误
app.use(isProduction ? function * error(next) { // error handler
try {
yield next;
if (this.response.status === 404 && !this.response.body) {
this.throw(404);
}
} catch (err) {
const STATUS_CODES = require('http').STATUS_CODES;
const seo = require('app/modules/seo').initialState;
this.status = err.status = err.status || 500;
if (err instanceof URIError) {
this.redirect('/search');
return;
}
err.message = STATUS_CODES[this.status];
this.app.emit('error', err, this);
yield this.render('error', {
assets,
err,
seo: {...seo, long_title: `${err.status} – ${seo.long_title}`}
});
}
} : error());
componentDidMount() {
if (this.state.isAmp) {
document.write(expotedAmpMarkup(this.props.body))
};
}
请告诉我,当 URL 中有请求时,服务器端如何禁用标准标记的使用?
是否可以在服务器端绘制新页面?
我提前为混乱的文字道歉。我知道的太少,无法构建一个有能力的问题,除了这个论坛,我没有人可以寻求帮助。
如有必要,它已准备好发送整个服务器和 webpack 配置。准备回答任何问题。感谢。
解决方案
您可以根据您的请求在 SSR 上呈现您需要的任何页面。
您可以查看我处理路线的 SSR 应用程序: https ://github.com/tornado1979/ssr-rentalcars 。
一些关键点如下:
客户端'index.js':
.....
import { BrowserRouter } from 'react-router-dom'
import { renderRoutes } from 'react-router-config'
import store from './store'
import Routes from './components/Router/routes'
ReactDOM.hydrate(
<Provider store={store}>
<BrowserRouter>
<div>{renderRoutes(Routes)}</div>
</BrowserRouter>
</Provider>,
document.getElementById('root'),
)
客户端'routes.js',在这里放置所有页面
export default [
{
...App,
routes: [
{
...HomePage,
description: "Compare car hire deals and find the cheapest prices in.",
keywords: 'car hire, cheap car hire, car rental uk, rent a car, car rentals, uk car car, cheap car rentals spain, cheap car rental usa, carrentals, rent car, car hire comparison, carrental, carhire, compare car hire, car rental comparison, rentalcars, rental cars',
path: '/home',
title: '.......',
},
{
...About,
description: 'About Compare car hire deals...',
keywords: 'car hire, ...',
path: '/about',
title: 'About - Rentalcars',
},
{
...NotFoundPage,
description: '',
keywords: '',
title: 'page not found - Rentalcars',
},
],
},
]
服务器端,'index.js'
你接收请求并将正确的组件发送到客户端
//你需要这个路由器:
import { matchRoutes } from 'react-router-config'
app.get('*', (req, res) => {
const store = createStore()
// Initialize and load data into the store
const promises = matchRoutes(Routes, req.path).map(({ route }) => {
return route.loadData ? route.loadData(store) : null
})
Promise.all(promises).then(() => {
const context = {}
const content = renderer(req, store, context)
if (context.notFound) {
res.status(404)
}
return res.send(content)
}).catch(error => res.status(500).send(`Internal Server Error:,
${error}`))
})
渲染page
andstore
并将它们传递给客户端'render.js'
export default (req, store, context = {}) => {
const content = renderToString(
<Provider store={store}>
<StaticRouter context={context} location={req.path}>
<div>{renderRoutes(Routes)}</div>
</StaticRouter>
</Provider>,
) const 头盔 = Helmet.renderStatic()
返回 (
<!DOCTYPE html>
<html ${helmet.htmlAttributes.toString()}>
<head>
<meta charset="UTF-8">
${helmet.title.toString()}
${helmet.meta.toString()}
</head>
<body ${helmet.bodyAttributes.toString()}>
<div id="root">${content}</div>
<script>
window.INITIAL_STATE = ${serialize(store.getState())}
</script>
<script src="bundle.js"></script>
</body>
</html>
) }
我希望它有所帮助。
推荐阅读
- mysql - 两列上的 SQL 查询过滤器
- c# - 在组合框更改时更改绑定类的值
- python - Python 3 - 解码转义字符串
- google-cloud-platform - bigQuery 数据导出费用
- google-apps-script - Google 表格 - 从多个工作表选项卡中提取数据的双向查找
- python-3.x - 在 opencv 中执行阈值处理时出现调整大小功能的问题
- c# - 如何使用 ADO.NET 框架从 MySql 加载我的类?
- javascript - 字符串常量和引号之间的字符串“”有什么区别?以及如何在它们之间转换?
- spring - 独立 Tomcat 的 Spring Boot 会话超时
- docker - Mattermost 凭据设置在哪里?