如何在 React 中进行部分服务端渲染
介绍
服务器端代码可以与 React 和其他前端框架很好地配合使用,即使是纯前端应用程序也可以使用一些简单的工具有效地利用服务器端渲染的优势。
在本指南中,我们将了解服务器端渲染以及如何使用它来大幅提高 React 应用程序的性能。
服务端渲染
服务器端渲染 (SSR) 在服务器上渲染 SPA(单页应用程序),然后将其发送到客户端。然后,客户端解释页面并将其显示在前端,之后应用程序的控制权由框架接管。
SSR 带来的一个重要性能提升是应用程序的快速初始加载。您可能已经注意到,通过任何框架的 CLI 旋转本地开发服务器需要很长时间才能首次呈现应用程序。SSR 从服务器本身发送一个完全加载的应用程序,因此服务器的计算能力可以补偿客户端使用的处理能力。由于服务器非常强大,因此 HTML 页面包可以非常快速地发送。随着速度的提高,您的应用程序将对搜索引擎优化的抓取机器人可见。
在 React 中实现
设置
确保您的机器上安装了Nodejs和npm(至少版本 8 或更高版本)以及代码编辑器和 Web 浏览器(最好是 Chrome 或 Firefox)。
使用 create-react-app 创建一个新项目:
npx create-react-app react-ssr-app
通过删除logo.svg、所有相关导入以及App.js中的一些样板来清理项目模板。您的App.js应如下所示:
import React from 'react';
const App = () => {
return (
<div className="app">
<h2>hello from app!</h2>
</div>
);
}
export default App;
运行npm start来启动本地开发服务器。您可以在浏览器中的localhost:3000上看到应用程序启动并运行(create-react-app 会自动为您执行此操作),并显示一条简单消息:**hello from app!** 现在,下一步是在此应用程序中进行更改,以便从服务器呈现相同的应用程序。
用 hydrate() 替换 render()
在index.js中将render()方法替换为hydrate()。
//...
ReactDOM.hydrate(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
...//
Hydration 通过将事件监听器附加到已经存在的标记来确保所有功能保持完整,以便搜索引擎机器人可以索引从服务器预加载的标记。
安装库和包
Express是一个建立在Nodejs之上的 Web 框架,提供 HTTP 实用方法和中间件,仅用几行代码即可构建服务器。
npm install express
接下来,安装babel来转换我们本地的 JSX 代码,并安装ignore-styles来忽略我们节点环境中导入的样式。
npm install @babel/register @babel/preset-env @babel/preset-react ignore-styles
构建服务器端代码
在根目录中创建一个名为server的文件夹,其中包含两个文件:index.js和server.js。
后者将包含服务器的所有代码,而前者将被视为入口点。
react-ssr-app
├── src -- src folder
└── server -- server folder
├── server.js -- server-side rendering code
├── index.js -- entry point for the server
创建服务器
服务器设置在节点环境中使用 express 完成。选择一个端口(可以是任何端口,只要该端口上没有进程正在运行)并调用express()来初始化 express 应用程序。使用 router 方法设置一个简单的路由并告诉应用程序监听该端口。
const express=require('express');
const PORT = 8080;
const app = express();
const router = express.Router()
router.use('^/$', serverRenderer)
app.use(router)
app.listen(PORT, () => {
console.log(`react app running on port ${PORT}`)
})
从服务器渲染 App.js
下一步是从服务器渲染App.js文件,因此导入该文件。要处理所有文件操作,需要内置文件系统模块 ( fs ) 和路径模块;要渲染 React 应用程序,需要React和ReactDOMServer。
创建一个接受三个参数的简单函数:req、res和next。目标是在 build 文件夹中创建一个静态 HTML 文件,并使用 express 应用程序在服务器上提供该文件。接下来,在ReactDOMServer上调用renderToString()方法,使用router.use()在创建的路由上将整个app.js呈现为服务器上的字符串。
const path=require('path');
const fs=require('fs');
const express=require('express');
const React=require('react');
const ReactDOMServer=require('react-dom/server');
import App from '../src/App'
const PORT = 8080
const app = express()
const router = express.Router()
const serverRenderer = (req, res, next) => {
fs.readFile(path.resolve('./build/index.html'), 'utf8', (err, data) => {
if (err) {
console.error(err)
return res.status(500).send('An error occurred')
}
return res.send(
data.replace(
'<div id="root"></div>',
`<div id="root">${ReactDOMServer.renderToString(<App />)}</div>`
)
)
})
}
router.use('^/$', serverRenderer)
router.use(
express.static(path.resolve(__dirname, '..', 'build'))
)
app.use(router)
app.listen(PORT, () => {
console.log(`SSR running on port ${PORT}`)
})
处理入口点
该应用程序不会从服务器渲染任何样式,因此需要ignore-styles和babel来确保Nodejs中的导入按要求工作,并且代码转换不会出现任何问题。最后,需要server.js文件,因为节点应用程序将运行此文件来执行所有服务器端代码。
require('ignore-styles')
require('@babel/register')({
ignore: [/(node_modules)/],
presets: ['@babel/preset-env', '@babel/preset-react']
})
require('./server')
测试
在这里,您将测试刚刚创建的服务器。您不会运行前端,因此请通过终止该终端来取消由npm start启动的所有进程。
由于您要在 build 文件夹中提供index.html文件,因此首先需要创建该 build 文件夹。在根目录中,运行以下命令:
npm run build
您将看到创建了一个包含index.html文件的 build 文件夹。现在使用以下命令运行节点应用程序:
node server/index.js
您首先会在控制台上看到以下消息:
SSR 在 8080 端口上运行
现在在浏览器中运行localhost:8080即可查看浏览器上呈现的app.js文件。
如果您收到任何警告或错误,您可以通过更新package.json文件并运行命令npm i来使用本指南中使用的这些库的精确版本。
{
..//
"dependencies": {
"@babel/preset-env": "^7.6.3"<span class="hljs-punct
免责声明:本内容来源于第三方作者授权、网友推荐或互联网整理,旨在为广大用户提供学习与参考之用。所有文本和图片版权归原创网站或作者本人所有,其观点并不代表本站立场。如有任何版权侵犯或转载不当之情况,请与我们取得联系,我们将尽快进行相关处理与修改。感谢您的理解与支持!
请先 登录后发表评论 ~