分享 后端渲染还是前后端分离?Listen to yourself.

lokyoung · 2018年06月07日 · 最后由 dada1380 回复于 2018年06月19日 · 7498 次阅读

TL;DR

本文提及的后端渲染主要指 Rails 后端渲染。这里说的前后端分离不意味着使用了 React/Vue 这样的前端库就是前后分离。在后端渲染的应用中也可以集成 React/Vue。

前言

最近这两年由于前端技术圈一直都很热门,有不少产品都做成了前后端分离的单页应用(SPA)。

关于前后端分离究竟是好还是不好,社区里之前曾有过一次比较激烈的探讨 https://ruby-china.org/topics/34846 。大家都各有各的看法,不过从这个话题的回答中我个人感觉社区中很多人其实是不太支持前后端分离的,毕竟 Rails 这样的全栈框架已经可以很好地适用于大多数应用,Rails 自带的 ujs 和 form 已经足够处理很多前端开发中的常见问题。

昨天看到有同学也在纠结是 Rails 项目是做成单页应用还是前后端分离 https://ruby-china.org/topics/36894 。我在最近的一个 Rails 项目里也有过这样的纠结和尝试,所以做了一段回答。我把之前问题的回答做了份整理,想说给大家听听。

我的尝试

我们在项目技术选型时想到有些界面的交互比较复杂,再加上我们想用 ant-design 的 UI,而实现了 ant-design 的 UI 库只有用 React/Vue/Angular 实现的。而 Vue 是一个相对轻量级的库,集成进 Rails 很容易。所以经过考虑,我们决定引入 Vue。但是不做成单页应用,就用后端渲染,想最大程度地利用 Rails 带给我们的便捷。(之前我也看到过很多批判前后分离的,所以在这里我主观上也是不希望做成单页应用的)

但是到了真正开发的时候,由于我们引入了基于 Vue 的第三方 UI 库,对于 Vue 的依赖其实比较重。而我们又是传统的后端渲染方式,所以碰到了这样几个问题:

  • 我们开启了 turbolinks,需要在 turbolinks 相应的 callback 中销毁和重新注册相关 Vue 组件。但是我们引入的第三方 UI 库的某些组件在 turbolinks 开启的情况下会出现一些意想不到的的问题。
  • 表单操作方面,Vue 不能直接在 Rails 原生的表单中使用。如果还是使用 ujs 的方式去处理表单,遇到需要 Vue 去处理某些数据绑定的操作,也还是不方便。如果使用 Vue 去构建 Form,提交表单只能发起异步请求,不会有 Rails 原生表单的行为,一些本来交给 Rails 处理的行为(例如在 controller 中 redirect)需要交给前端处理。而且这样的行为在一个非前后端分离的项目中可能会显得比较怪异。例:如果使用了 Vue 去提交一个表单,想在提交成功之后做 redirect。由于是一个异步请求,Rails 并不能帮助我们进行 redirect,只能在前端使用window.location这样类似的方式进行 redirect。这个行为既不符合 Rails 也不符合单页应用的规范。(单页应用中通常使用前端 Router 去跳转)
  • 前后端数据命名规范不一致。在 js 中,命名的规范是 camelCase,在 Rails 中是下划线的形式。使用了 Vue 之后在写前端逻辑时应该会倾向于 camelCase,所以我们还是需要对 Rails 返回给前端的数据做一道转换。

我们在最初的开发中就一直想着的就是避免做成单页应用,但是随着开发的进展和我们遇到的问题,我们发现我们的代码既不像一个后端渲染应用,也不像单页应用。究其根本,在我们决定使用基于 Vue 的 ant-design UI 库的时候,我们就应当想到重度依赖这些组件的界面,就应当做成单页应用。这样就可以减少很多不必要的麻烦。

单页应用的缺点

