react的SSR(1)

需求分析

之前做react项目的时候,最早的首屏需要加载的大小在5M左右,也就导致了特别慢的访问速度,后来更改了webpack的配置,启动压缩,分离依赖等各种搞法弄完之后,还有有1M的大小需要加载。如果第一次进入页面,还需要加载依赖,大小大概在1.5M左右。

极慢的首屏访问速度严重影响了用户体验,抵消了那次改版的所有优点,后由于我因为某些愿意离职,也就没有再关注过这方面了,之后入职一直在从事react-native,也一直没有搞过这方面了,赶上最近比较闲,打算用服务端渲染的方法重写一下我个人的小网站,练练手的同时也丰富一下网站的内容,当然丰富的内容就不在这个笔记里写了,这里主要写服务端渲染。

项目搭建

首先我们来搭建一个最简单的项目,大概需要的babel,webpack,express,react,另外还需要一个零零碎碎的依赖,具体可以再github里看,会在最后面放上我的仓库地址。

首先建立一个项目

npm init -Y

然后新建一个webpack文件

var path = require('path')
var webpack = require('webpack')

module.exports = {
    entry: {
        main: './app/index.js'
    },
    output: {
        filename: '[name].js',
        path: path.join(__dirname, 'dist'),
        publicPath: '/'
    },
    resolve: {
        extensions: ['.js', '.jsx']
    },
    module: {
        rules: [
            {
                test: /\.jsx?$/,
                loaders: ['babel-loader'],
            }
        ]
    }
}

这个就是一个最最基本的webpack设置了,然后我们在package文件里添加

"scripts": {
    "start": "nodemon index.js",
    "build": "webpack",
  },

这样写之后运行

npm run start

是启动express服务,而执行

npm run build

是执行react的打包命令。

为什么这个东西需要分开呢?因为react的服务端渲染是在服务端渲染首屏,但是由webpack打包出来的js文件和spa模式下的react项目并没有区别,准确说是在运行的模式上没什么区别,但是具体写法上还有些许的不同。

react的ssr在服务端渲染出来的html是没有任何的事件的,还需要webpack打包出来的js再次绑定事件,这方面的东西一定要注意,很容易出现bug,并且出现了不好分析。

在webpack里写了入口和出口,所以下面我们就要建立入口文件和出口文件夹。

我们建立一个名字叫app的文件夹,里面存放react的内容。在app的文件夹内建立一个index.js的文件作为webpack打包的入口文件

import Hello from './hello'
import ReactDOM from 'react-dom'
import React from 'react'

ReactDOM.hydrate(<Hello />, document.getElementById('root'))

建立一个名为hello.js的文件

import React from 'react'

export default class Home extends React.Component {
    render () {
        return <div onClick={this.click}>hello world</div>
    }

    click(){
        alert(123)
    }
}

为什么只有一个组件也要分开呢?因为等会服务端也要读取组件信息,因为服务端没有index.js文件中的document对象,这个对象只在浏览器中有,所以index.js文件服务器是读不懂的,只能读取hello.js文件。

这个问题后面我们可以用其他方案避免,但是现在只是为了最简单的做出来一个react的服务端渲染,所以做最简单的处理。毕竟最简单的才做容易理解。

好了,目前我们的react方面就做好了,我们只需要建立一下出口目录之后就可以执行

npm run build

这样打包过后的文件就出现在./dist文件夹内了。

下面我们开始写express的文件,因为express不能用import,所以我们要先用babel转一遍,所以在项目下建立index.js文件

require('babel-core/register')()

require('babel-polyfill')
require('./server')

上面两个引用用来翻译,后面的才是我们真正的文件,所以我们要继续建立server.js文件

import express from 'express';
import React from 'react';
import { renderToString } from 'react-dom/server';
import Hello from './app/hello'
import template from './template';

const server = express();

server.use('/assets', express.static(__dirname + '/dist'));

server.get('/', (req, res) => {
  const appString = renderToString(<Hello/>);

  res.send(template({
    body: appString,
    title: 'Hello World from the server',
  }));
});

server.listen(8080);
console.log('listening');

这里我们看到引入了刚刚写的组件,Hello组件。这里的关键是renderToString函数,这个函数可以把组件变成html的字符串,这也是react可以进行服务端加载的核心。

而template是一个自己写的简易的模板,内容如下

export default ({ body, title}) => {
  return `
    <!DOCTYPE html>
    <html>
      <head>
        <title>${title}</title>
      </head>
      
      <body>
        <div id="root">${body}</div>
      </body>
      
      <script src="/assets/main.js"></script>
    </html>
  `;
};

下面执行

npm run start

这样就可以启动express的服务了,然后去我们本地的8080端口就可以看到效果了。

这就是一个最简单的react服务端渲染。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值