react服务器端渲染原理解析和实现(一)——初探:demo和组件渲染

客户端渲染(CSR)和服务端渲染(SSR)

CSR是什么流程?

  1. 客户端(浏览器)请求服务器,服务器返回静态html文件,css,js文件等;
  2. 客户端解析html静态文件,并下载css和js文件进行解析;

SSR是什么流程?

 1. 服务器通过模板引擎解析html,返回给用户端客户端html字符串。
 2. 客户端解析html字符串,读取静态js文件,然后进行解析;

CSR缺点

  学过react的小伙伴都知道,react可以用来快速开发单页面和多页面应用。但是这样做出来的网站有些缺点

  • seo问题
      什么是seo问题呢?seo称为搜索引擎优化,react客户端渲染做出来的网站整个网站内部标签只有一个#root,还有一大堆的js文件,搜索引擎在爬取你的网站的时候会很难抓取到你网站的关键信息,虽然很多这样的网站多做了meta标识,降低了搜索引擎爬取的难度,但是这指标不治本。
  • 首屏加载问题
      我们都知道单页面应用就只有一个root标签,浏览器加载js的时候会会消耗比较长的时间,在这个期间用户会等待很长,这个就被称为首屏加载问题。

  回到主题,我们来具体了解一下react服务端渲染是怎么实现的,这需要我们自己配置webpack,所以需要你掌握webpack相关的基础知识。我们的基本项目目前为止需要安装的包有:
在这里插入图片描述
在这里插入图片描述

  • webpack配置
      因为我们是服务端渲染,所以我们需要两套webpack.config.js文件,一套解析客户端的代码,一套解析服务端的代码(根据配置文件创建文件夹和文件)。当然我这里配置文件只会处理js,所以不必配置很多laoder。
    • webpack.base.js
        这里需要安装几个包,建议安装最新版,不过向后兼容也可以.。
    	module.exports = {
        module: {
            rules: [
                {
                    test: /\.jsx?$/,
                    exclude: '/node_modules/',
                    loader: 'babel-loader',
                    options: {
                        presets: ["@babel/react", ['@babel/env', {
                            targets: {
                                browsers: ['last 2 versions']
                            }
                        }]]
                    }
                }
            ]
        }
    };
    
    • webpack.client.js
        这里需要安装webpack-merge包,这是一个合并多个webpack.config.js的包
    const path = require('path');
    const merge = require('webpack-merge');
    const baseConfig = require('./webpack.base');
    const clientConfig = {
        entry: './src/client/index.js',
        mode: 'development',
        output: {
            filename: 'index.js',
            path: path.resolve(__dirname, 'public'),
        }
    };
    module.exports = merge(baseConfig, clientConfig);
    
    • webpack.server.js
        这里需要安装webpack-node-externals包,这是一个将引用到的node_modules下面的包也打包到文件里面,因为我们后台用的express框架,不然的话我们在打包之后express框架就被排除了。
    const path = require('path');
    const path = require('path');
    const nodeExternals = require('webpack-node-externals');
    const merge = require('webpack-merge');
    const baseConfig = require('./webpack.base');
    const serverConfig = {
        target: 'node',
        entry: './src/server/index.js',
        mode: 'development',
        output: {
            filename: 'bundle.js',
            path: path.resolve(__dirname, 'build'),
        },
        externals: [nodeExternals()],
    };
    
    module.exports = merge(baseConfig, serverConfig);
    
  • .babelrc文件配置
      babelrc文件是必须的,位于和webpack.base.js同级目录下,由于我们会写装饰器写法,所以我这里也配置了装饰器写法相关的babel配置
{
  "presets": [
    "@babel/preset-env"
  ],
  "compact" : true,
  "plugins": [
    "@babel/plugin-transform-runtime",
    [
      "@babel/plugin-proposal-decorators",
      {
        "legacy": true
      }
    ],
    [
      "@babel/plugin-proposal-class-properties",
      {
        "loose": true
      }
    ]
  ]
}

  文件建好之后,我们看下我们的项目目录
在这里插入图片描述
  需要安装的包在配置文件里面都可以查看到,若报错根据报错信息再安装相应的包。除此之外我们还需要安装express(后台node框架),react,react-dom

相当重要的一点,提高效率的方式

在这里插入图片描述
  这个package.json文件的配置比较重要,你不这样配置的话,需要每次都要build,每次都要start。而用上了上面的配置,我们只需要每次启动的时候输入yarn dev 或npm run dev。这部分需要安装的包有:nodemon、npm-run-all

进入主题

  前面我们在webpack.server.js中配置了服务器端的react代码的入口文件是
./src/server/index.js
  我们需要新建server文件夹,新建index.js,具体的代码如下图。

import express from 'express'
import React from 'react'
const app = express();

// 这里的*是因为后面我们需要做路由,服务器端不可能自己新建多个路由,所以直接 * 完事儿
app.get('*', (req, res) => {
	const content = 'hello world , this is the first SSR demo'
	const html = `
        <!doctype html>
        <html lang="en">
            <head>
                <title>hello</title>
                <body>
                <!-- 这里的#root由于后面我们需要单页面应用的渲染,就在这里加上 -->
               <div id="root">${content }</div>
               <script src="/index.js"></script>
                </body>
            </head>
        </html>`
    res.send(html ) // 调用express框架的res.send方法,想客户端返回html字符串,
   					// 若出现跨域情况,可用res.jsonp()代替,
   					// 这个方法大家可以平时进行mock数据时可以用到
});

app.listen('3000');

  这样一个小小的ssr demo就完成了,你可以尝试用yarn dev启动项目,然后在3000端口进行访问

怎么渲染组件呢?

  通过上一个demo可以看到ssr服务器渲染好的html字符串已经可以在客户端运行,而且你会发现打开速度非常快,这是因为我们服务端解析的是字符串而不是一个庞大的js文件。
  那么有些同学就会问了,那我们怎么渲染组件呢?

  • 新建组件
    在src目录下新建一个pages的文件夹,然后再新建一个home文件夹,再home文件夹里面新建一个index.js,具体代码如下,该组件可以写成无状态组件。
import React, {Component, Fragment} from 'react'

export default class Home extends Component {
    render() {
        return (
            <Fragment>
                this is SSR dell!
            </Fragment>
        )
    }
}
  • 引入组件
    在我们之前写好的server下面的index.js添加如下代码
import Home from '../pages/home'
import {renderToString} from 'react-dom/server'

app.get('*', (req, res) => {
 // 渲染成字符串,这个方法会讲组件渲染成一个字符串,
 // 注意:这个组件上面的事件是不会被渲染上去的,因为事件渲染成字符串之后被省略掉了,
 // 这个问题我们下一章解决
const home = renderToString(
        <Home />
    );
})
const html = `
.... 
<div id="root">${home}</div>
`

  好了今天的ssr学习就学习完了

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值