为什么我们在最初会坚持使用后端渲染而不是前后端分离呢?在这时我又重新思考了下项目开始时考虑到的单页应用的缺点:

  • SEO 问题。由于单页应用依赖 js 渲染,所以 SEO 一直是老生常谈的问题。只能通过引入 SSR(服务端渲染)解决。但是如果我们现在正在开发的是一个管理系统(SaaS/OA/CRM),大多数界面都是需要登录之后才可以访问的,所以爬虫压根就没有机会进入这些界面,也就不存在 SEO 的问题。而需要 SEO 的界面通常不会有很麻烦的交互,完全可以摆脱对前端框架的依赖,直接使用后端渲染。
  • 首屏加载。有很多调查表明首屏加载速度慢是网站用户流失的最大原因之一。单页应用需要在首页中加载大量的资源文件,所以加载耗时会比后端渲染更费时。但是现在主流的前端框架在 build production 版本的时候都会对资源文件进行优化压缩,配合 Lazy Loading、gzip,最后得到的资源文件大小并不会很大。
  • 让 Rails 变成了一个 API。Rails 在这里只是一个提供数据,处理后端业务逻辑的 API。Rails 中很多便利的东西我们都不能使用(View helper、form 以及很多前端相关的 gem)。在后端渲染情况下,同一个界面我们只需要维护一份 view。但是前后分离的话,在 Rails 层面我们需要维护返回的 json,在前端去维护真正的界面 template。

这三个主要痛点中,最后一点是我们无法去改变去优化的。Rails 这个全栈框架带给前端开发的各种优点,我们都将无法从中获益。但是换一个角度思考,在我自己的例子中,我因为不忍心放弃 Rails 在前端开发中的优势,在一些并不太适合用后端渲染的界面中使用 Rails 去渲染,反而束缚了自己,让 Rails 的这些优点成为了“阻碍”

后端渲染还是前后端分离?

这个问题没有标准答案,一切都需要根据我们的场景和环境所决定。针对于我们的场景,既然我们选择了基于 Vue 的 UI 库,也就意味着我们在前端方面会强依赖于 Vue,这时候如果为了使用后端渲染而选择后端渲染,则显得很不合时宜。事实也证明,强行后端渲染让我们花费了更多的精力去调试很多意外的问题,最后得到的还是一份不规范的代码。 究竟该如何选择,我想给出点简单的建议:

  • 如果你有很多重前端的场景,一些业务场景重度依赖于 React/Vue,或者说你使用了一些基于 React/Vue 的 UI 库。为了减少你处理一些不必要的麻烦的时间,建议直接上 SPA。一些轻交互或者无交互简单界面可以依旧使用后端渲染,更加方便。
  • 如果你仅仅是用 React/Vue 处理某些交互麻烦的地方,如果 React/Vue 对当前项目来说只是 jQuery 般的存在,后端渲染会是更好的选择。Rails 在很多产品中的成功经验让我们有这个信心能用 Rails 就完成大多数前端的开发工作。
  • 最最重要的是,选择适合当前团队的方案。如果你现在的团队成员有过 SPA 的经验,并且更适应 SPA 的开发方式,那么前后端分离无论是对于开发效率还是质量来说可能都是更好的方式。反之,如果你的团队更熟悉传统的后端渲染的方式,为什么就一定要为了前后端分离而分离呢?前后端分离只是一种不同的开发方式,前后端分离可以实现的业务使用后端渲染一样可以实现。

无论是后端渲染还是前后端分离,我们的目的都是为了解决问题。二者并没有优劣之分,都是针对 Web 开发的解决方案。无论我们采用其中哪种方式,使用怎样的框架和库,都是为了提升开发效率和质量,都是了给我们自己带来便利。而不是让我们自己去硬生生地去为了使用后端渲染或者前后端分离强行去适应,反而制造出很多本来没有的问题。

你不必因为这几年前端的“热”就去盲目追随这个潮流,所有场景不加思索就直接前后端分离,放弃后端渲染。同时,你也不必像我一样,在过于依赖前端框架、使用前后端分离会更合适的场景硬要上后端渲染。看清楚当前的业务场景,找到适合自己和团队的方式,高效高质量地开发才是我们最终的目标。

前几天看一个帖子,用 vue 干活的月工资 4k,问有一个 6.5k 的工作要不要跳槽。一年前还有一些培训机构在炒 vue,不到一年,已经白菜价。我赌 2 年后,vue 基本销声匿迹。

就在 1 年前,写 vue 的还看不起写 thinkphp 的😆

Vue 今年 Star 大概会超过 React ... 优势是 Vue 还支持 Pug / Sass 这些语法,hot reload 保存见效果. 劣势是如果得后端渲染要么写两份,要么用耗内存巨多的方法载一个 node 环境去渲染。API 调用太多效率也会超级低。

如果还想发挥 Rails 的优势,那么明显就是用 Turbolinks + Stimulus 而不是 Vue 这些啊。

