前端搭建系统学习分享

2020 年 04 月 02 日

阅读量:0

正文共 3528 字,预计阅读时间 18 分钟

banner

前言

最近在掘金上写文章,偶然看到了系统推荐的前端早早聊的活动。

应该一直都有,但是之前没怎么注意。

这次已经是第三届了,主题是前端搞搭建。

我在前端的工作经验较少,而且所任职的公司都没有这类系统。

出于好奇心,决定看一下,大厂是如何做搭建系统的。

这是讲师团队的阵容。

讲师团队

据说讲师平均水平都是阿里 P8 级别的,单凭这一点,77 块钱的活动费真的不算贵。

大会的目的是解决如下困惑:

  • 每天陷在业务中,机械的切页面写功能
  • 想要提升开发效率,不知道从哪里下手
  • 变来变去的营销页面,可不可以快速生成
  • 前端技术一直变,切页面有哪些新的方式
  • 一个可视化搭建工具,需要具备哪些模块
  • 如果尝试开发搭建工具,有哪些实现难点

在观看大会之前,我和很多没接触搭建系统的人有类似的看法,AI 自动生成 HTML 好像还是个天方夜谭。但通过短短一天时间,彻底改变了我这种看法。

  • “业务做不快,加班加不完”

  • “联调时扯皮,成就感缺失”

  • “公司不重视,前端地位低”

  • “需求做不完,技术没成长”

  • “那么多页面,能不能搭建”

这些问题,每个前端在每个公司或多或少都存在。虽然大会提供了针对可能性、方法论和技术实现的讲解。但我个人认为,在公司具体落地搭建系统,还是要靠如下三点。

  1. 公司确实需要该项技术。
  2. 技术人员个人主观意识,愿意主动推进。
  3. 公司技术管理层足够重视。

搭建系统的目的是为了提效,只有公司需要提效、开发人员需要提效,搭建系统才有意义。

搭建系统能力讲解

搭建系统的能力在我的理解里分为两种。

一种是拖拉拽生成 HTML 文件,然后配置数据源。一键部署上线,支持版本回滚等基本操作。

一种是根据根据设计稿生成 HTML,或者根据 json schema 智能生成 HTML。同样支持一键部署上线,支持版本回滚等基本操作。

第一种其实在几年前就有了,记得在 15、16 年那阵,bootstrap 就有可视化拖拉拽生成系统。但那都是些半成品,而且不支持数据源的配置等操作。

第二种的话比较难,因为需要用到人工智能和机器学习技术。在中小型前端团队里,很难实现这类能力。像阿里这种大型团队,目前探索的脚步已经走的非常远了。它们的产品非常强大,可以在 imgCook 上体验一下,处理一些简单的设计稿绰绰有余,但我尝试过处理复杂页面,效果很糟。

搭建系统特别适合电商营销运营场景,大名鼎鼎的鲁班系统就是为此而生。

像天猫、京东、淘宝这些大型电商网站,他们的活动页面基本上都是靠搭建系统生成出来的,当然有一些可能需要再进行微调。

普遍意义上,搭建系统的用户并不是开发人员,而是设计师或者运营。

而前端开发人员在其中担任的角色就是能力的提供者。把创造页面的能力通过搭建系统提供给运营、产品和设计。这个模式像极了依赖注入模式。

在我们技术人眼里特别简单的易企秀,其实就是一个类搭建系统。他们把创造页面的能力提供给完全不懂技术的普通人,只不过限制较多。

搭建系统简易版技术实现

实现搭建系统是一个庞大的工程,中小团队很难把这件事做好。

做好这件事,我认为需要具备以下条件:

  1. 有对技术有追求,爱折腾的人。
  2. 有足够的时间,搭建系统更像是一个产品,而不是单纯的开发工具。

我个人爱折腾,但没有时间。在看完直播后利用空闲时间(最近忙的要死,根本没有空闲时间,基本上都是在占用睡眠时间)做了一个简单的搭建系统。

因为技术分享的信息量太过于密集,很多东西没来得急仔细研究。现在 PPT 和录播也还没公开,所以很多细节都是靠自己的理解、琢磨和网上查找的资料来完成的。

借鉴了:

  • 阿里淘系技术 - 鲁班系统
  • 京东惊喜 - MPM 系统

根据计算机之子、知乎三大软狗之一的 winter 程劭非的专栏《重学前端》中介绍,实现搭建系统在技术层面大概是有 3 种流派。

  1. 模板化搭建,最老的那种实现。前端工程师生产模板,运营提供数据,组合起来形成页面。淘宝就是这么实现的,我们公司的老版 PC 商城也有类似的功能。
  2. 模块化搭建,由前端工程师提供模块,由运营组合模块和提供数据形成页面,属于模板化搭建的升级。
  3. 数据驱动界面,最高级的思路。

接下来的实现,我采用的是最高级的思路,数据驱动界面。

网络代理

我使用的是 nginx 作为网络代理。

直出端

需要有一个服务端来渲染页面,我本来选择的是 node 的 SSR 框架 next.js。next.js 的优点是可以同构,这也是 node.js 和前端契合的一个关键。如果选择其它语言,如 Java、Go,同构的地方就需要写两份代码。但是页面生成的不是 react 代码,所以我干脆用原生 node.js 做了一个类似于 next.js 的 SSR 框架。

initialPageData JSON Schema

使用 json schema 定义一份 initialPageData,作为生成页面的依据。

