多多少少有些不开心的事, 以为精力没有被投入在重点上
创业公司遇到问题变成盲人摸象也许正常吧
不过最近这段时间由于服务端的策略调整, 我开始作一些服务端渲染
主要的站点是简聊的登陆页面, 总体从 Jade 切换到了 React
https://account.jianliao.com/signin
以及作了一些总体项目结构统一的工做, 或者说一些思考html
我估计这些问题已经被考虑过不少次, 特别是对于发展较快的那些公司
由于富交互的应用和较大的网站的需求, 很容易导向这个结果
而为了保证交互效果以及产量, 提出相应的方案是天然的一个结果
Teambition 主站的同窗以前有讲过 ejs 共用代码的方案
我大体记得是后端渲染, 前端编译, 还从新实现了路由, 大体的
简聊(https://jianliao.com)这里的尝试晚了半年一年, 层次也不深, 用 React 难度也低一些前端
这些天 Coding 在好多地方刷了几篇服务端渲染的广告, 学习目的推荐看下
http://segmentfault.com/a/1190000004120539
http://segmentfault.com/a/1190000004094442node
简聊没有继续跟进 Redux 和 JSX 的方案, 实际上细节处理很不同
总体的思路固然差不太多, Yahoo 的 fluxible 当时演示的方案已经成熟
我整理一下大致思路吧, 也许用获得, 特别是中间一些坑
大体有这么几点, 在开发以前就须要考虑清楚的react
先后端共用的渲染模块webpack
先后端共用的数据层实现git
先后端共用的路由方案github
先后端共用的类库web
简聊技术栈当中已有的模块, 可以在服务端共用的:ajax
渲染模块: React 内置功能, 轻松实现数据库
数据层实现: actions-recorder 是很简单的封装
路由方案: router-view 功能少, 容易自由组合
共用类库: 经过 typeof window 强制判断控制加载
先后端渲染, 实际上整体的思路仍是前端单页面渲染的套路
单页面, 会先建立好 Model, 而后根据 Model 和 Router 渲染 View
渲染在 React 当中就简化成为初次渲染, 以及后续数据和操做的更新
而服务端渲染, 仅仅是把初次渲染放在服务端进行, 后边照常
所以, 虽然说是共用代码, 但实际上只是支持单页面在服务端作初次渲染
共用渲染代码原本是最难的, 然而 React 出现之后几乎不是个事情
只是渲染的性能让 React 的实用性打了折扣
不过 0.14 以后有新的模块在尝试, 号称性能提高明显
总体思路就是把渲染过程转化为 Node 经常使用的 Stream
https://github.com/aickin/react-dom-stream
我没有实际用, 不过这个方案须要手动封装 HTML 的 <head>
部分
方案的代码是 fork 了 react-dom 官方实现作的, 看起来挺长
我仍是等等事件提供更好的方案吧
数据层须要作的主要是定义一个渲染页面所需的 initialStore
这个 initialStore 能够用于服务端的初次渲染, 也能够用于客户端
简聊网页版用的 actions-recorder 在服务端渲染时几乎每作什么
整个 initialStore 直接被输出为 JSON 写在 HTML head 当中
<script>window._initialStore= (JSON.stringify(store))</script>
前端代码初始化时读取其中的数据, 从新用 actions-recorder 初始化一遍
通常服务端写 initialStore 以前会作一些操做
好比说服务端能拿到的 cookie 或者其余的一些配置
或者是后面要说的路由信息, 由于简聊的路由是等效 JSON 表示的
服务端是代替客户端作了一些初始化工做, 不然前端初始化也是相似的代码
router-view 包含两部分代码, 一部分是解析路由, 另外一部分是渲染和监听
固然, 初次以外, 还有接口能够定义路由规则, 我挺懒
若是有兴趣看看内部实现和实例也就算了, 很短的代码
https://github.com/teambition/router-view
页面初次渲染的过程, 大体就是解析出路由, 渲染对应页面就完了
路由解析在后端作, 在前端作, 只是获取 path 的 API 不一样而已
这里却是有一点要注意, 服务端渲染有特别的地方, 就是初次操做
好比说, 打开一个页面, 会自动触发一个操做, 好比验证某些数据
单纯按照单页面的思路, 渲染时不该有操做, 那么, 操做应该是更早发出
也就是在以前用户发有操做, 到服务器渲染页面, 这中间
这种问题在前端作, 总架构考虑, 就该是认为是用户打开浏览器的行为上发出
总之尽可能避免认为是 didMount 的时候发出这样一个行为了
路由另一点是隔离 JavaScript/CSS 代码的做用
固然, 其实仍是经过单页面应用的套路来实现的, 甚至 Webpack 打包也是
就是说经过 Component 的分割, 将 JavaScript/CSS 限制在每一个页面里
咱们早期一些代码用的是原始的 DOM 操做, 就不容易管理
好比说打包到一块儿, 万一 CSS 或者 JavaScript 不该该却触发了怎么办?
咱们没有积累强大的后端渲染静态资源管理方案, 于是这点须要避免...
最主要的问题就是第三方类库可能影响在 Node 中加载代码
其实初次渲染极可能用不到不少代码, 只要加载不报错就行了
用的办法简单粗暴, 就是强制判断, 而后控制 require 的执行
typeof window isnt undefined
我记得这个仍是之前 AirBnB 放出的幻灯片里看到用的
实际遇到会是很琐碎的状况, 甚至致使代码都有些难看
可是谁让 JavaScript 设计时看不到这么远的适应场景呢
另外有个办法, 是用 Webpack 的打包方式, 自动把 Node 模块过滤掉
这个办法我是刚学会, 具体看网上的例子:
https://webpack.github.io/docs/configuration.html#node
http://stackoverflow.com/a/34033159/883571
大体说来就是定义一些模块, 告诉 Webpack 用什么方案处理
能够 mock, 能够引用... 细节我还不清楚, 但值得挖掘
我实践中遇到最坑的一件事, 莫过于代码当中存在 event loop
简聊有段代码打包后几万行, 中间有时间循环, 根本不知道在哪
后来猜测是 setInterval 有问题, 就重置了变量经过报错定位出来
这种 IO 代码毕竟不如 pure function 好控制, 能隔离尽可能隔离
先后端渲染主要的好处, 就是作了单页面, 又保证首屏渲染体验
若是仅仅是服务端渲染加 jQuery, 组件化会很头疼
特别是实现比较复杂的功能, 还要迁就初次渲染额外处理, 真的不轻松
然而用了 React 不少工做就这么省掉了
简聊目前的场景, 就是第一次加载是服务端渲染, 而后前端加载
以后点击切换路由, 就彻底是 HTML5 路由切换, 彻底是单页面套路
说简单除了页面少, 另外一点是由于数据层几乎没有内容
就是说, 从服务端在 HTML head 写 JSON 传导前端初始化, 几乎没有数据
仅仅是读取的一些配置信息而已, 因此不涉及数据库操做
复杂的状况, 从目前对简聊主站应用的状况作的设想
应用在初始化时, 会先装备好查询到首屏须要的全部数据
数据拼装完成, 而后才能开始渲染, 固然到这一步就很简单了
难度在于怎么查询好须要的数据? 并且, 是一套代码, 不是先后端各一套
那么要求有更好的抽象机制能作数据查询的事情, 有点难度
一方面是 polyfill 两边的 ajax API, 另外一方面是数据逻辑抽象
我感受跟着 React 和 GraphQL 的思路, 已经触及一些重要问题了数据和界面之间, 怎么作好隔离, 然而又怎样设计界面对数据的依赖?界面自身的组合如何抽象, 数据自身的组合又如何抽象?未来要梳理的问题仍是会有不少