React Server-Side Rendering
其实这个概念很早之前就有了解了,出于没有应用场景原因,之前一直都只停留在了解API的层面,未曾去实践。快到周末闲来无事,自己复盘了下之前做的新商城,一直在考虑有没有更好的方案,于是React Server-Side Rendering被很自然的写到了草稿纸上,一起写上去的还有egg.js。
总结一句,接入服务端渲染有服务端渲染的好,客户端渲染有客户端渲染的更好。

这是背景。

2019.04.12更新

发现我这个react-ssr的github仓库代码和这篇文章的思维被掘金的一个博主抄到掘金社区,他那篇文章拿了高赞。他连我仓库的里前端工程代码都拿出来写到博客里,而且没有备注出处!真希望大家尊重原创性。

2019.04.01 更新

补充一个最终上线完的体验。

最终线上产品体会;相比于传统的服务端渲染,React SSR可以做到更完善的体验;相比于前后端完全分离的SPA,React SSR可以做到首屏更快的得到展示,浏览器解析渲染完dom节点既可以展示了。我的个人博客是这个方案实现的(Koa2 + React SSR + Mongdb),可以参考下。

王佳欣的小站​www.shuxia123.com

----以下是原文----

问题?

为什么React既可以做browser浏览器端的渲染,又可以做server服务端,还可以做native客户端的渲染呢?

因为React将渲染工作交给了react-dom(浏览器渲染)、react-server(服务端渲染)、react-native(客户端渲染)等渲染器。而React 包只负责定义react,让我们可以使用react的特性,如:component、createElement、lazy、createContext、createRef等等在特性,这些特性任何平台都可以正常使用的,不负责具体的渲染工作。

而,各个渲染器中指定了特定的平台,实现各个平台的渲染逻辑和平台特性,如react-dom.render就可以实现dom的渲染。

所以,react就能实现多端渲染,只要在不同的端,引入不同的渲染器就可以了。

好处?

1、可以优化SEO,可以优化首屏白屏的加载时间。

2、不需要开发额外的模板

如果采用使用SSR做node渲染的前后端分离,可能要开发多套模板的,比如:加载更多的情况,就需要做一套node使用的nunjucks模板(用于渲染首屏数据渲染),和一套浏览器js使用的模板(用于加载更多时),比较难维护。

采用SSR渲染使用’ react-dom/server’ 的 renderToString对React组件进行渲染的,因此只需要开发一套组件(React 模板),避免了开发多套模板的工作。

3、单页更好做用户体验的优化,这点也很重要。

重新翻阅了React、React-Router服务端渲染的API,

ReactDOMServer – React​reactjs.org

React Router: Declarative Routing for React​reacttraining.com

一:总体大纲

开始动手实践前,我画了张大概流程图,捋了捋思路,我把原图贴一下,希望有些帮助。

如上图(有点丑)所示:

Server端(Koa实现)需要做3件事:

  1. Koa-Router路由处理,服务端路由的处理。
  2. 数据处理,根据请求的信息(路径、参数等),获取需要的数据。
  3. 渲染模板(dist/index.html),根据模板和数据渲染内容。返回给客户端。

Client端(React实现)

  1. 构建一个模板文件(dist/index.html),服务端渲染是会用到该模板文件。