{
  "pageId": "demo0007",
  "appType": "1",
  "dataSource": [
    {
      "url": "https://d.luzhenqian.me/api/demo0001",
      "methods": "GET",
      "resultMapName": "data"
    }
  ],
  "modules": [
    {
      "id": "m33",
      "styles": {
        "background": "#ffffff",
        "font-size": "1.25rem"
      },
      "components": [
        {
          "id": "c103",
          "elements": [
            {
              "text": {
                "id": "e.txt00001",
                "content": "演示",
                "styles": {
                  "background-color": "#ffdd66",
                  "font-size": "1em"
                }
              },
              "input": {
                "id": "e.ipt.000001",
                "defaultValue": "hi",
                "styles": {
                  "background": "red",
                  "font-size": "1em"
                }
              },
              "buttons": {
                "id": "e.t000001",
                "onClick": {
                  "url": "https://d.luzhenqian.me/api/demo0004",
                  "methods": "GET",
                  "params": "e.ipt.000001",
                  "callback": {
                    "jump": {
                      "pageId": "demo0007",
                      "initialParams": true
                    }
                  }
                }
              }
            }
          ]
        }
      ]
    }
  ],
  "dataCache": {}
}

这个 json 的格式很大程度上借鉴了京东惊喜的 MPM,但又有所改进。因为我支持了接口的调用等功能。

一些小的改进

我把一个页面上的所有可以看到的事物拆解成三类。

大的模块 module,中等的组件 component,最小的元件 element。

通过这三类事物的组合,构成一个页面。

module 一般是标题头,或者豆腐块列表等常用的区域,可以通过配置背景色、背景图、边距、宽高等来自定义样式。

component 和传统开发中的组件概念类似,但比传统组件稍大一些,因为它可能是复合型业务组件。

element 是最基本的元件,与传统概念中的组件一样,比如 button、text 等。

这个 json 存放在数据库中。由于这份 json 的格式是非常不固定且随时会变动的。MySQL 这类关系型数据库直接 pass 掉。mongodb 和 json 简直是天选之和,没有理由不使用 mongodb。

并且将页面的数据源升至顶层,在 SSR 阶段,通过 next.js 的 getInitialProps 方法在页面渲染前就把整个页面中所有的数据提取到,并且将数据格式简单的处理,映射成你想要的名字。你可以自定义 params 和 data 作为数据源的参数。你也可以配置多个数据源,服务端会自动帮你合并。这里面有一个很细节的点,多个数据源的返回数据命名一致时,并不会发生 js 默认的覆盖行为,而是使用合并策略。

个人感觉最难处理的点是交互,目前我只能给元件添加事件,并且事件只能是发送请求或者跳转页面,你可以选择这条请求是否需要附带参数,和指定哪些参数。这个请求可以触发回调,回调同样触发一个事件,该事件同样只支持发送请求或跳转页面。

版本管理、回滚和发布

至于版本的管理,技术实现上比较简单。功能主要是版本回滚与动态发布。

当保存 json schema 时,都会在 mongodb 中生成一个新的记录,而不会修改原来的记录,并给这个新记录一个版本号和一个标记。

如果需要回滚,只需要将标记移到对应的记录上即可。

这个思想是借鉴了 redux 的 immutable 思想,因为前些日子在写 redux 的文章,对 redux 的理解又加深了一些。因为 redux 的时间旅行就是依此实现的。

一键发布也是通过移动标记,每次移动标记时,都会在 直出端项目下修改一个 json 文件。

直出端项目通过 pm2 来部署,在部署时添加 --watch 参数,这样当 json 文件发生变化时,pm2 会 restart 服务端项目,重新在 mongodb 中获取当前的最新的数据。

在 restart 过程中,如果有页面请求怎么办?使用集群部署就好了。然后 json 变化时,创建一个任务队列,将集群中每个进程按顺序依次 restart。前一个服务 restart 结束,下一个再 restart。这样会保证系统的可访问性。

整体架构图

我付出的时间比较短,做出的东西相对简单,架构如下:

架构图

可以看到,整个过程都没有使用 docker,原因是 docker 实在是太臃肿了,我已经放弃使用 docker(除非服务器硬盘足够大)。

到此为止,虽然我实现了一个搭建系统最核心的部分,但距离生产还有很大的距离。

可优化的点

由于时间问题(实现上面这些事我用了两个晚上),很多细节都没来得及优化。

比如:

  • 用户鉴权、系统配置、客户端页面

  • 组件、模块的组合

  • json schema 的校验

  • 可视化拖拽调整位置、宽高等

  • 模块、组件的数据源配置(这个实现比较难,因为 next.js 不支持组件级别的 getInitialProps,但我有些思路)

  • 动态路由的实现

  • 编辑动态保存

  • 目前生成的是原生 HTML,计划支持生成 React 和 Vue,并可以定制化代码。

  • 搭建物料市场

  • 错误自动上报

  • 自动化性能分析

  • 其它我还没想到的点...

搭建系统无能为力的地方以及痛点

无能为力的地方就是强交互页面,因为这不是搭建系统该负责的。

痛点有很多,但我觉得最难的是接口,因为那些乱七八糟的数据格式实在是难以梳理。这里就需要借助 BFF 层,把那些乱七八糟的接口整理成让人调用起来可以感到愉悦的接口。

写在最后

通过这次直播学习、自我总结和实践,带给我最大的收获是技术视野的增长。

当普通人还在接口扯皮调数据、怼需求切页面时,业界大厂已经开始研究如何自动化实现这些东西了。可以预见,未来几年,必然会淘汰更多的初中级前端,只有早早掌握最为核心的能力,晋升为高级前端才能在技术革新浪潮中幸免于难。

通过借鉴别人思路,自己思考和动手,实现搭建系统的核心部分代码。这也让我拥有了未来应对开发搭建系统的能力。我认为,编程这件事并不只是单纯去学,更多的是靠自己思考、自己动手。最后把所思所想所获所得整理出来,分享出去。

分享到此结束,希望对你有所帮助。


你好,我是 卢振千,一名软件工程师。欢迎你来到我的网站。