/react-ssr

Primary LanguageJavaScriptOtherNOASSERTION

注意事项

如果你在使用过程中发现错误应首先查看下面的错误指引!

为什么做同构

原因很简单,跟风,想探索技术,为以后的需求做技术储备,还能学习node相关技术(webpack等),这是做这个脚手架的初衷。

技术选型

目前流行的同构框架也比较多如nextbeidou等,我没有选择这些框架,目的有三个,一是对现有的spa改造不太灵活,二是我想自己走一遍同构流程,能理解的更深刻,三是我不了解这些框架。技术选择的目标是尽可能少的依赖第三方库,个人认为这样通用性好一些,还有就是尽可能用最新的技术,我真的不想这个脚手架做出来没多久就不能在最新的第三库下运行了,当然使用比比较小的第三方库后期会考虑用node实现取代它。

技术栈

  • express
  • webpack
  • webpack-dev-middleware
  • webpack-hot-middleware
  • react-router-config
  • react-loadable

同构需要做什么

同构的目的狠简单,就是服务端渲染出和客户端一摸一样的dom树,这样客户端可以和服务端无缝对接,关于同构的优点在此就不说了,相信想了解同构的同学已经了解很清楚了。我们想想如何实现服务端渲染?答案很简单,react技术栈提供了在服务端渲染dom树的方法,开箱即用。我们去实现其实还是有些困难的,比如如何实现热重载按需加载服务端数据预加载,这些大多在spa项目开发中能轻易实现,但是在服务端也实现并不是一件狠简单的事情,至少我是这样认为的。

实现目标

  • 同构热重载
  • 代码分割
  • 服务端数据预加载(不校验用户信息部分的数据)

服务端热重载

这个主要在开发模式下,本来我想舍弃这个功能,用spa的模式去开发,只考虑同构的生产模式开发,理论上讲只要你的同构方案是对的,spa开发完毕直接同构生成打包就能满足需求,后来想想这样总不妥,至少不是够优雅,我也想在开发过程中体验同构带来的效果(并不是说一定比spa好),实现热重载参考spa项目中的实践,比如webpack-hot-middleware,还有开发模式下把文件打在内存中读取比较快,这里有个难点,服务端文件打包后是要被执行的,我们不能require一个内存中的文件吧,利用webpack-server-hot-middleware可以做到,具体实现原理还没去理解,我采用的是鲸吞式的开发,开发完后再去细嚼原理消化所接触的技术。这个中间件为什么说效果不好呢,我组织的代码结构大概可以分serverclientwebpack,这里serverclient都不包含打包相关库,其中server是单纯的提供服务的,如果用webpack-server-hot-middleware我们这里的server只能做一层中间件,webpack部分提供真正的服务,这样server层不能包含纯业务,业务需要分散到webpack部分中,也许我说的并不太清除,看下我的组织结构并简单看下里面的内容你就明白了,我做这个尝试完全从零开始,包括打包技术都是现学现做,所以代码组织结构完全凭自己想法,阅读时不合理的地方大家可以指出,我会根据自身能力做出相应修改。好了,言归正传,舍弃了webpack-server-hot-middleware,我采用了分离server,让这一层可以只做业务逻辑,暴露出相应接口供接受者使用,server采用webpack自带的热更新插件编译到硬盘中,当然理想的情况是编译到内存中,出于技术原因我还没做到,等沉淀些技术会重新考虑这件事情,这样问题就简单了webpack直接编译到硬盘,然后我们可以从webpack这部分读取该文件,服务端热更新到此实现完成。

同构按需加载

这个实现起来选择比较多,据我目前所知道react-universal-componentwebpack-flush-chunks,这些可以实现,前者实现代码分割,后者提取脚本和样式文件,当然这是我在查阅相关资料时看到一些大神的解决方案,但是我选择了react-loadable,这是我在学习react-router时官方教程里出现的一个库,用它做按需加载狠简单,做服务端数据预加载也很简单,而且它也提供了提取chunk的功能。

服务端样式问题

服务端没有document这些所以那些常用来处理样式的loader在服务端就不好使了,我的解决方案狠简单,直接在服务端忽略样式文件,利用上面抽取的chunk塞回html中去。

服务端数据预加载

这个是最简单实现的,react-router-config提供了提取渲染组件的能力,我们给需要的组件添加加载数据的方法,等数据加载完再返回html即可,这使得使用redux这些数据管理库做数据预加载很容易。

总结

这个脚手架前后折腾了两周左右,这段时间公司项目也比较多,做的过程狼吞虎咽,接触很多优秀的第三方库,所用到的库都是目前最新版本,过阵子闲下来还要去研究这些框架及其原理才能真正学到技术。

错误指引

  • 生产环境打包报错,比如npm | cnpm | yarn run ssr:build | spa:build,请先运行npm | cnpm | yarn run dll
  • 不管是开发环境还是生产环境构建之前必须在根目录存在deploy目录
  • 当你修改了webpack/client.dll.config.js中的entry时请一定要记得run dll重新构建dll包