之前讲了利用 koa 实现了类似 rails 的 web 开发 mvc 项目 kails。 但是在今天的 web 开发中,大家都讲究前后端分离以及微服务,传统的 MVC 已经不能满足很多人胃口了。 所以今天再讲下如何利用 koa 构建高性能的 web 中间层,实现大前端概念下的前后端分离。
个人原创,版权所有,转载请注明出处,并保留原文链接:
前后端分离-利用 koa 实现基于 node.js 的 web 高性能中间层
https://www.embbnux.com/2017/01/09/use_koa_as_a_middlelayer_to_split_frontend_and_backend/
一、web 开发
web 开发,主要分为前端和后端。
其中后端的话主要是指服务器相关,数据库,web应用等跑在服务器上的程序部分,开发语言众多,java, php, ruby 和 python 等等,这些语言都可以在服务器上跑起来,处理网络请求,并输出响应。为了开发大规模的 web 应用,发展出了 MVC 框架,方便开发者编程以及项目维护,后来随着业务逻辑的越来越复杂,发展出了 MVCS 框架,即多了 Service 逻辑层。后端 web 开发者需要把从相应数据从数据库传递到 view 层,最终渲染出 html 文件给用户。
而前端一般是指跑在客户端的程序。对于 web 开发来讲的话,客户端主要还是还是浏览器,程序语言主要还是指 html, js, css. 如今对客户端体验以及复杂度的要求越来越高,很多项目慢慢演变成了单页应用。为了大型项目的开发和维护,前端发展出了众多的框架,如 react, angular 等, 都是为了能在浏览器里能有众多的交互效果,页面的渲染可以直接在浏览器生成,通过后端提供的 api 拿到数据用于呈现。为了支持这些框架,web 应用的框架里需要继承前端程序打包工具, 如现在的 webpack。所以 web 框架需要做的事情越来越多,本身代码也越来越庞大。
所以传统上的 web 项目的代码即包括后端代码,也包括前端代码,同样不管对于前端工程师或者后端工程师都得配置这前后端的环境,不然开发环境跑不起来。这就尴尬了。
二、前后端分离
随着前后端的越来越复杂,于是有人喊出了把前端和后端分开,后端专注于数据库、性能和业务逻辑等,前端专注于页面与交互。得益于 node.js 的出现, 前端的 js 代码也有可能跑在服务器上了,解决了前后端模板共用的问题。所以基于 node.js 的前后端分离方案被越来越多的人所接受。所以现在后端专注于自己的业务,对外自提供 api 接口即可,自己开发测试也只要测 api 即可。前端需要负责 html 的页面渲染,在 node.js 上取 api 的数据,渲染出 html 给浏览器,浏览器再继续跑前端的 js 代码,实现交互。这样前端代码的打包能环境就能只集成在自己的项目里了。
二、高性能中间层?
为什么说高性能中间层呢,因为和之前的不分离方案相比,你在中间忽然加了一层,肯定会造成等待传输时间变长。所以怎么缩短中间层造成的时间损失是很重要的话题。而恰恰得益于 node.js 的设计思想,非阻塞,异步 IO,可以极大的降低这个损耗。
这里介绍下使用 koa 实现:
const index = async (ctx, _next) => { const page = parseInt(ctx.query.page) || 1; const hackerNews = new HackerNewsService(ctx); const newsIds = await hackerNews.getTopStories(page); const newsList = await Promise.all( newsIds.map(async id => await hackerNews.getItem(id)) ); const locals = { title: 'Hacker News', nav: 'news', newsList: newsList, baseUrl: '/news', currentPage: page, pages: 20 }; await ctx.render('news/index', locals); };
这是一个在服务器上用 KOA 获取 api 数据展示的例子,完整程序可以看这里: Kails HackerNews Page, 这里使用了 es7 的 await 特性可以用同步的方式来写异步的程序。
使用 Promise.all 特性可以实现多个异步操作同时进行,时间即为最慢的那个异步操作。这样本来需要获取好几个 api 数据的页面响应时间就被极大的缩短了。结合后端 api 的优化,把 api 做得更加干净和迅速,可能一个页面的数据比原本的传统方案更加短。
所以这种框架下应该分为三个部分:前端SPA + node.js + 后端API(Java等)。对吧。
另外,博主您说“Promise.all 特性可以实现多个异步操作同时进行”,这个应该是在Node层进行的对吧。那么在前端SPA不也可以直接用吗?
是的,前段 SPA 也可以使用,但是在客户端有可能收到浏览器的限制