Правильно настроить серверную часть шлема
Шлем прямо сейчас возвращает пустые строки на сервере. Я не уверен, что документация объясняет это действительно хорошо, и существующие проблемы редко помогают!
Выпуск -
`console.log('title', helmet.title.toString());
console.log('meta', helmet.meta.toString());
console.log('link', helmet.link.toString());`
все пустые, кроме заголовка, который входит <title data-react-helmet="true"></title>
Здесь существует очень похожая проблема - шлем-реактив выводит пустые строки на стороне сервера
Но он уже выбросил приложение для 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 ответ
Код здесь выглядит хорошо. Helmet.renderStatic() после рендеринга должен дать вам все, что вы добавили во время рендеринга.
Это работает на стороне клиента? Если вы посмотрите на DOM в чем-то вроде инструментов Chrome Dev, вы увидите заголовок, метаданные? Если нет, то с кодом в вашем компоненте, устанавливающим данные, что-то не так.
Если он работает на стороне клиента, он становится хитрее, и может случиться так, что шлем, загруженный в ваш компонент, отличается от того, который вы импортируете в своем коде SSR. Это может произойти, если вы, например, связываете код приложения с веб-пакетом, но здесь это не так.