首页 > 解决方案 > 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 配置。准备回答任何问题。感谢。

标签: javascriptnode.jsreactjsserver-side-rendering

解决方案


您可以根据您的请求在 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}`))
})

渲染pageandstore并将它们传递给客户端'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> ) }

我希望它有所帮助。


推荐阅读