前后分离

写在最开始
移动端与前端的区别
前端开发的混沌时代
后端 MVC
        MVC 方案实现
        MVC 的缺点与改进
         前端只写 Demo
         HTML 模板
         后端 MVC 架构总结
AJAX 与前端 MVC
前后端分离的缺点
        双端 MVC 不统一
        SEO
        性能不够
         集中 Or 分离
Nodejs
         前后端分离的哲学
         Nodejs 分层
         实战应用
           风险控制
总结
参考资料

写在最开始

这是一篇面向移动端开发者的科普性文章,从前端开发的最初流程开始,结合示范代码,讨论开发流程的演变过程,希望能覆盖一部分前端开发技术栈,从而对前端开发的相关概念形成初步的认识。

本文会提供一些示范代码,然而他们无法运行,也不需要完全看懂,更多的是方便读者对相关概念和方案有更加具体形象的感受和更清晰的理解。

在写作过程中,我阅读学习了淘宝在前后端分离和前端开发技术演变方面的博客,受益匪浅,相关文章都罗列在文末的参考资料中。同时由于自身能力有限,对很多概念的理解比较浅显,甚至有误,欢迎交流指正。

移动端与前端的区别

在开发 App 的过程中,我们不会刻意思考开发流程,因为一切看上去都非常自然。可以本地确定的内容就直接写死,否则异步发起网络请求并动态的修改,最后把源代码编译成可执行的二进制文件供客户安装。

前端开发和移动端开发就有本质的不同了。一个网页的最终展现样式受到 HTML + CSS 的影响,而 JavaScript 脚本负责用户交互。一个页面不会被编译成可执行文件,它仅仅由几个文本文件组成,由服务端明文下发给浏览器并绘制到屏幕上。

下文中可能会反复提到“渲染”的概念,除非特别说明,它不表示解析 HTML 文档(DOM)并绘制到屏幕上这个过程,因为这一步由浏览器内核实现,普通情况下不需要做过多了解和干预。

网页可以分为静态、动态两种,前者就是一个 HTML 文件,后者可能只是一份模板,在请求时动态的计算出数据,最后拼接成 HTML 格式的字符串,这个过程就被称为渲染。

前端与移动端开发另一个显著差异是: 虽然可以在本地调试 HTML,但实际上这些 HTML 的内容需要部署在服务端,这样才能在用户发起 HTTP 请求时返回 HTML 格式的文本。

前端开发的混沌时代

一开始,我们没有任何工具,只能靠蛮力。我们知道 Servlet 是由 Java 编写的服务端程序,可以方便的处理 HTTP 请求和返回,因此可以直接把 HTML 文本当做字符串返回,也就是上文所说的渲染:

