《从零构建前后分离 web 项目》探究 - 深入聊聊前后分离架构

本贴最后更新于 2302 天前,其中的信息可能已经时移世易

探究 :深入聊聊前后分离架构

前后分离,一直是一个相当泛泛的问题,前后分离到底好不好?没有绝对的对,没有绝对的错,业界就这个问题已经激烈的探讨几年了.出现讨论的点在于:分离当然是好的,但是以什么样的服务需要进行前后拆分?拆分到什么粒度?前后端如何配合?

截图时间: 2018-08-30 - Github

我们随意在 Github 输入前后分离关键字,看下搜索的结果: 1K 的库 11kIssues 足以说明前后分离的趋势,可以想象激烈程度,业界比较有名的讨论:Web 前后端分离的意义大吗?,值得一提的是:前排对于这个问题讨论比较深刻的大部分都是全栈工程师。因为全栈对全局的了解相对比单纯做前端、后端全局观念更强一些,考虑的问题更多一些。

筛简历引发的思考和分析

后端职位的怪圈

在公司的简历库随手截几个局部的图,近两年面试过很多的 1-3java 开发者,在筛选简历和面试过程中,也发现了几个问题:相当多一部分 javaer 技术栈上总是多了那么个 HTML ajax jquery bootstrap easyUi ,看起来很唐突,如果面试提到了前端技术栈,基本没有能答的很好的,甚至有的人连 原型链 都不知道。这也是大部分人对全栈的误解,其实我是不太感冒这样的简历的,因为没有什么亮点,技术栈不是写的越多越好,总结起来:他们对前端的掌握很基础,勉强能胜任一些业务上的工作。那为什么这么多人都掌握一些前端技术呢?我分析可能有三点:

思考原因:

  • 培训机构的兴起,机械化的教学

  • 求职者自身的兴趣

  • 一些公司的技术栈不全,对技术没有追求,大部分用的几年前的架构,前后业务耦合很大,市场缺口大

分析

因为我也维护过几个月的敏感项目,深有体会,只写服务端的人是无法胜任这项工作的,
如果多数的 开发者 这样的简历,可以推测:现在的 IT 行业中前后端糅杂一起的架构还是存在、并且有一个量级,这导致他们不得不寻找一些懂得一点前端技术的人来开发项目,减少沟通的成本,加快项目的进度,这也就催生了很多所谓的 web 开发培训机构。

你问我当年维护的开心吗?一会告诉你。

什么是前后分离

前后端分离并不是什么新鲜事,到处都是前后端分离的实践。然而一些历史项目在从一体化 Web 设计转向前后端分离的架构时,不可避免的会遇到各种各样的问题。由于层出不穷的问题,甚至会有团队质疑,一体化好好的,为什么要搞前后端分离?说到底,还是技术和思维方式没转变过来。

一体化模式其实在上一开篇:纵观历史演变 中已经提到过了,不在赘述。

前后分离看起来应该是这样的:

前后分离就是在架构层次上 构建项目或对现有的项目 客户端 服务端 分离开,减少前后端代码的耦合度,大家一致认同的前后端分离的例子就是SPA(Single-page application) ,所有用到的展现数据都是后端通过 JSON 但不仅限于 JSON 的方式提供的,前端只管展现,提供更好更绚的交互,后端只管提供更健壮的高可用服务。

千万不要有先写项目,写完再重构的想法,项目初期能一步到位最好,何必再去重构,然后不得已抛弃一些已经写完的组件、库浪费人力呢?

前后分离解决了什么问题

每个人各尽其职

好的开发者是可与不可求的,若寻找一个 优秀的 full_stack 更是难,从校招进行培养也不太实际,招一个能力一般的程序员,技术驱动性比较差,甚至拖慢产品迭代。分离开来我们就可以专注于 前端服务端 领域去寻找专业的人才。

解耦

前端后端代码大量耦合代码看起来是这样的:

看看简单例子吧:

//(node端处理)
if (is_weixin()) {
init([
'api',
'image',
'xxx',
'...',
], function () {
<%- doSomeGloble %>
});
} else {

}
//接收node端一些数据
let blogs = <%- blogs %>;

let users = <%- users %>;
                     

这还不是 JAVA 模板 而是相对轻量、优雅的 NODEEJS 渲染的,这还好,我见过更令人难受的代码,经常为了一个问题要回头看 N 多代码,这里就不写了。

那么前后分离如何让它们解耦变得更清晰?后面会结合服务端统一补充。

什么项目不适合前后分离

blog、文档

你说你搭建一个博客、 API 文档系统 这种小项目,一个人就可以开发。搞了一个前后分离,需要分离部署。又增加了 SEO 的复杂度,增加了开发的周期、增加了用户部署的难度,何必呢?当然,如果只是技术实践的一种学习方式,还是欢迎的。

前后分离带来的问题,如何解决?

沟通成本问题

前端妹子:哥,获取全部博客调哪个接口?

哦,昨天不是发你文件了吗

前端妹子:我找不到了😭

哦,等下吃晚饭发你啊


前端妹子:哥,产品提出根据手机壳自动换主题的需求,你有接口吗?

... 我看看...应该...没有!可能需要 Python 的老哥支持!你去找他要吧


前端妹子:哥,你根据 TAG 获取博客的接口写完了没?接口是啥?我好渲染数据啊

没等等......


