反应头盔服务器端正确设置

时间:2018-02-12 13:17:23

标签: reactjs serverside-rendering react-helmet

Helmet现在正在服务器上返回空字符串。我不确定文档是否解释得很好,现有问题很少有任何帮助!

问题 -

   `console.log('title', helmet.title.toString());
    console.log('meta', helmet.meta.toString());
    console.log('link', helmet.link.toString());`
除了记录<title data-react-helmet="true"></title>

的标题外,

都是空的

这里存在一个非常类似的问题 - react-helmet outputting empty strings on server-side

但它已经为SSR推出了应用程序。我还没有做到这一点,并希望不只是为了反应头盔。 其次,我需要从API动态调用元标记并填充相同的内容。

我很不清楚这些是如何运作的。这些如何在下面自动获取元数据和链接?我不需要设置它们吗?

我最终会想为每条路线添加自定义元标记。但是让我们开始主页至少为头盔

我的实施方式如下文所述:

import React from 'react';
import ReactDOMServer from 'react-dom/server';
import { Provider } from 'react-redux';
import { ConnectedRouter } from 'react-router-redux';
import store from '../../src/store';
import {createMemoryHistory } from 'history';
import { ServerStyleSheet } from 'styled-components';
import Loadable from 'react-loadable';
import manifest from '../../build/asset-manifest.json';
import Helmet from 'react-helmet';
import App from '../../src/containers/app';
const path = require('path');
const fs = require('fs');
const history = createMemoryHistory({
  initialEntries: ['/', '/next', '/last'],
  initialIndex: 0
});
const modules = [];
const extractAssets = (assets, chunks) => Object.keys(assets)
    .filter(asset => chunks.indexOf(asset.replace('.js', '')) > -1)
    .map(k => assets[k]);

export default (req, res, next) => {
    const filePath = path.resolve(__dirname, '..', '..', 'build', 'index.html');
    fs.readFile(filePath, 'utf8', (err, htmlData) => {
        if (err) {
            console.error('err', err);
            return res.status(404).end();
        }
        const sheet = new ServerStyleSheet();
        const body = ReactDOMServer.renderToString(
            sheet.collectStyles(<Provider store={store}>
              <ConnectedRouter history={history}>
                  <Loadable.Capture report={m => modules.push(m)}>
                       <App />
                  </Loadable.Capture>
              </ConnectedRouter>
            </Provider>)
        );
        const helmet = Helmet.renderStatic();
        console.log('title', helmet.title.toString());
        console.log('meta', helmet.meta.toString());
        console.log('link', helmet.link.toString());
        const styleTags = sheet.getStyleTags();
        const extraChunks = extractAssets(manifest, modules)
        .map(c => `<script type="text/javascript" src="/${c}"></script>`);
            return res.send(
                htmlData.replace(
                    '<html>',
                    `<html ${helmet.htmlAttributes.toString()}>`
                ).replace(
                    '<head>',
                    `<head>
                        ${helmet.title.toString()}
                        ${helmet.meta.toString()}
                        ${helmet.link.toString()}
                    </head>`
                ).replace(
                        '</head>',
                        `${styleTags}</head>`
                    ).replace(
                    '<div id="root"></div>',
                    `<div id="root">${body}</div>`
                ).replace(
                    '<body>',
                    `<body ${helmet.bodyAttributes.toString()}>`
                ).replace(
                    '</body>',
                    extraChunks.join('') + '</body>'
                )
            );
        });
};

1 个答案:

答案 0 :(得分:1)

这里的代码看起来不错。渲染后的Helmet.renderStatic()可以为您提供渲染时添加的所有内容。

它是否在客户端工作?如果您在Chrome Dev工具中查看DOM,您会看到标题,元数据标签吗? 如果没有,则组件中的代码设置数据有问题。

如果它在客户端工作,它会变得更加棘手,可能是组件中加载的Helmet与您在SSR代码中导入的Helmet不同。例如,如果您将应用程序代码与webpack捆绑在一起,就会发生这种情况,但这似乎并非如此。