第一章 使用 react-router 创建express服务器
npm install express
第一节 配置server.js
新建 server/server.js.js
import path from 'path';
import fs from 'fs';
import express from 'express';
import React from 'react';
import ReactDOMServer from 'react-dom/server';
+ import App from '../src/containers/App';
在src/index 文件中
ReactDOM.hydrate(<App />, document.getElementById('root'));
第二节 配置babel
npm install @babel/polyfill @babel/register @babel/preset-env @babel/preset-react
应该安装的 Babel 包是@Babel/polyfill,它编译诸如 async/await;@Babel/register 这样的函数来告诉 Babel 它应该使用.Js 拓展; @Babel/preset-env 和@Babel/preset-React 来配置 Babel 使用 React:
server/index.js
require('@babel/polyfill');
require('@babel/register')({
presets: ['@babel/preset-env', '@babel/preset-react'],
});
require('./server');
在npm中进行配置
第三节 使用browserRouter来进行渲染
在运行 npm run ssr 命令之前,您应该始终在 Node.js 服务器使用构建版本之前执行 npm run build。但是,如果现在运行 npm 运行 ssr 命令,就会收到一个错误消息,说 BrowserRouter 需要一个 DOM 来渲染。由于反应路由器的设置方式,使用 SSR 时需要使用 StaticRouter 组件,而不是 BrowserRouter:
https://github.com/react-static/react-static/issues/343
我已经上传了问题解决
但是最终渲染的样子是这样的,不知道真不正确
第二章 使用React Helmet添加头部标签
假设您希望您的应用程序被搜索引擎索引,那么您需要为爬虫设置头标记,以标识页面上的内容。这是您希望为每个路由动态地执行的操作,因为每个路由都有不同的内容。在反应应用中设置这些头部标签的一个流行包是 React Helmet,它支持 SSR。您可以安装反应头盔与 npm:
npm install react-helmet
第一节 在需要的组件中使用 react-helmet
import React from 'react';
import styled from 'styled-components';
+ import Helmet from 'react-helmet';
...
const Header = () => (
+ <>
+ <Helmet>
+ <title>Q&A Feed</title>
+ <meta name='description' content='This is a Community Feed project build with React' />
+ </Helmet>
<HeaderWrapper>
<Title>Q&A Feed</Title>
</HeaderWrapper>
+ </>
);
export default Header;
第二节 在server.js中设置
import path from 'path';
import fs from 'fs';
import express from 'express';
import React from 'react';
import ReactDOMServer from 'react-dom/server';
import { StaticRouter as Router } from 'react-router-dom';
+ import Helmet from 'react-helmet';
...
app.get('/*', (req, res) => {
const context = {};
const app = ReactDOMServer.renderToString(
<Router location={req.url} context={context}>
<App />
</Router>,
);
+ const helmet = Helmet.renderStatic();
const indexFile = path.resolve('./build/index.html');
fs.readFile(indexFile, 'utf8', (err, data) => {
if (err) {
console.error('Something went wrong:', err);
return res.status(500).send('Oops, better luck next time!');
}
data = data.replace('<div id="root"></div>', `<div id="root">${app}</div>`);
+ data = data.replace('<meta name="helmet"/>', `${helmet.title.toString()}${helmet.meta.toString()}`);
return res.send(data);
});
});
第三节 在HTML中设置相关的参数
在这个文件的最后一行,你已经定义了 < meta name = " Helmet"/> 元素应该被 React Helmet 创建的 title 和 meta 标签所取代。要使用这些标记替换此元素成为可能,请将此元素添加到 public 目录中的 index. html 中。此外,你必须删除现在已经由 React Helmet 创建的 title 元素:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no"
/>
<meta name="theme-color" content="#000000" />
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
+ <meta name="helmet" />
- <title>React App</title>
</head>
...
附录
参考:https://github.com/PacktPublishing/React-Projects/tree/ch4-initial