写在前面

前段时间一直在研究 react ssr技术,然后写了一个完整的 ssr开发骨架。今天写文,主要是把我的研究成果的精华内容整理落地,另外通过再次梳理希望发现更多优化的地方,也希望可以让更多的人少踩一些坑,让更多的人理解和掌握这个技术。

相信看过本文(前提是能对你的胃口,也能较好的消化吸收)你一定会对 react ssr服务端渲染技术有一个深入的理解,可以打造自己的脚手架,更可以用来改造自己的实际项目,当然这不仅限于 react ,其他框架都一样,毕竟原理都是相似的。

为什么要服务端渲染(ssr)

至于为什么要服务端渲染,我相信大家都有所闻,而且每个人都能说出几点来。

首屏等待

在 SPA 模式下,所有的数据请求和 Dom 渲染都在浏览器端完成,所以当我们第一次访问页面的时候很可能会存在“白屏”等待,而服务端渲染所有数据请求和 html内容已在服务端处理完成,浏览器收到的是完整的 html 内容,可以更快的看到渲染内容,在服务端完成数据请求肯定是要比在浏览器端效率要高的多。

没考虑SEO的感受

有些网站的流量来源主要还是靠搜索引擎,所以网站的 SEO 还是很重要的,而 SPA 模式对搜索引擎不够友好,要想彻底解决这个问题只能采用服务端直出。改变不了别人(搜索yinqing),只能改变自己。

SSR + SPA 体验升级

只实现 SSR 其实没啥意义,技术上没有任何发展和进步,否则 SPA 技术就不会出现。

但是单纯的 SPA又不够完美,所以最好的方案就是这两种体验和技术的结合,第一次访问页面是服务端渲染,基于第一次访问后续的交互就是 SPA 的效果和体验,还不影响 SEO 效果,这就有点完美了。

单纯实现 ssr 很简单,毕竟这是传统技术,也不分语言,随便用 php 、jsp、asp、node 等都可以实现。

但是要实现两种技术的结合,同时可以最大限度的重用代码(同构),减少开发维护成本,那就需要采用 react 或者 vue 等前端框架相结合 node(ssr) 来实现。

本文主要说 ReactSSR技术 ,当然 vue 也一样,只是技术栈不同而已。

核心原理

整体来说 react 服务端渲染原理不复杂,其中最核心的内容就是同构。

node server 接收客户端请求,得到当前的 req url path,然后在已有的路由表内查找到对应的组件,拿到需要请求的数据,将数据作为 props 、 context或者 store 形式传入组件,然后基于 react 内置的服务端渲染api renderToString()orrenderToNodeStream() 把组件渲染为 html字符串或者 stream流, 在把最终的 html 进行输出前需要将数据注入到浏览器端(注水),server 输出(response)后浏览器端可以得到数据(脱水),浏览器开始进行渲染和节点对比,然后执行组件的 componentDidMount 完成组件内事件绑定和一些交互,浏览器重用了服务端输出的 html节点,整个流程结束。

技术点确实不少,但更多的是架构和工程层面的,需要把各个知识点进行链接和整合。

这里放一个架构图

react ssr

从 ejs 开始

实现 ssr 很简单,先看一个 node ejs的栗子。

 // index.html  react ssr   //node ssr const ejs = require('ejs'); const http = require('http');http.createServer((req, res) => { if (req.url === '/') { res.writeHead(200, { 'Content-Type': 'text/html'  }); // 渲染文件 index.ejs ejs.renderFile('./views/index.ejs', { title: 'react ssr',  data: '首页'},  (err, data) => { if (err ) { console.log(err); } else { res.end(data); } }) }}).listen(8080);

jsx 到字符串

上面我们结合 ejs模板引擎 ,实现了一个服务端渲染的输出,html 和 数据直接输出到客户端。

参考以上,我们结合 react组件 来实现服务端渲染直出,使用 jsx 来代替 ejs,之前是在 html 里使用 ejs 来绑定数据,现在改写成使用 jsx 来绑定数据,使用 react 内置 api 来把组件渲染为 html 字符串,其他没有差别。

为什么react 组件可以被转换为 html字符串呢?

简单的说我们写的 jsx 看上去就像在写 html(其实写的是对象) 标签,其实经过编译后都会转换成 React.createElement方法,最终会被转换成一个对象(虚拟DOM),而且和平台无关,有了这个对象,想转换成什么那就看心情了。

const React = require('react');const { renderToString} = require( 'react-dom/server');const http = require('http');//组件class Index extends React.Component{ constructor(props){ super(props); } render(){ return 

{this.props.data.title}

}}//模拟数据的获取const fetch = function () { return { title:'react ssr', data:[] }}//服务http.createServer((req, res) => { if (req.url === '/') { res.writeHead(200, { 'Content-Type': 'text/html' }); const data = fetch(); const html = renderToString(); res.end(html); }}).listen(8080);

ps:以上代码不能直接运行,需要结合babel 使用 @babel/preset-react 进行转换

 npx babel script.js --out-file script-compiled.js --presets=@babel/preset-react

引出问题

在上面非常简单的就是实现了 react ssr ,把 jsx作为模板引擎,不要小看上面的一小段代码,他可以帮我们引出一系列的问题,这也是完整实现 react ssr 的基石。

  • 双端路由如何维护?

首先我们会发现我在 server 端定义了路由 '/',但是在 react SPA 模式下我们需要使用 react-router来定义路由。那是不是就需要维护两套路由呢?

  • 获取数据的方法和逻辑写在哪里?

