🌞

记录一次借壳开发重构之旅

内部工具的一次重构,记录下重构过程遇到的坑背景内部使用的活动搭建平台,由于历史原因,组件模块开发体验比较差。开发入门门槛以及对整个项目结构的理解成本比较高,同时整体的开发效率比较低。搭建工具的工作原理

文链接在语雀:https://www.yuque.com/wumingshi/rkh1qq/


内部工具的一次重构,记录下重构过程遇到的坑

背景

内部使用的活动搭建平台,由于历史原因,组件模块开发体验比较差。开发入门门槛以及对整个项目结构的理解成本比较高,同时整体的开发效率比较低。


搭建工具的工作原理比较常规,基于后台的配置文件,在渲染端(ssr)根据配置加载不同的组件,也就意味着组件的载入是一个异步的过程。


现状

活动工具的整体技术栈为:Regular.js + Node.js + SSR。


组件的目录结构:

image.png

开发组件跟着组件仓库,如上图中的只有packages内的内容是实际开发者需要关注的内容,其他的内容大部分都是和业务开发无关,开发工具通过Koa静态托管文件,本地起一个代理加载组件文件实现本地开发。

主要存在的问题:

  • 组件没办法和管理后台联动
  • 组件的容器非最新,线上线下显示不一致
  • 组件没有办法和其他组件共同联通,即多组件共同开发
  • 整体开发流程特别繁琐:npm link + npm run watch + npm run start。然后依然需要做各种 hack 工作
  • 开发工具的规范无法收敛
  • 项目结构混乱
  • ...


基于以上,最终是想通过借壳开发,保证线上线下无差别,并在开发过程中可以0感知把组件托管到本地。整体的工作思路比较简单,主要在于如何在历史深坑中,一个个去“补填”

重构后的架构

image.png


统一代理服务

本地启动一个代理服务,作为一个全局请求的统一入口,负责分发各个请求。

image.png

根据不同的类型,请求到不同的接口下。

本地组件静态服务

对于本地的组件,依赖webpack watch 打包出静态文件并监听,如有多个,则启动多个webpack watch进程;同时启动一个静态资源服务(port:8061)进行托管,

为什么选择webpack watch?

  1. 历史组件的构建方式都是webpack watch 可以比较好的兼容老的版本。
  2. 方便内容托管在同一端口下,方便多组件共同启动。

hot live 这里依赖webpack-plugin-serve

启动服务后,访问127.0.0.1:8001/activity

登录依赖第三方登录,活动工具后台的的服务端是一个node 服务,页面也是由服务端直出,登录的状态是依赖node-session通过第三方登录进行node登录。管理后台不是一个前后分离页面,访问该路由,直接重定向到管理后台,直出document,但是当前域名下并没有登录态。


而我们这里需要一个本地第三方登录。如何解决呢?

这里通过前端静态服务托管一个登陆服务页面(admin-login),通过第三方登录写入127.0.0.1 登录cookie,写入cookie后,重定向到node-server,通过重定向补齐session状态,完成 node 登录。

这里会有一个问题,即 node-server 未登录以及前端模拟登录完成重定向到node-server,都是未登录并返回302,那如何判断何时触发本地登录流程呢?

这里通过判断返回的 status code 为302,并重定向3次作为触发本地流程的起始条件

image.png

管理后台组件连接到本地开发环境

上文已经提到,本地组件已经被托管在8061端口下,那如何区分把本地的开发组件连接到真实环境中,组件的加载是一个异步过程,就是会单独通过 script 标签 加载组件的js/css。

在启动的时候,通过选择的开发组件,生成一个配置文件。通过此配置文件,对所有的组件资源进行筛选,如果是开发组件,则将资源重新链接到8061端口下的静态地址。这里并没有区分版本号,即只要本地有代理,则直接会覆盖线上的资源,从而达到本地调试的目的。

同理,对于启动开发的组件这里也需要动态插入到module list中,从而保证本地模块可以在页面编辑的时候被正确检索到。


用户端的组件连接到本地开发环境

活动工具搭建出的页面是通过ssr输出到用户。除了基本的容器及热区等,是通过ssr直出,而组件本身的内容其实是通过csr重新生成的。而组件的相关信息是通过直接注入到html中

<script>
 var __moduleJsUrl__ = ["/tms3/posterGenerate/posterGenerate/1.0.3/index.min.js"] 
 var __moduleCssUrl__ = ["/tms3/posterGenerate/posterGenerate/1.0.3/index.min.css"] 
</script>

容器的js会根据这个全局变量动态注入组件js。

那这里就是直接暴力拦截document内容,把其中的内容里追加本地调试的组件。


至此基本调试流程已完成。


新的组件项目的结构

image.png

项目中的包含的内容和开发高度相关,其他均收敛到一个脚手架中

// package.json

{
  "name": "xxx",
  "moduleType": "xxx",
  "title": "xxx",
  "version": "1.0.0",
  "icon": "th-large",
  "description": "",
  "base": "react",
  "tmsVersion": "3.0",
  "main": "src/main.js",
  "scripts": {
    "init": "tms3-cli init",
    "start": "tms3-cli watch",
    "build": "tms3-cli buildAll",
  },
  "keywords": [
    "activity",
    "tms3.0"
  ],
  "devDependencies": {
    "@music/tms3-cli": "x.x.x"
  },
  "dependencies": {
    ...
  }
}

对于组件本身的脚手架也有调整,主要是项目组织方式以及配置的优化,这里先跳过。


主要功能介绍:

tms3-cli init: 通过交互的方式生成组件的脚手架,组件的脚手架是包含完整的依赖,这里生成的时候回根据最外层的依赖,动态删除组件的依赖,一定程度提高开发及构建速度,防止包的冗余。毕竟一个项目的组件的数量可能达到几十个。

tms3-cli start:一键启动开发,启动各个服务

tms3-cli buildAll: 构建所有组件,这里增加了多进程构建,对于多组件的项目提升至少200%,

发布平台, process.NODE_ENV 默认为production,装依赖主要特别的把devDepencies装全。

tms3-cli us: 一键升级老的脚手架项目。

image.pngq


其他

  • 新版本检查

image.png

  • 组件脚手架及部分方法热更,在watch及init方法的前后会注入。用于在一些极端的情况做到及时触达,比如重要的通知,或者一些变更等。
  • 试水了wasm在node的运行,可以保存一些非明文的信息,对于这部分感兴趣的可以参考链接
  • 统计项目覆盖服务 based on gitlab api。


最后

本次重构是基于“历史包袱”,在不影响现有业务的开发前提下一次比较平滑的升级。值得肯定的是,没有耽误业务方的迭代,对于开发及构建有非常大的提升。




updatedupdated2021-01-212021-01-21