前后端合作新模式

2019-07-13 admin

本文主要介绍一种全新的前后端合作模式,在介绍这种模式之前咋们先来看看前后端合作模式的演变。

singsong:该模式主要对传统多页面应用构建的改进。关于 SPA(Single Page Application,单页应用程序)可以参考 SRR(Server-Side Render,服务端渲染)。

演变

在那个前端角色比较弱化的年代,页面主要以静态页面为主。合作模式很简单粗暴。

model-1

前端开发完页面,输出给后端。后端拿到页面拼模板,然后再渲染输出。但随着前端业务复杂性逐渐地增加,这种模式合作起来就不是很愉快了。后端在拼模板时,不能确保输出的页面结构与前端保持一致。为了规避这个问题,聪明的开发人员就给前端同学建议:使用后端开发环境开发前端页面

model-2

前端直接在本地部署后端开发环境,只负责 views 开发。再基于代码托管工具 git,实现前后端的合作。此时还是以后端为主导,维护性成本依然很高。

随着 node.js 的崛起,前端工程化也逐渐成为前端开发重要组成部分。各种构建工具(如 webpack、rollup、grunt、gulp 等),MVVM 框架(如 React、Vue、Angular 等),模块化系统(cjs、amd、umd、ES6-modules 等),CSS 预处理器(SASS、Less、Stylus、Postcss 等),模块管理工具(NPM、Yarn、brower 等)犹如雨后春笋般不断涌现。SAP 也开始在前端领域流行来,前端能做的事情更多。如客户端渲染,静态分析、优化打包等。后端只需负责数据提供。此时,前后端已完全分离,各自负责各自的业务。

model-3

这种合作模式的核心:客户端渲染 + 接口。由于基于客户端渲染,对浏览器的 SEO 不是很友好。虽然可以通过 SRR 来解决,但是 SRR 也存在局限性。关于 SRR 感兴趣的同学可自行查阅相关的资料。本文主要探讨传统多页面应用构建的优化。

基于前端工程化,要让传统多页面应用构建也支持前后端完全分离。还需要做一件事,前端脚手架需要与后端使用相同的模板渲染引擎。前端编写好后,直接输出模板给后端使用。为此自己也构建一个 fes 脚手架。

model-4

在使用 fes 构建了几个项目后,虽然在开发体验、开发效率上都得到了很大地提升。但与后端合作起来不是很轻松。因为在开发之前需要与后端约定好模板数据变量,一般会以文档形式进行说明。如果后端更新了数据,没同步更新文档,就会存在数据不一致的问题。对开发效率大打折扣,与传统的后端重新拼接模板相比优势不是很明显。秉着 geek 的精神,就想能不能 将模板数据以接口的形式提供给前端。这样上述问题不就迎刃而解了么。

model-5

于是就对 fes 进行改造。让其支持模板数据接口的配置,在渲染之前会根据配置拉起接口数据,再进行渲染输出。同时还提供了接口数据适配功能,能让客户端更好地控制数据结构。

mockConfig: {
  // 访问路径作为key
  '/index': {
    // 提供渲染模板数据接口
    api: 'https://postman-echo.com/get?page=index',
    // 适配数据
    format: data => data.args,
  },
  '/fes/info': {
    api: 'https://postman-echo.com/get?page=info',
    format: data => data.args,
  },
}

另外,为了方便查看模板数据,开发模式下输入 mock 指令可获取当前的模板数据。

$ mock
Mock Data:

{
    "/about": {
        "page": "about",
        "common": "commons",
        "data": "singsong",
        "name": "fes-about-page"
    },
    "/index": {
        "page": "index",
        "common": "commons",
        "name": "fes-index-page",
        "data": {
            "name": "fes"
        },
        "article": {
            "_value": {},
            "_state": 1
        }
    },
    "/post": {
        "common": "commons"
    }
}

如果需要查看对应页面数据,只需输入对应的路径即可。如 /index

$ /index
Mock Data [/index]:

{
    "page": "index",
    "common": "commons",
    "name": "fes-index-page",
    "data": {
        "name": "fes"
    },
    "article": {
        "_value": {},
        "_state": 1
    }
}

除了 mock 指令,还提供了如下指令:

  • mock: 查看当前的 mock 数据
  • view: 打印范围地址和二维码信息
  • clear: 清空控制台

这种合作模式,需要后端多做一件事。额外提供一个包含模板数据的接口供前端使用(只存在开发环境下,在上线时需要关闭掉)。只需对该类接口定义特定的前缀,然后在模板渲染逻辑之前拦截请求响应数据。这样不仅能保持数据一致性,而且维护起来也方便。

Demo

这里以改进后 fes 进行演示。如下以 index 页面 为例进行讲解:

前端修改

index 页面路由为:http://127.0.0.1:3001/index,结构如下:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>{{ title }}</title>
  </head>
  <body>
    <h1>{{ title }}</h1>
  </body>
</html>

模板数据接口为:http://127.0.0.1:3001/mockdata/index。其中/mockdata为前缀,接口返回的数据如下:

{
  "rawdata": {
    "title": "index page"
  },
}

在 fes 中对模板数据接口进行如下配置

mockConfig: {
  // 访问路径作为key
  '/index': {
    // 提供渲染模板数据接口
    api: 'http://127.0.0.1:3001/mockdata/index',
  }
}

这里如果只想要 rawdata 中的变量数据。可以通过format 进行适配。最后的配置信息如下:

mockConfig: {
  // 访问路径作为key
  '/index': {
    // 提供渲染模板数据接口
    api: 'http://127.0.0.1:3001/mockdata/index',
    // 适配数据
    format: data => data.rawdata,
  }
}