发现数据获取的 fetch 写的独立的方法,和组件没有任何关联,我们更希望的是每个路由都有自己的 fetch 方法。

  • 服务端 html 节点无法重用

虽然组件在服务端得到了数据,也能渲染到浏览器内,但是当浏览器端进行组件渲染的时候直出的内容会一闪而过消失。

好了,问题有了,接下来我们就一步一步的来解决这些问题。

同构才是核心

react ssr 的核心就是同构,没有同构的 ssr 是没有意义的。

所谓同构就是采用一套代码,构建双端(server 和 client)逻辑,最大限度的重用代码,不用维护两套代码。而传统的服务端渲染是无法做到的,react 的出现打破了这个瓶颈,并且现在已经得到了比较广泛的应用。

路由同构

双端使用同一套路由规则, node server 通过 req url path 进行组件的查找,得到需要渲染的组件。

//组件和路由配置 ,供双端使用 routes-config.js

class Detail extends React.Component{ render(){ return 
detail

}}class Index extends React.Component { render() { return

index

}}const routes = [ { path: "/

markdownpad2 html渲染组件出错_「万字长文」一文吃透React SSR服务端同构渲染相关推荐

  1. react ssr php,一文吃透 React SSR 服务端渲染和同构原理

    全网最完整的 React SSR 同构技术原理解析与实践,从零开始手把手带你打造自己的同构应用开发骨架,帮助大家彻底深入理解服务端渲染及底层实现原理,学完本课程,你也可以打造自己的同构框架. 写在前面 ...

  2. react ssr 服务端渲染入门

    react ssr 服务端渲染入门 前言 前后端同构,作为针对单页应用 SEO 优化乏力.首屏速度瓶颈等问题而产出的解决方案,近来在 react.vue 等前端技术栈中都得到了支持.当我们正打算抛弃传 ...

  3. 「react进阶」一文吃透React高阶组件(HOC)

    一 前言 React高阶组件(HOC),对于很多react开发者来说并不陌生,它是灵活使用react组件的一种技巧,高阶组件本身不是组件,它是一个参数为组件,返回值也是一个组件的函数.高阶作用用于强化 ...

  4. React SSR 服务端渲染实践指南

    年前因为工作原因需要对原有 React 项目进行服务端渲染的改造,下面是我对之前工作经验的一些总结分享,希望可以对大家有所帮助. 适用场景 首先我们来了解一下 SSR 可以做什么,可以解决什么问题,诞 ...

  5. html js不触发_「万字整理 」这里有一份Node.js入门指南和实践,请注意查收 ??

    前言 什么是 Node.js 呢 ? JS 是脚本语言,脚本语言都需要一个解析器才能运行.对于写在 HTML 页面里的 JS,浏览器充当了解析器的角色.而对于需要独立运行的 JS,NodeJS 就是一 ...

  6. react native text换行_基于React+Koa实现React SSR服务端渲染

    React Server-Side Rendering 其实这个概念很早之前就有了解了,出于没有应用场景原因,之前一直都只停留在了解API的层面,未曾去实践.快到周末闲来无事,自己复盘了下之前做的新商 ...

  7. 我的世界服务器java出错_看懂 游戏《Minecraft》的崩溃报告 服务端/客户端

    前言 [WARNING] 本篇适用于Minecraft服务端/客户端报错的诊断分析,其他游戏除外,比如网易 [WARNING] 本篇适用于Minecraft服务端/客户端报错的诊断分析,其他游戏除外, ...

  8. 「万字长文」实时数仓实践以及架构的演进

    前言 "数据智能" (Data Intelligence) 有一个必须且基础的环节,就是数据仓库的建设,同时,数据仓库也是公司数据发展到一定规模后必然会提供的一种基础服务. 从智能 ...

  9. 「万字长文」谈认知差异——理解层次中的“金字塔”

    本文发于微信公众帐号: 一界码农(The_hard_the_luckier) 无需授权即可转载: 甚至无需保留以上版权声明- 当看到知乎一篇7万+赞的文章(点击阅读原文可查看),思绪万千久久回荡无法消 ...

最新文章

  1. PHP - 如何实现跨域
  2. 【 MATLAB 】Filter Data
  3. centos7.6+vim8.1
  4. 寻找获取Bean 的入口
  5. 关于Promise.all
  6. 项目案例:qq数据库管理_2小时元项目:项目管理您的数据科学学习
  7. 07 - java 方法里面的 return
  8. 如何理解 Python 中的面向对象编程?
  9. python和java哪个好学-Python和Java发展前景哪个好?老男孩python高级编程
  10. github操作实用命令
  11. 佳能G系列领军相机G1X
  12. Maven搭建Spring Security3.2项目详解
  13. Python设计模式:建造者模式
  14. ubuntu串口调试工具RS485
  15. 南京邮电大学通信考研经验
  16. python化学公式配平_最简单易懂的化学方程式的配平方法
  17. NYoj21 三个水杯
  18. linux -unrar解压缩
  19. 如何安装OCSNG及GLPI
  20. 图片上传时报403问题

热门文章

  1. PAT1048 数字加密 (20 分)
  2. netty系列之:基于流的数据传输
  3. Spring Boot filter
  4. Libra教程之:Transaction的生命周期
  5. windows下安装rabbitMQ教程(实战书写)
  6. Java结束线程的三种方法
  7. OpenBase关于一致性,可用性,分区容错性(CAP)分析
  8. 一张图看懂Bean的实例化过程
  9. 大话ConcurrentHashMap的put,get过程
  10. Web前端开发笔记——第二章 HTML语言 第一节 标签、元素、属性