这显然是不规范的,我们期望的是前端后端先约定一个接口协议,后端没完成时,前端自己 mock 测试数据,前端找不到接口的时候,直接查看 API ,根据这个接口协议我们前后端统一编程,那么我们如何处理呢?

如何降低沟通成本?
后端数据服务化,走统一的 REST 接口规范输出,降低前后端接口定义的沟通成本。避免“口头说明”的方式。

什么是 RESTful API ?
所以 RESTful API 就是 REST 风格的 API。 那么在什么场景下使用 RESTful API 呢?在当今的互联网应用的前端展示媒介很丰富。有手机、有平板电脑还有 PC 以及其他的展示媒介。那么这些前端接收到的用户请求统一由一个后台来处理并返回给不同的前端肯定是最科学和最经济的方式,RESTful API 就是一套协议来规范多种形式的前端和同一个后台的交互方式。

我通常用 swagger + mock 平台生成标准的 RESTful API,同时也支持扩展多个编程语言例如:Go Python

SEO 问题

vue + webpackSPA 为例,没有了后端模板返回的 HTML,前端渲染并不被搜索引擎的爬虫接纳。在日后实战 SEO 之前先通俗渲染呗爬虫识别的区别:

seo 本质是一个服务器向另一个服务器发起请求,解析请求内容。但一般来说搜索引擎是不回去执行请求到的 js 的。也就是说,如果一个单页应用,html 在服务器端还没有渲染部分数据数据,在浏览器才渲染出数据,而搜索引擎请求到的 html 是没有渲染数据的。 这样就很不利于内容被搜索引擎搜索到。 所以服务端渲染就是尽量在服务器发送到浏览器前 页面上就是有数据的。

以博客为例简单聊聊:

  • 静态服务
<div>我是正文1</div>
<div>我是正文2</div>
<div>我是正文3</div>

爬虫直接抓到 html 解析 - 生成索引

  • 传统后端渲染
 @RequestMapping("/index") 
    public String index(HttpServletRequest request,HttpServletResponse   response){ 
        return "welcome"; 
    } 

这里就比较有意思了,比如我们打开的网址是:

http://host:port/index
实际充当 Controller 的是 服务端,服务端直接返回渲染好的网页给你,爬虫拿到的也是一样,所以 SEO 没啥太大的问题。

  • 前后分离 SPA
let blogs = [];

this.axios.get('/index, {})
                .then(res => {
                 blogs = res.data;    
                })
                .catch(err => {
                    console.error(err);
                });
                
             <!--前端模板渲染dom-->   
 <div  v-for="(item, index) in blogs" :key="item">               

同样我们输入
http://host:port/index

注意:SPA 通常有自己的路由策略,这也就是前端 MVC MVVM 中的 第一个 M

一个典型的 SPA 站点

我们输入网址先到了这个页面,然后再去异步请求服务器,再由前端页面渲染,又是单页面服务如果我们不做任何处理,那么你将被各大搜索引擎抛弃。

如何解决?

只要做 SEO 的产品就要做服务端渲染,如果你对 SEO 需求有,但要求并不高,仅部分页面、可以曲线救国

nodejs 出现之前有两种解决方式,一是做一动一静两套页面,服务器判断请求来自蜘蛛就呈现静态页,否则呈现动态页;二是服务器架设虚拟浏览器软件,请求过来了先让虚拟浏览器跑一遍,再将得到的静态页面返回给客户端。这两种方式在大型项目上都有性能问题。

有了 nodejs 后主流做法是前后端同构方案,即一套代码在浏览器端和 node 端都可以运行,从而可以先在 node 端请求数据渲染模板,然后将渲染结果返回给浏览器最终呈现。感兴趣可以看看
Vue 的 SSR 方案
Angular 的 SSR 方案

如何更细致的研究 SEO 以后再说

跨域

由于采用前后端分离部署,自然不在一个端口,不在一个端口必然跨域,不过这对现在的技术手段来说完全不是问题

开发模式
为了更快更好的开发,dev 下一般采用 node 做代理层,解决跨域,几乎无障碍开发,而且可以轻松切换环境。

部署模式
部署一般不依托 node 进行部署,通常我们发布到 HTTP 服务器,与服务端进行通信,通常使用 nginx 进行正向代理。

总结

我认为近几年,前后分离是一种趋势,它的诸多问题正在逐步得到解决,逐渐被大家接受。它确实使我们的架构变得更加清晰,如果你还在犹豫,为什么不大胆跟我走出第一步呢?

讲了两章概念我都已经忍不住想要马上带大家实践了:nerd::nerd::nerd:

关于我

往期文章

《从零构建前后分离 WEB 项目》 序 - 开源的意义

《从零构建前后分离 web 项目》:开篇 - 纵观 WEB 历史演变

《从零构建前后分离 web 项目》探究 - 深入聊聊前后分离架构

  • Vue.js

    Vue.js(读音 /vju ː/,类似于 view)是一个构建数据驱动的 Web 界面库。Vue.js 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件。

    265 引用 • 666 回帖 • 1 关注
  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3190 引用 • 8214 回帖 • 1 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
  • 我见过最彻底的前后端分离架构是的 zeronet
    .

    这货只通过 WebSocket 和服务器通讯。请求都是消息。

    1 回复
  • pkwenda
    作者

    哈哈 webpack 的 热更新也是 Socket