概述
前言
什么是服务端渲染呢?在使用单页面应用框架(如:react、vue等)时,我们的dom树的构建构建流程是
加载js->请求所需数据->渲染dom树
,
也就是说我首次http请求加载过来的仅仅是一个空壳子。如下
<!doctype html>
<html>
<title>ssr</title>
<body>
<div id="root"></div>
</body>
<script src="/vendor/bundle.js"></script>
</html>
这样的缺点有哪些?
1、不利于SEO (搜索引擎优化),搜索引擎在抓取我们的网页的时候,获取的仅仅是这一点信息,当我们的用户去搜索我们的网站的时候,相关信息就很少。
2、客户端渲染,当我们打包的js文件过大的时候,加载延迟会很大,白屏时间会很长,用户体检较差,有些用户不愿意等,就关闭了我们的网页,达不到预期的宣传效果。
解决思路
既然这种加载的流程不行,我们就换种方式加载。考虑让一次http加载出更详细的网页信息。这里就要用到服务端渲染
了。
想一想传统的react、vue页面 是如何显示在浏览器中的:
1、用webpack、gulp等这些前端构建工具对 我们写好的页面进行打包
2、会用一个render函数来渲染dom
那么我们就在服务端模拟这个流程,将渲染出来的html保存在一个变量里,然后将这些数据返回给客户端,这样不就可以显示解决上面的问题了吗
实践
在react的刚好提供了这样一个服务端渲染的函数 renderToString
它放在react-dom/server
里 他会对react组件进行渲染
试一下,我们要在服务端安装 react ,而且 通常我们的react里包含了许多es6一些语法 :箭头函数、import等。我们也要在服务端支持这些语法。
先安装babel相关
yarn add @babel/register @babel/preset-react @babel/preset-env
以及babel的plugins:@babel/plugin-transform-runtime用与运行时转换
yarn add @babel/plugin-transform-runtime
在服务端代码入口的第一行注册babel
require('@babel/register')({
presets: ['@babel/preset-react','@babel/preset-env'],//转换es6以及react jsx
plugins: ["@babel/plugin-transform-runtime"]
});
这样就可以在服务端代码中使用 es6语法了
const express = require('express');
const app = express();
const React = require('react');
const {renderToString} = require('react-dom/server');
function App(){
return (<div>hello world</div>)
}
app.get('/',function(req,res){
const content = renderToString(<App />));
res.send(`
<!doctype html>
<html>
<title>ssr</title>
<body>
<div id="root">${content}</div>
</body>
</html>
`);
});
我们发现可以正常显示了 hello world
但是这里生成的仅仅是静态的html 没有交互能力,我们需要为他添加交互能力 JavaScript 即同构
简单来说就是“同种结构的不同表现形态
”。在这里我们用更通俗的大白话来解释react同构就是:
同一份react代码在服务端执行一遍,再在客户端执行一遍。
我们重新分割一下代码
App.js
import React from 'react';
import Generetor from '../app/src/components/Dragging/generator';
class App extends React.Component {
sayHello(){
alert('hello')
}
render(){
return (
<div onClick={this.sayHello()}>
hello world
</div>
);
}
}
export default App;
ssr_server.js
import React from "react";
import App from "./App";
module.exports = <App/>;
ssr_clients.js
import React from 'react';
import {hydrate} from 'react-dom';
import 'antd/dist/antd.css';
import App from './App';
hydrate(<App/>,document.getElementById("root"));
app.js
import App from './ssr_server'
const express = require('express');
const app = express();
const React = require('react');
const {renderToString} = require('react-dom/server');
app.get('/',function(req,res){
const content = renderToString(<App />));
res.send(`
<!doctype html>
<html>
<title>ssr</title>
<body>
<div id="root">${content}</div>
</body>
</html>
`);
});
我们用webpack将 ssr_client打包生成js 插入到html中即可
我们配置服务端wepack.config.js
const path = require('path');
const nodeExternals = require('webpack-node-externals');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const MiniCssPlugin = require("mini-css-extract-plugin");
module.exports = {
// 入口文件
entry: './SSR/ssr_client.js',
output: {
filename: 'bundle.js',
path: path.join(__dirname, '/public/dist/ssr')
},
module: {
// 配置相应的规则
rules: [
{
test: /.css$/,
use: [ MiniCssPlugin.loader,'css-loader', 'postcss-loader']
}, {
test: /.js[x]?$/,
use: {
loader:'babel-loader',
options: {
presets: ["@babel/react", "@babel/preset-env"],
plugins: ["@babel/plugin-proposal-class-properties"]
}
},
exclude: /node_modules/,
}, {
test: /.less$/,
use: [MiniCssPlugin.loader,
{ loader: 'css-loader', options: { importLoaders: 1 } },
'less-loader'],
},{
test: /.(png|jpe?g)/i,
use: [
{
loader: "url-loader",
options: {
name: "./img/[name].[ext]",
limit: 10000
}
},
{
loader: "img-loader"
}
]
}
]
},
target: 'node', //不将node自带的诸如path、fs这类的包打进去
// 配置相应的插件
plugins: [
new MiniCssPlugin({
filename:'bundle.css'
})
]
};
由于打包过程中会遇到es7、es6语法 需要安装@babel/plugin-proposal-class-properties支持es7 es6的之前装过了,
打包之后生成css 以及js文件
执行
webpack --config webpack.config.js
产出
___dist
______ssr
________bundle.js
________bundle.css
修改app.js
import App from './ssr_server'
const express = require('express');
const app = express();
const React = require('react');
const {renderToString} = require('react-dom/server');
app.get('/',function(req,res){
const content = renderToString(<App />));
res.send(`
<!doctype html>
<html>
<title>ssr</title>
<head>
<link rel="stylesheet" type="text/css" href="/ssr/bundle.css" >
</head>
<body>
<div id="root">${content}</div>
</body>
<script src="/ssr/bundle.js"></script>
</html>
`);
});
启动服务器 访问 localhost:3000即可看到服务端渲染的界面
最后
以上就是鲤鱼宝贝为你收集整理的react 服务端渲染 基本操作的全部内容,希望文章能够帮你解决react 服务端渲染 基本操作所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复