模板内定义好要渲染的信息。

  • seo信息,title、keyword、description字段信息
  • layout信息,既服务端渲染dom内容,ReactDOM.hydrate/render是会用到该节点。
  • window['defaultReaderData’]信息,json格式的初始信息,供给React组件在浏览器端首次渲染时使用,确保渲染dom与服务端渲染的dom一致。

2. React-Router定义路由,保持与服务端定义的路由一致,所以采用BrowserRouter形式的路由。

3. Redux数据处理,为了使React组件首次渲染dom与服务端渲染的dom一致,所以createStore时,默认数据用window['defaultReaderData’]

4.路由切换时,路由的目标组件,完成数据获取,与组件的重新创建/更新。

二:开始动手

思路捋清楚了,然就做吧。

服务端开发

服务端依赖比较少,可以浏览器访问接口直接测试,所以从服务端开始。

以首页和详情页为例子。需要实现以下的页面路由和数据接口路由(RestFul规范)。

1、路由准备

// 页面路由

http://xxxx.com/

http://xxxx.com/detail/4840388

// 接口路由

http://xxxx.com/api/home

http://xxxx.com/api/movie/1652592

// demo文件
let router = new Router({prefix: '/'
});
router.get('/', demoControl.home);
router.get('detail/:id', demoControl.detail);// api/demo 文件
let router = new Router({prefix: '/api'
});
router.get('/home', ApiControl.fetchHome);
router.get('/movie/:id', ApiControl.fetchOneMovie);

模板渲染({{ xxx }} 是需要通过服务端渲染的占位符)

模板文件:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>{{ title }}</title><meta name="keywords" content="{{ keyword }}"><meta name="description" content="{{ description }}">
</head>
<body>{{ layout | safe }}<script type="text/javascript">window['defaultRenderData'] = {{ data | dump | safe }};</script><script type="text/javascript" src="http://localhost:8088/index.js"></script>
</body>
</html>

渲染模板:

通过React Api文档,了解到’ react-dom/server’ 的 renderToString 可以在将React组件渲染成字符串,我们可以根据它来构造layout的内容。

renderToString会触发React组件的constructor和render和componentWillMount方法,然后dom字符串。这也解释了为什么componentWillMount中setState或者获取数据会不安全。因为,如果再componentWillMount中或数据获取的话,那么服务端渲染时可能会导致数据的多次获取。原文是这样讲的。

The above code is problematic for both server rendering (where the external data won’t be used) and the upcoming async rendering mode (where the request might be initiated multiple times).

StaticRouter 的context属性设置的数据,在Client端匹配路由组件可以通过this.props.staticContext获取到,这样方便我们将数据直接输出到目标组件。

const store = createStore(model.data);
const reactDomStr = renderToString(<Provider store={ store }><StaticRouter location={ctx.request.url} context={model.data}><Layout /></StaticRouter></Provider>
);ctx.response.body = ENV.render(view, Object.assign(// layout组件节点渲染结果{ layout: reactDomStr },// seo相关model.seo || {},// 服务端渲染的数据{ data: model.data || { home: {} } })
);

数据处理:

这边不做深入介绍了。

客户端开发:

模板准备

我用webpack做的项目工程,因此只要构建一个html即可。这边需要注意的是不同环境的配置,以开发环境来说,为了在更新所以在构建模板是,模板引入资源publicPath设为http://localhost:8088/与devServer配置的端口一致。其他环境大家可以看配置文件build/cofig.js

路由准备:

<div id="app" className={className('layout')}><Switch><Route path="/" component={Home} exact /><Route path="/detail/:id" component={Detail} /></Switch>
</div>

其他的就不做深入,介绍了。可以看下git库,欢迎大家提建议。

webpack 定义依赖目录,在node环境下的解决方案

webpack依赖目录 与 nodejs依赖目录

webpack中配置resolve.alias依赖目录,方便import

// build/webpack.base.config.js文件
alias: {'@scss': resolve('src/assets/scss'),'@api': resolve('src/api'),'@containers': resolve('src/containers'),'@components': resolve('src/components')
},

因此node下也需要配置一致的目录,否则会提示"@components 目录找不到"。这个可以通过 module-alias 进行配置。

// package.json 配置
"_moduleAliases": {"@scss": "src/assets/scss","@api": "src/api","@containers": "src/containers","@components": "src/components"
}

One More Thing

实践过程中,踩到的一些坑点。

  • node 需要支持ES6 modules,解决方案是 @babel/register
  • 需要服务端渲染的组件,constructor和render不要写类型window、document等浏览器特有的对象。
  • Client端接口服务采用whatwg-fetch@2.0.4
  • 这个案例中我没有让koa支持webpack配置,没有支持在需要服务端渲染的组件import 样式文件,用了另一种方式。
  • 这个案例我未支持immutable.js,遇到了一些问题,还在处理。
  • renderToString 服务端渲染组件只会触发constructor和render和componentWillMount,不会触发其他声明周期,因此需要注意下。
  • 别再componentWillMount里做数据获取,记住,这很重要。

源码github地址,如果刚好你有React-SSR的开发经验,欢迎讨论呀。

coocssweb/react-ssr​github.com

大概效果如下:

目前简单的实现了,首页和详情页的功能。

react native text换行_基于React+Koa实现React SSR服务端渲染相关推荐

  1. React SSR: 基于 express 自构建 SSR 服务端渲染

    React SSR: 基于 express 自构建 SSR 服务端渲染 文章目录 React SSR: 基于 express 自构建 SSR 服务端渲染 完整代码示例 前情提要 构建 CSR 项目 项 ...

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

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

  3. react ssr 服务端渲染入门

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

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

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

  5. python多线程tcp客户端_基于Python多线程的TCP客户端/服务端应用示例

    每个连接都必须创建新线程(或进程)来处理,否则,单线程在处理连接的过程中,无法接受其他客户端的连接. 服务端:server.py # -*- coding:utf-8 -*- import sys i ...

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

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

  7. react native 文本换行

    react native 文本换行 # just add style , finishflex-wrap: wrap;flex: 1;

  8. React + Koa 实现服务端渲染(SSR)

    ⚛️React是目前前端社区最流行的UI库之一,它的基于组件化的开发方式极大地提升了前端开发体验,React通过拆分一个大的应用至一个个小的组件,来使得我们的代码更加的可被重用,以及获得更好的可维护性 ...

  9. React服务端渲染实现(基于Dva)

    React服务端渲染实现 (基于Dva) 功能 基于 Dva 的 SSR 解决方案 (react-router-v4, redux, redux-saga) 支持 Dynamic Import (不再 ...

最新文章

  1. ajax学习----json,前后端交互,ajax
  2. 在Hyperopt框架下使用XGboost与交叉验证
  3. 华为hcia H31-311 练习题
  4. AutoML简要概述
  5. element-ui踩坑
  6. 完全二分图生成树计数
  7. java判断是否手机浏览器_User-Agent判断是什么浏览器
  8. GNN + Zero-shot
  9. 190815每日一句
  10. JAVA制作QQ空间点赞_利用Javascript实现QQ空间自动点赞
  11. Model性能相关操作:select_related
  12. 计算机局域网的组网,计算机局域网组网方案设计(精选).doc
  13. Vue的v-model的几种修饰符.lazy的介绍
  14. 使用git上传代码遇到关于remote: Support for password authentication was removed on August 13, 2021.的问题
  15. PO: Purchase Order采购订单关键知识点
  16. 二零年的十一月开始 努力做个极简的人
  17. Android studio 试用小技巧
  18. C语言函数大全--d开头的函数
  19. [游戏学习28] MFC 时钟
  20. python舆情系统开发_舆情系统开发

热门文章

  1. Win7 单机Spark和PySpark安装
  2. linux中断申请之request_threaded_irq【转】
  3. 类string的构造函数、拷贝构造函数和析构函数
  4. 99%的人都不会的用户流失分析,到底应该怎么做?
  5. 浅析数据库设计三范式
  6. 飞秋官方下载 这个程序很不错
  7. 程序简单教程:飞秋官方下载
  8. 理解ASP.NET中的三层结构
  9. 博客,文字的卡拉OK版
  10. 微信“拍一拍”,竟然可以使用Python实现,你get到了吗?