public class HelloWorldServlet extends HttpServlet {
    @Override
    public void doGet(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException {
        resp.setContentType("text/html");

        PrintWriter out = resp.getWriter();
        out.println("Hello World Sample");
        out.println("

Hello World Title

" +new Date().toLocaleString() + "

"
); out.flush(); } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

理论上来说,我们已经可以开始所有前端开发了,但在这混沌初开的年代,想写出一份可维护的代码恐怕得用上“洪荒之力”。把 UI 和业务逻辑写在一起是一种非常强的耦合,不利于项目日后的拓展。也无法要求每个人同时会写 Java 和前端。

后端 MVC

上述方案的问题之一在于逻辑混乱不清,移动开发者在入门阶段大多也经历过,解决方案比较简单:使用 MVC,把业务逻辑抽离到 Controller 中,让 View 层专注于显示 UI。

MVC 方案实现

在前端开发领域,也有类似的技术,比如 JSP,它经过编译后变成 Servlet。在写 JSP 的时候,我们更加关心页面样式,因此代码看起来就像是 HTML,不过在 <% %> 代码块中可以调用 Java 函数:

<HTML>
<HEAD>
<TITLE>JSP测试页面---HelloWorld!TITLE>
HEAD>
<BODY>
<%
    out.println("

Hello World!

"
); %>
BODY> HTML>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

JSP 相当于 View 层,它从 Model 中获取数据,说的再具体一点,是使用后端的语言(比如 Java)去访问 Model 层提供的接口。

Controller 作为直接和客户端接触的模块,负责解析请求,数据校验,路由分发,结果返回等等逻辑。路由分发是指根据请求路径的不同,调用不同的 Model 和 View 提供服务。

MVC 的缺点与改进

使用了 MVC 架构(比如大名鼎鼎的 Struts)后,似乎职责变清晰了,前端开发者负责写 JSP,后端开发者负责写 Controller 和 Model,然而在实际开发时还是有诸多问题。

首先业务逻辑依然没有严格区分,如果没有良好的编码规范,JSP 中就会混入大量业务逻辑。而一个框架存在的作用应该是让没有接受很多培训的新人也能写出合格的代码。此外,前端开发者还需要对后端逻辑有大致的了解,熟悉后端编程语言,因此也存在很多沟通、学习成本。

前端只写 Demo

一种解决方案是前端开发者只写 Demo,也就是提供静态的 HTML 效果给后端开发者,由后端开发者去完成视图层(比如 JSP)的开发。这样前端开发者就完全不需要了解后端知识了。

可惜这种想法很好,但是一旦付诸实现就会遇到不少问题。首先后端开发者依赖于前端的 Demo,只有看到 HTML 文件他们才可以开始实现 View 层。而前端又依赖于后端开发者完成整体的开发,才能通过网络访问来检查最终的效果,否则他们无法获取真实的数据。

更糟糕的是,一旦需求发生变动,上述流程还需要重新走一遍,前后端的交流依旧无法避免。概况来说就是前后端对接成本太高。

举个例子,在开发 App 的时候,你的同事给你发来一段代码,其中是一个本地写死的视图,然后告诉你:“这个按钮的文字要从数据库,那个图片的内容要通过网络请求获取,你把代码改造一下吧。”。于是你花了半天时间改好了代码,PM 跑来告诉你按钮文字写死就好,但是背景颜色要从数据库读取,另外,再加一个按钮吧。WTF?

显然这种开发流程效率极低,难以接受。

HTML 模板

其实一定程度上来说,JSP 可以看做 HTML 模板的雏形。HTML 大体上肩负了两个任务: 页面框架和内容描述。所谓的 HTML 模板是指利用一种结构化的语法,表示出 HTML 的框架,同时把具体数据抽离出来。

比如 

111

 表示一个段落,其中内容为 “111”。如果用模板来表示,可以写作 

Content

 或者p Content 等等。总之,不要纠结于具体语法,我们只要知道:

数据 + 模板 = HTML 源码

比如在 Controller 层,可以这样调用:

// 这里没有指定模板的名称,是因为使用了依赖倒置的思想,在配置文件中绑定了 Controller 对应的 View
return res.view({title: "111"});
  • 1
  • 2

模板中的代码如下:

<%= Content%>h1>
  • 1

熟悉前端开发的读者可能会发现,这其实采用了 Sails.js + EJS 开发。前者是基于 JavaScript 的服务端应用程序,后者是基于 HTML 语法的模板,另一种风格的模板是 Jade,不过本文的目的并不是重点介绍这些工具如何使用,就不再赘述了。

回到模板的概念上来,它相对于 JSP 的优势在于,利用工具强行禁止前端开发者在视图层写业务逻辑。前端开发者只需要关心 UI 实现并确定 HTML 中的变量。而后端开发者只要传入参数即可获取 HTML 格式的字符串。

模板开发的另一个好处是前后端可以同步开发。双方约定一个数据格式,前端就可以模拟出假数据并用来自测,后端也可以用生成的数据与假数据对比进行测试。同时,这个约定的数据格式扮演了契约和文档的作用,规范了双方的数据交流形式,从而节省交流的时间成本。关于更多 Mock Server 的话题,请参考 这个连接。

后端 MVC 架构总结

使用后端 MVC 架构加上模板开发是当前比较主流的一种开发模型,但它也不是完美的。由于模板由前端开发者完成,所以要求前端开发者对后端环境(注意这里不是实现细节)有所了解。

举个简单例子,大型应用的后端要分很多文件夹,这就要求前端对代码组织结构有所了解,上传文件时需要掌握 ssh、vim 并且依赖于服务端环境。

总的来说,采用服务端 MVC 方案时,HTML 在后端渲染,整体开发流程也全部基于后端环境。因此前端工程师不可避免的需要依赖于后端(虽然使用模板后情况已经大大改善)。

AJAX 与前端 MVC

AJAX 的全称是 Asynchronous Javascript And XML,即 “异步 JavaScript 和 XML”。它并非一个框架,而是一种编程思想。它利用 JavaScript 异步发起请求,结果以 XML 格式返回,随后 JavaScript 可以根据返回结果局部操作 DOM。

AJAX 最大的优点是不用重新加载全部数据,而是只要获取改动的内容即可。这在移动端编程中看上去是天经地义的,而前端开发则需要专门使用 AJAX 来实现,默认情况下网页的任何一处微小改动都需要重新加载整个网页。

类比移动应用就会发现,AJAX 适合做单页面更新,但是不擅长页面跳转,就像你的 app 页面跳转都是新建一个 UIViewController/Activity 而不是直接把当前页面的内容全部换掉。

得益于 AJAX 的提出,HTML 在前端渲染变成了可能。我们可以下载一个空壳 HTML 文件和一个 JavaScript 脚本,然后在 JavaScript 脚本中获取数据,为 DOM 添加节点。

这时候就出现了很多前端的 MVC 框架,比如 Backbone.js,AngularJS(姑且认为MVVM 是 MVC 的变种) 等一堆名词,你可以从 这里 找到他们各自的 Demo。以我相对熟悉的 React 为例:


<html>

<head>
  <script src="../build/react.js">script>
  <script src="../build/react-dom.js">script>
  <script src="../build/browser.min.js">script>
head>

<body>
  <div id="example">div>
  <script type="text/babel">
    var LikeButton = React.createClass({ 
      getInitialState: function() { 
        return {liked: false}; 
      }, 
      handleClick: function(event) { 
        this.setState({liked: !this.state.liked}); 
      }, 
      render: function() { 
        var text = this.state.liked ? 'like' : 'haven\'t liked'; 
        return (
          <p onClick={this.handleClick}>
            You {text} this. Click to toggle.
          p>
        ); 
      } 
    }); 
    ReactDOM.render(
      <LikeButton />, 
      document.getElementById('example') 
    );
  script>
body>

html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

这段代码不用完全读懂,你只要意识到,引入 React.js 这个框架后,我们就可以脱离 HTML 编程了。所有的逻辑都写在 

你可能感兴趣的:(服务器开发)