前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >react 同构初步(5)

react 同构初步(5)

作者头像
一粒小麦
发布2020-01-02 17:19:01
8730
发布2020-01-02 17:19:01
举报
文章被收录于专栏:一Li小麦一Li小麦

这是一个即时短课程的系列笔记。本笔记系列进度已更新到:https://github.com/dangjingtao/react-ssr

服务端性能优化思路

ssr把原来在客户端做的渲染工作摆到了服务端。在减少了客户端性能压力的同时,增加了服务端的工作量。那作为一个前端开发者,如何去优化服务端的性能呢?

一个最常见的思路就是负载均衡。如果把我们的服务端比作一个饭馆,用户请求服务就是到饭馆吃饭。那么当前用户,服务端,接口层的的关系是这样的:

在当前的服务端代码中,饭馆能提供什么,上菜速度怎样,全由厨房决定。随着用户的增加,用户A说:我要吃饺子,用户B说,我要吃馄炖,用户C说我要吃汤圆——此时服务器的性能将急剧下降。

但如果我把饭馆定义为一个"用户吃饭的地方",思路将会开拓许多。我们可以在这家饭馆附近租金便宜的地方开设几间厨房。三个用户在点菜之后,饭馆将它转发到对应的厨房去做菜。厨房A专门受理饺子的订单,厨房B专门受理馄炖的订单,厨房C专门受理汤圆的订单。做好之后送回饭馆。那么饭馆就节省了在闹市开设厨房的租金。同时也满足了更多的用户需求。

假设饭馆的名气越来越大,来吃饭的用户越来越多,饭馆已经坐不下了。如何更好地满足用户的需求呢?

在此介绍的另外一个思路就是,降级渲染。饭馆无法容纳更多人,可以考虑把食材做成速冻产品,让用户拿回去自己煮着吃。换成专业一点的语言就是:如果用户量到达一定的阀值,就放弃ssr,重回csr。

降级渲染

首先要实现完整的csr。可以安装html-webpack-pluginwebpack插件。

代码语言:javascript
复制
npm i html-webpack-plugin -S

然后在webpack.client.js配置如下:

代码语言:javascript
复制
const path=require('path');
// 引入插件
const HtmlWebpackPlugin =require('html-webpack-plugin');

module.exports={
    mode:'development',
    entry:'./client/index.js',
    output:{
        filename:'bundle.js',
        path:path.resolve(__dirname,'public')
    },
    // 新增插件
    plugins:[
        new HtmlWebpackPlugin({
            filename:'index.csr.html', // 定义渲染的html
            template:'src/index.csr.html', // 模版
            inject:true
        })
    ],
    module:{
        rules:[
            {
                test:/\.js$/,
                loader:'babel-loader',
                exclude:/node_modules/,
                options:{
                    presets:['@babel/preset-react',['@babel/preset-env']]
                }
            },
            {
                test:/\.css$/,
                use:['style-loader','css-loader']
            }
        ]
    }
}

接下来就在src下新建index.csr.html

代码语言:javascript
复制
<!-- scr 模版,和ssr基本一致 -->
<html>
<head>
    <meta charset="UTF-8">
    <title>react ssr->csr</title>

<body>
    <div id="root"></div>
</body>
</head>
</html>

执行npm start,你会发现在public文件夹下多出了一个index.csr.html。内容和ssr渲染的一毛一样:

代码语言:javascript
复制
<!-- scr 模版,和ssr基本一致 -->
<html>
<head>
    <meta charset="UTF-8">
    <title>react ssr->csr</title>

<body>
    <div id="root"></div>
<script type="text/javascript" src="bundle.js"></script></body>
</head>
</html>

就是多了一个bundle引入,正是我们想要的。

然后回到服务端,定义一个渲染html模板的方法:

代码语言:javascript
复制
import path from 'path';
import fs from 'fs';

// 开启csr方法
const csrRender=(res)=>{
    // 读取scr下的html模板,直接返回
    // 读取当前工作目录下的,index.csr.html
    const filename=path.resolve(process.cwd(),'public/index.csr.html');
    // 同步读取
    const html=fs.readFileSync(filename,'utf-8');
    return res.send(html);
}

然后在请求方法中直接判断,以请求参数_model作为flag:

代码语言:javascript
复制
app.get('*', (req, res) => {
    // 各种开启条件
    if(req.query._mode=='csr'){
        csrRender(res);
    }
    // ...
}

访问http://localhost:9000/about?_mode=csr,就会发现网络请求走的scr路径(title由react ssr变成了 react ssr->csr)

此时浏览器有一个报错:

代码语言:javascript
复制
Warning: Expected server HTML to contain a matching <div> in <div>.

是因为在纯客户端应用时,不能使用注水方法。

代码语言:javascript
复制
// 客户端 client/index.js
if(window.__context){
    // 服务端渲染,注水:不需render
    ReacDom.hydrate(Page, document.querySelector('#root'));
}else{
    ReacDom.render(Page, document.querySelector('#root'));
}

由此,降级逻辑完成。

样式模块化

上节留了一个坑,就是样式。我们在webpack里配置样式,直接是以style插入到html代码中的,所以你只要写了样式,就必定是影响全局的。

css-loader可以配置模块化的样式,在webpack中配置rules:

代码语言:javascript
复制
// webpack.server.js
{
    test: /\.css$/,
    use: [
        'isomorphic-style-loader',
        {
            loader:'css-loader',
            options:{
                modules:true
            }
        }
    ]
}

// webpack.client.js
{
    test:/\.css$/,
    use:[
      'style-loader',
      {
        loader:'css-loader',
        options:{
            modules:true
        }
    }]
}

然后尝试测试一下,新建index.css:

代码语言:javascript
复制
.title{
    color:red;
}
.container{
    background: #f5f5f5;
}

然后在index组件中具名引入:

代码语言:javascript
复制
import styles from '../style/index.css';
function Index(){
  // ...
  return <div className={styles.container}>
    <h1 className={styles.title}>react ssr</h1>
    {/* ... */}
  </div>
}

那么样式就出来了。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-12-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 一Li小麦 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 服务端性能优化思路
  • 降级渲染
  • 样式模块化
相关产品与服务
负载均衡
负载均衡(Cloud Load Balancer,CLB)提供安全快捷的流量分发服务,访问流量经由 CLB 可以自动分配到云中的多台后端服务器上,扩展系统的服务能力并消除单点故障。负载均衡支持亿级连接和千万级并发,可轻松应对大流量访问,满足业务需求。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档