我是靠谱客的博主 鲤鱼宝贝,最近开发中收集的这篇文章主要介绍react 服务端渲染 基本操作,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

前言

什么是服务端渲染呢?在使用单页面应用框架(如: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 服务端渲染 基本操作所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(26)

评论列表共有 0 条评论

立即
投稿
返回
顶部