后端修改

  • 路由处理器

    //path: ./controllers/index.js
    module.exports = async ctx => {
      const {url} = ctx;
      // 从 DB 获取数据
      const getDataFromDB = () => {
        // 做一些数据查询操作……
        return {
          rawdata: {
            title: 'index page',
          },
        };
      };
      const data = getDataFromDB();
    
      // 判断是否有前缀进行不同的响应
      // 这里前缀已保存在 ctx.mockApiPrefix 中
      if (url.indexOf(ctx.mockApiPrefix) === 0) {
        ctx.body = data;
      } else {
        await ctx.render('index', data.rawdata);
      }
    };
    
  • 定义路由

    // path: ./pages/index.js
    // 该接口与页面请求使用相同的路由处理,通过是否有`PREFIX`进行区别
    module.exports = (PREFIX = '') => [
      {
        method: 'get',
        path: `${PREFIX}/index`,
        middleware: require('./controllers/index'),
      },
    ];
    
  • 注册路由

    const Router = require('koa-router');
    const router = new Router();
    
    const pagesConfig = require('./pages/index');
    
    const config = [];
    // 定义前缀
    const MOCK_API_PREFIX = '/mockdata';
    // 注册页面路由
    config.push(...pagesConfig());
    
    // 注册模板数据接口
    if (process.env.NODE === 'dev') {
      config.push(...pagesConfig(MOCK_API_PREFIX));
    }
    
    const generateRoutes = (router, config) => {
      config.forEach(({method, path, middleware}) => {
        router[method](path, middleware);
      });
    };
    
    module.exports = app => (ctx, next) => {
      // 绑定前缀,方便后续逻辑使用
      ctx.mockApiPrefix = MOCK_API_PREFIX;
      generateRoutes(router, config);
      app.use(router.routes()).use(router.allowedMethods());
      return next();
    };
    

运行效果:

总结

本文主要与大家分享一种前后端合作新模式,也许当成一种新思路更恰当些😀,因为它只是对多页面应用构建的一种优化。不管怎样也希望本文能让各位读者有所收获。周末愉快~~~🌴

[转载]原文链接:https://segmentfault.com/a/1190000019752589

本站文章除注明转载外,均为本站原创或编译。欢迎任何形式的转载,但请务必注明出处。

转载请注明:文章转载自 JavaScript中文网 [https://www.javascriptcn.com]

本文地址:https://www.javascriptcn.com/read-69674.html

文章标题:前后端合作新模式

相关文章
Easyui Tree获取当前选择节点的所有顶级父节点
只支持四层目录结构,比较笨的一个方法 JS代码 var node = $(&#x27;#tree&#x27;).tree(&#x27;getSelected&#x27;); &#x2F;&#x2F;获取该节点所有父节点 ...
2017-03-17
前端工程师应该具备的三种思维
如果你是一个天才等级的工程师(马上可以离开),可以独立完成一个很多事情,你可以是一个怪咖,因为我相信没有一个人不会不佩服你。但现实归现实,多数人都不是天才,而我们在职场上也不是单打独斗,我们需要团队合作,需要协调和配合,需要考虑除了代码以外...
2016-01-13
前端开发领域推荐关注的微信公众号
这篇文章分享了前端领域的多个值得关注的技术、设计、极客、创业相关微信公众号。其中有最受欢迎的热门公众号、也有专注某个技术或设计的公众号,涵盖:算法、JavaScript、Nodejs、程序员、Web前端、Linux、数据库、创业、UI设计和...
2017-03-23
五个值得尝试的前端开发工具
在过去的几年时间里,出现了许多全新的网页应用程序,不过,由于应用程序的功能越来越丰富,也导致了前端开发的复杂度大幅增加。 现在也有不少前端开发工具,比如Backbone和EmberJS框架都能提供稳定的App开发解决方案。同时,Javasc...
2015-12-23
js实现时间显示几天前、几小时前或者几分钟前的方法集锦
这里汇总了js实现时间显示几天前、几小时前或者几分钟前的常见方法。分享给大家供大家参考。具体如下: 方法一: 个人做法是保存时间戳,然后在前端用jq插件做转换,比如 smart-time-ago 方法二: (通过freemarker模板)如...
2017-03-24
如何用js 实现依赖注入的思想,后端框架思想搬到前端来
大家在做些页面的时候,很多都是用ajax实现的,在显示的时候有很多表单提交的add或者update操作,显然这样很烦,突然想到了一个比较好的方法,下面给大家分享下如何用js 实现依赖注入的思想,后端框架思想搬到前端来。 应用场景: 前后端一...
2017-03-29
使用javascript将时间转换成今天,昨天,前天等格式
方法超级简单,把时间格式化一下就好了,直接奉上代码 function transDate() { var $time =document.getElementById(&quot;share-time&quot;); var...
2017-03-25
详解vue-Resource(与后端数据交互)
单来说,vue-resource就像jQuery里的$.ajax,用来和后端交互数据的。可以放在created或者ready里面运行来获取或者更新数据… vue-resource文档:https://github.com/vuejs/vue...
2017-03-07
前端单页应用微服务化解决方案2 - Single-SPA
技术选型 经过各种技术调研我们最终选择的方案是基于 Single-SPA 来实现我们的前端微服务化. Single-SPA 一个用于前端微服务化的JavaScript前端解决方案 使用Single-SPA之后,你可以这样做: (兼容各...
2018-09-07
Vue.js bootstrap前端实现分页和排序
写之前先抱怨几句。本来一心一意做.net开发的,渐渐地成了只做前端。最近项目基本都用java做后台,我们这些.net的就成了前端,不是用wpf做界面,就是用html写web页面。 深知自己前端技术不足,以前虽说用asp.net前后台都做,但...
2017-03-14
回到顶部