本篇内容主要介绍FaaS场景下的SSR框架,也就是在FaaS场景下怎么开发服务端渲染页面。服务端渲染是指前后端同构的服务端渲染,即React SSR。
在介绍SSR框架之前,首先简单介绍一下Serverless。
首先是NodeJS的定位。在很多公司NodeJS都在充当BFF层的角色,甚至NodeJS只出现在本地开发,仅仅做一些开发工具和构建工具的角色。最主要的原因,可能是因为前端工程师在运维方面的知识比较稀缺,就导致了可能很多公司不敢NodeJS,不敢让前端工程师做服务端。
但是随着Serverless概念的出现,上面提到的问题就很好解决了。Serverless不需要关注运维,只需要关注自身业务逻辑的开发,因为运维的工作在云开发平台都已经解决了,这对前端工程师来说是收益最大的。
从BFF到SFF层本质上开发模式并没有改变,但是却大大提升了开发效率。上图列举了在SFF场景下,经常做的5给方面工作:
第一个, API接口;
第二个,API Proxy;
第三个,Render渲染层。渲染层可以分为客户端渲染和服务端渲染;
第四个,SSR+API,就是如何开发服务端渲染应用,下面会着重介绍在FaaS应用里,如何同时开发服务端生产应用和API接口;
第五个,Gateway网关层。
SSR框架前身
SSR框架是由Egg+React+SSR演变来的。这个项目已经开源一年多了,目前大概有1200个star了。阿里内部已经有七八个部门用于线上应用的开发了,阿里外部也有很多公司正在使用这个项目来开发线上应用。大家对应用开发的整体反馈是,比一些业界类似的框架好很多。
FaaS场景下的SSR框架
这个框架针对FaaS场景做了很多优化和制定了一些规范。尽量保证在云开发和本地的开发体验保持一致。
实操演示SSR框架的使用
首先登陆云开发平台http://workbench.aliyun.com,然后创建应用。在创建的时候的时候,选择WEB和FaaS场景下的SSR框架。创建完成安装依赖,tips是可以用cnpm而不是用npm来安装依赖,cnpm安装依赖要快很多。
如下图可以看到yml文件,可以看到和API接口看起来差不多。
上图所示新增的 render字段的意思是,当检测到函数里有这个字段,这个函数要返回htmlStr界面的,而不是返回API服务。index handler的作用很简单,就是从 ssr-core中emloy的render方法,然后再把返回的结果到htmlStr。
本地开发也是通过Snpm start 来启动服务,可以直接使用SSR框架。启动后进行构建,同时启动FaaS服务,最后会返回一个地址,这个地址可以直接在浏览器打开来预览当前的应用。
从页面的源码可以看出它包含了一个完整的HTR结构,也就是说这个页面是由服务端而不是客户端渲染产生的,点击刷新也不会产生因客户端渲染而产生的白屏。
由根路由切换到详情页,这个切换过程仅限于前端的切换,不会向服务端发出请求。所以详情页的数据其实是由前端发起HTTP请求获取的,这个请求也会写在FaaS服务里的。包括退回到首页的操作也是前端路由的切换逻辑,只有刷新才是真正访问到服务器。
如下图在f.yml文件中, api-index和api-detail底下是定义的两个API的接口服务。打开web目录,就是前端组件存放的目录。打开Pages文件夹,这个就是首页组件对应的路由,这里有一个fetch文件,它定义了数据是怎么获取的。这里区分了服务端和客户端两个场景的数据获取。再看API index函数,它是返回一个Json数据结构。如果是在服务端的话,非常简单,可以直接通过ctx.apService拿到自己写的一个Service服务直接调用,然后就可以返回正确结果。
SSR框架还支持客户端和服务端的一键切换的能力。以下图为例,它是服务端渲染,在 url参数后面加csr=1,就可以迅速的切换为客户端渲染,切换之后页面的源码就变成空的了。
回到控制台页面继续发布,发布之前要先build,把前端文件进行打包,打包成生产环境需要用到的文件大小。
如果使用Cloud ID发布,可以直接通过左边第一个tag;如果是本地发布,可以直接通过一个命令来发布。
发布时选择日常环境发布。构建之后会放在build目录下,然后根据函数作为文件夹的区分。比如,当前渲染层函数叫index,构建出来的结果都放在build index函数文件夹下,分为client和server两个文件夹。
Client文件夹之前的课程已经详细介绍过了,这里就不多赘述。看下server文件夹,因为是服务端渲染所以多出来一个server文件夹,比如Page.server.js就是在服务端使用到的文件。
Serverless场景和传统的NodeJS应用的发布场景有什么区别呢?传统NodeJS应用发布场景,很多成熟的公司发布构建大部分是在CI平台上进行的,比如说本地把代码谱写到仓库之后自动出发这个构建逻辑;但是在云平台发布场景,代码打包是在本地进行的,意思是点了部署后,首先它是会把本地的代码都达成一个code.zip压缩包,然后再把压缩包上传,同时对包的大小也是限制的。值得注意的一点,它也会把node-modules的文件夹一起打包进去。
所以如果开发应用运行在Serverless场景,就需要很清楚哪些依赖是在生产方面用的,哪些依赖是在开发方面用的。如果不注意,打的包就会很容易特别大,超出平台限制。
部署成功后会返回一个地址,可以通过这个地址打开预览或申请新域名指到这个地址使用。
总结而言,本地开发只需要关注start命令,执行ssr start;build就是执行ssr build 命令。如果是本地开发,也可以直接通过ssr deploy一键发布到云端。
ssr-spec规范
这部分主要介绍在怎样的规范下,才能在Serverless场景下开发出一个渲染层的页面。
(实操演示讲解)
如下图,框架在github的地址。
在这个地址可以看到SSR的规范。
这个规范主要是基于单页应用和多页应用两个不同类型的应用制定不同的规范,分为SPA和MPA。当下非常常见应用是SPA类型的。
首先就src目录放一些FaaS服务端相关的代码。这里要做的就是在文件夹下新增一个web目录,web目录里放一些前端相关的东西,比如前端组件。
这虽然是为FaaS场景打造的,但是与服务端无关。在web目录下,上图所示的文件夹结构也可以参考。文件夹里的路由用的是约定式,不需要去手动编写路由配置表。
举个例子,pages文件夹会放页面的登录,有的也会将根组件放在这里,如果pages有index文件夹,就会把index文件夹映射默认为根路由。
fetch.ts文件,在这个文件主要做一些数据获取方面的逻辑,比如页面需要在服务端调用哪个接口或者调哪个服务获取数据,然后在文件导出的函数里把它返回出来就可以了。
index.less是样式文件。
render.tsx,定义了它是怎么渲染的,其实就是render方法。
components文件夹存放了一些公共组件
pages文件夹,如果页面登录有对应的组件就会放在这里;详情页可以放在detail文件夹中。
Layout文件夹,采用的是html结构。如果当前开发的是单页面应用,只需要一个layout就够了;如果是为不同的路由做不同逻辑区分,可以在下图代码处拿到context,然后根据请求不同做不同逻辑处理。
yml文件的编写规范
yml文件编写规范,函数里增加了render字段,也就是说,如果检测到这个函数有rander字段,就说明这个函数会有渲染服务。
比如render有个mode,mode默认是以ssr模式来渲染的,如果把ssr写成csr就会把它降级为客户端。举个例子,页面可能会有些极端情况,当发生时页面在服务上会报错,这时候可以通过改yml文件来为客户端渲染。开发接口服务,只需要handler和events是这两个字段就可以了。
发布这里对接的是Midway FaaS的发布功能,如果在云平台的话,直接点 tab按键就可以发布。
MPA的页面规范
开发多页面应用,跟单页面应用总体上比较类似,区别是多页面应用有不同的layout,每个pages文件夹下面都是一个独立的页面和应用。如果不给每个文件夹添加独立layout,那么就是用默认的layout。
构建出来的build目录也会根据yml文件,基于多页和多函数构建出对应数量的文件夹。如下图所示,yml文件如果有多个函数,每个函数都定义了一个render字段的话,这就需要开发一个MPA多页面应用。
使用MPA多页面应用很简单,只需要按照上文介绍的规范,添加一个web目录,然后从ssr-core模块里倒入render方法,再把请求的.ctx传进去,就会自动渲染组件,再把渲染好的结果返回。
模式切换
降级也有多种方式。
为了更加灵活,如下图,支持config.js。如果想改默认的配置或端口等,都有对应的配置可以更改。这个框架集成了很多流行的前端UI框架,不需要再为集成框架做额外配置了。