详解React+Koa实现服务端渲染(SSR)
React是目前前端社区最流行的UI库之一,它的基于组件化的开发方式极大地提升了前端开发体验,React通过拆分一个大的应用至一个个小的组件,来使得我们的代码更加的可被重用,以及获得更好的可维护性,等等还有其他很多的优点...
通过React,我们通常会开发一个单页应用(SPA),单页应用在浏览器端会比传统的网页有更好的用户体验,浏览器一般会拿到一个body为空的html,然后加载script指定的js,当所有js加载完毕后,开始执行js,最后再渲染到dom中,在这个过程中,一般用户只能等待,什么都做不了,如果用户在一个高速的网络中,高配置的设备中,以上先要加载所有的js然后再执行的过程可能不是什么大问题,但是有很多情况是我们的网速一般,设备也可能不是最好的,在这种情况下的单页应用可能对用户来说是个很差的用户体验,用户可能还没体验到浏览器端SPA的好处时,就已经离开网站了,这样的话你的网站做的再好也不会有太多的浏览量。
但是我们总不能回到以前的一个页面一个页面的传统开发吧,现代化的UI库都提供了服务端渲染(SSR)的功能,使得我们开发的SPA应用也能完美的运行在服务端,大大加快了首屏渲染的时间,这样的话用户既能更快的看到网页的内容,与此同时,浏览器同时加载需要的js,加载完后把所有的dom事件,及各种交互添加到页面中,最后还是以一个SPA的形式运行,这样的话我们既提升了首屏渲染的时间,又能获得SPA的客户端用户体验,对于SEO也是个必须的功能。
OK,我们大致了解了SSR的必要性,下面我们就可以在一个ReactApp中来实现服务端渲染的功能,BTW,既然我们已经处在一个到处是async/await的环境中,这里的服务端我们使用koa2来实现我们的服务端渲染。
初始化一个普通的单页应用SPA
首先我们先不管服务端渲染的东西,我们先创建一个基于React和React-Router的SPA,等我们把一个完整的SPA创建好后,再加入SSR的功能来最大化提升app的性能。
首先进入app入口App.js:
importReactDOMfrom'react-dom'; import{BrowserRouterasRouter,Route}from'react-router-dom'; constHome=()=>Home; constHello=()=>Hello; constApp=()=>{ return() } ReactDOM.render( ,document.getElementById('app'))
上面我们为路由/和/hello创建了2个只是渲染一些文字到页面的组件。但当我们的项目变得越来越大,组件越来越多,最终我们打包出来的js可能会变得很大,甚至变得不可控,所以呢我们第一步需要优化的是代码拆分(code-splitting),幸运的是通过webpackdynamicimport和react-loadable,我们可以很容易做到这一点。
用React-Loadable来时间代码拆分
使用之前,先安装react-loadable:
npminstallreact-loadable #or yarnaddreact-loadable
然后在你的javascript中:
//... importLoadablefrom'react-loadable'; //... constAsyncHello=Loadable({ loading:loading..., //把你的Hello组件写到单独的文件中 //然后使用webpack的dynamicimport loader:()=>import('./Hello'), }) //然后在你的路由中使用loadable包装过的组件:
很简单吧,我们只需要importreact-loadable,然后传一些option进去就行了,其中的loading选项是当动态加载Hello组件所需的js时,渲染loading组件,给用户一种加载中的感觉,体验也会比什么都不加好。
好了,现在如果我们访问首页的话,只有Home组件依赖的js才会被加载,然后点击某个链接进入hello页面的话,会先渲染loading组件,并同时异步加载hello组件依赖的js,加载完后,替换掉loading来渲染hello组件。通过基于路由拆分代码到不同的代码块,我们的SPA已经有了很大的优化,cheers