路白-react.js 服务端渲染&同构

本文介绍了React.js服务端渲染的发展背景,通过示例代码展示了如何创建一个服务端渲染的应用,详细解释了同构流程,包括路由的处理。内容涵盖了从传统服务器端渲染到客户端渲染,再到服务端渲染的演变,以及如何通过同构技术优化SEO和用户体验。
摘要由CSDN通过智能技术生成

示例代码地址,需要自行下载

背景

  • 第一阶段

很久以前, 一个网站的开发还是前端和服务端在一个项目来维护, 可能是用php+jquery.
那时候的页面渲染是放在服务端的, 也就是用户访问一个页面a的时候, 会直接访问服务端路由, 由服务端来渲染页面然后返回给浏览器。

也就是说网页的所有内容都会一次性被写在html里, 一起送给浏览器。
这时候你右键点击查看网页源代码, 可以看到所有的代码; 或者你去查看html请求, 查看"预览", 会发现他就是一个完整的网页。

  • 第二阶段

但是慢慢的人们觉得上面这种方式前后端协同太麻烦, 耦合太严重, 严重影响开发效率和体验。
于是随着vue/react的横空出世, 人们开始习惯了纯客户端渲染的spa.

这时候的html中只会写入一些主脚本文件, 没有什么实质性的内容. 等到html在浏览器端解析后, 执行js文件, 才逐步把元素创建在dom上。
所以你去查看网页源代码的时候, 发现根本没什么内容, 只有各种脚本的链接。

  • 第三阶段

后来人们又慢慢的觉得, 纯spa对SEO非常不友好, 并且白屏时间很长。
对于一些活动页, 白屏时间长代表了什么? 代表了用户根本没有耐心去等待页面加载完成.

所以人们又想回到服务端渲染, 提高SEO的效果, 尽量缩短白屏时间.

那难道我们又要回到阶段一那种人神共愤的开发模式吗? 不, 我们现在有了新的方案, 新的模式, 叫做同构。

所谓的同构理解为:同种结构的不同表现形态, 同一份react代码, 分别在两端各执行一遍。

创建一个服务端渲染的应用

  1. renderToString

spa里一定见过react-dom的render方法, 其实react-dom里还有一个renderToString方法. 咱们来查看一下他的注释.

Render a React element to its initial HTML. This should only be used on the server. React will return an HTML string. You can use this method to generate HTML on the server and send the markup down on the initial request for faster page loads and to allow search engines to crawl your pages for SEO purposes.

这个注释, 岂不是明牌说这个方法是用来做服务端渲染的? 我们来试一下

  1. Hello World
  • server.js
const express = require('express');
const app = express();
const React = require('react');
const {
   renderToString} = require('react-dom/server');
const PORT = 3000;

const App = class extends React.PureComponent{
   
  render(){
   
    return React.createElement("h1",null,"Hello World111");;
  }
};
app.get('/',function(req,res){
   
  const content = renderToString(React.createElement(App));
  res.send(content);
});
app.listen(PORT, () => {
   
    console.log(`sever listen on ${
     PORT}`)
});
  • 运行一下

node server.js

  1. webpack配置

上面咱们看起来就是服务端渲染了对吗? 虽然只是看起来实现了, 但是存在很多问题.

  • 可以用jsx语法吗

明显咱们现在是不支持jsx语法的, 根本都没有react的编译环境

  • 可以用esm吗

import {renderToString} from 'react-dom/server';

所以我们要针对服务端代码, 做一个webpack的打包工作.

  • build/webpack-server.config.js
const path = require('path');
const nodeExternals = require('webpack-node-externals');
const CopyWebpackPlugin = require('copy-webpack-plugin');
module.exports = {
   
  entry:{
   
    index:path.resolve(__dirname,'../server.js')
  },
  mode:'development',
  target:'node', // 服务端必须加上此参数
  devtool: 'cheap-module-eval-source-map',
  output:{
   
    filename:'[name].js',
    path:path.resolve(__dirname,'../dist/server')
  },
  externals:[nodeExternals()], // 打包时忽略node_module
  resolve:{
   
    alias:{
   
      '@':path.resolve(__dirname,'../src') 
    },
    extensions:['.js']
  },
  module:{
   
    rules:[{
   
      test:/\.js$/,
      use:'babel-loader', // js文件需要被babel转译
      exclude:/node_modules/
    }]
  },
  plugins: [
    new CopyWebpackPlugin([{
   
      from:path.resolve(__dirname,'../public'),
      to:path.resolve(__dirname,'../dist')
    }])
  ]
}
  • package.json添加打包的脚本

"build:server": "webpack --config build/webpack-server.config.js --watch"

  • package.json添加运行server.js的脚本(nodemon可以实现热更新)

"server": "nodemon dist/server/index.js"

运行一下

npm run build:server
npm run server

  • esm的模块引入方式已经支持了
import React from 'react';
import {
   renderToString} from 'react-dom/server';
  1. 给h1标签绑定一个click事件
import React from 'react';
import 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值