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

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

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

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

共收到 10 条回复

前几天看一个帖子,用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服务端渲染(知乎,淘金,微博等这么做的)

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