luikore 回复

是的,我所遇到的问题是如果想要后端渲染,就不应当过度依赖 Vue。但是有的时候还是略无奈啊,现在很多开箱即用的 UI 库(material、element、ant-design)几乎都是基于 Vue/React/Angular 实现的。既然选择重度依赖前端框架,其实就不该再强行依赖 Rails 在前端方面的传统优势了。

比较同意楼主的看法

现在的项目面向用户的使用的是 SSR
面向企业的管理画面使用的是 SPA(react + flux+ immutable.js)
以前也做过 angular 的项目

个人的看法,可以用 Rails 来解决的,没必要去用 SAP,只会加大你维护的难度和开发的时间

为什么用 SPA,因为前端交互太多, 用 jquery 也可以写,但是难以维护,jquery 太依赖 dom 结构,你很可能不小心就掉坑里了

说说用 react 做管理画面的感受

好处

  1. 更好的交互
  2. 很多 UI 组件可以重用
  3. 比用 jquery 写好维护

不好的地方

  1. 对于浏览器的支持不够,IE9,10 各种 bug,IE11 也有 bug,各种等 hotfix
    • 你的用户不需要 IE 的话,可以忽略
  2. 画面更新的时候,你必须弄清楚某个操作以后需要更新哪些地方,不小心就会漏掉
    • 你可以说这不是 bug,你重新刷下下页面就好了
  3. ajax 的异步处理有时候会有些麻烦,你需要搞清楚你发送的 API 是否是有顺序的,还是不需要在意顺序
  4. 异常的追踪远远难于 SSR
    • 原因很简单,用户使用的浏览器环境不同,问题也不同,chrome 没问题,换个浏览器,换个设置也许就不行了
    • 我们用 sentry 把异常收集起来,但是有不少异常再现很难
heroyct 回复

谢谢。Rails 渲染和 SPA 都有自己的合适的场景,不拘泥于框架、找到适合自己的解决方式才是最实际的。

lokyoung 关闭了讨论。 06月08日 10:40
lokyoung 重新开启了讨论。 06月08日 10:40

前后端分离后的前端更应该当作一个独立的应用程序,而不是某个大产品的附属。如果再考虑离线和数据同步的情况,也可以说是一种分布式系统了。因此我觉得考虑是否分离的最大因素,就是前端是否复杂到了需要做成一个独立的应用程序。

本质上这是衡量软件复杂度和抽象的问题。一方面它取决于实际需求。比如 MVC 分层是 web 框架最佳实践?做个简单的网站也许并不需要,Sinatra 那种在 block 里写实现的方式也许更快;jQuery 难以维护?如果你的需求只是网页上加少数动态组件可能它更简单。另一方面也在于开发者自身的技术背景。同样做个 SPA 在专业前端和顺带写点网页的后端眼里复杂度可能完全不同,因此做出的决策也不同,但结果可能殊途同归。

Vue 对于我只是 jQuery 一般的存在,一般是用 dom 操作比较方便的就 jQuery 了,View-Data 变化比较多且频繁的就 Vue 了。不过最近用 stimulus 替换了 vue。

总的原则,代码怎么写的少怎么来。

借助 webpacker,代码结构及模块管理也很容易清晰。

mingyuan0715 回复

大面积使用 Vue/React 还是适合 SPA,本以为 Rails 后端渲染也没问题的,结果带来了太多不必要的麻烦。

从前端发展史来看前后端分离是必然的结果,Rails 社区很开发,比起思考使用场景还是选择拥抱前端工具链把。 前后端分离的主要目的有两个,一个是代码的解耦,另一个是构建前端工作流。如果是一个足够健壮的项目,即使不依赖任何前端框架,分离也得做。webpack,gulp,babel 等构建工具实在太好用了。

1.seo 的问题本质不是前端渲染造成的,而是用了 mvvm 框架 dom 在 js 实例执行后才开始挂载到页面。不用 mvvm 的话还是有些解决方案的。 2.首屏加载速度也不是因为前端渲染,而是选择了 spa。

基于以上两点如果你了解 spa 应用,会发现大部分 spa 都不需要做 seo,而且用户体验很好。如果项目有特殊需求可以加层 node 服务端渲染(知乎,淘金,微博等这么做的)

需要 登录 后方可回复, 如果你还没有账号请 注册新账号