Skip to content

易企秀H5项目架构梳理 #13

Open
@xiaoyu2er

Description

@xiaoyu2er

回顾

在上一篇易企秀H5项目重构总结 中, 笔者详细记录了重构项目的缘由, 技术选型及实践, 灰度及 bug 修复, 编辑器功能边界划分及模块化实践, code review 实践 及 总结.

距离上次总结已经过去了一年的时间, 在这段时期, 笔者又基于当初的项目架构, 横向扩展了 wap 编辑器和 混合模式编辑器, 其中 wap 编辑器在线上正常运营, 而混合模式则碰到了很多技术瓶颈, 虽达到测试上线标准, 但是最终夭折腹中, 没有正式上线; 除此之外, 我与明纯 共同重构了另外一项复杂业务: 组合, 图层和功能模板. 最近, 有关组合, 图层的设计和一些复杂的算法明纯会在他的博客分享, 敬请期待 :D

8661515316159_ pic_hd
上图为 wap 编辑器

group3
上图是组合的操作

回过头看上一篇总结, 有些思想和方法是非常具有前瞻性的, 有些决定则看起来缺乏魄力, 显得略显保守. 接下来, 笔者将会就第一次重构进行复盘, 对目前项目的构建过程, 核心组件库, 编辑器架构等方面做最后一次易企秀 H5 项目的架构梳理.

第一次重构复盘

第一次重构的正确选择:

  • 淘汰 grunt, 采用 gulp + webpack, 大大提高了构建速度
  • 引入面向对象思想, 构建核心组件库, 至今组件库都是整个项目的基石. Core + 多编辑器实例构成了目前的多编辑器框架.
  • 引入 ES6, 面向下一代语言标准
  • 编辑器全指令+模块化开发
  • 积极 code review
  • 灰度方案

第一次重构时保守的选择:

  • 没有一开始就拥抱模块化标准, 采用了挂载全局变量的方式
  • 没有彻底的 OO 化, 对于触发, 动画, 事件系统等仍然采用面向过程式的编程
  • 没有做好是否使用新框架的调研 保守的采用了当时的 ng1 + jquery 的方案

重新来过, 有哪些可以做的更好

  • 明确目标, 拆分项目, 灰度方案, 技术选型, 重构和优化 应该分步走. 避免时间上无法量化的重构
  • 数据结构的梳理和规范应该是重构的第一步
  • 数据规范后应该采用 typescript 来开发项目, 从而规范和提升开发效率
  • 做好是否使用新框架的调研 或许一开始采用 vue 或者 react 可以解决现数据流动和 dom 操作的诸多问题
  • 积极做项目的抽象
    • 抽象出样式库 (避免后续的黑白模式修改起来费劲)
    • 抽象出基础组件库
  • 坚持 code review

架构梳理

构建方案

  • H5编辑器: webpack
  • H5预览: gulp + webpack

编辑器构建方案

所有编辑器都是相对独立的单页 app, 使用 webpack 进行构建

  • util.js 提供了对本地构建的版本号 (格式: ${git-commit-hash}_${time})
  • webpack.helper.js 提供 webpack 公共的构建逻辑, 其中使用了
    • loaders
      • file-loader 处理静态文件
      • html-loader 处理 html 文件的压缩
      • scss-loader, less-loader, css-loader 处理样式文件
      • babel-loader, awesome-typescript 处理 ts 文件
      • ng-annote-loder, babel-loader 处理 js 文件, ng-annote 处理 ng 的依赖注入
    • plugins
      • CleanWebpackPlugin 清理构建文件
      • WebpackZipPlugin 生成 zip 打包文件
      • ExtractTextPlugin 内联 CSS 抽出文件
      • UglifyJsPlugin 压缩 js 文件
      • HtmlWebpackPlugin 根据模板生成 index.html
  • 使用 webpack-dev-server 进行热更新构建
  • webpack.config.js 通过 yargs.argv 判断构建的编辑器入口, 调用 webpack.helper.js 构建

H5 预览构建方案

H5 浏览项目构建流程相对复杂, 采取 webpack 处理程序逻辑打包 + gulp 处理流程 的方式 进行构建

  • 使用 webpack.view.js 打包所有资源
  • 使用 gulpfile 处理其余流程
    • build:inject index.html 注入静态资源链接
    • index:ftl, index:mobile, 根据 index.html 生成后端模板和移动端模板
    • css:http 移动端模板中对 css 中的资源文件, 需要把相对路径转变成绝对路径
    • check 检查生成的资源是否完整
    • zip-all, zip-ftl 打包静态资源

项目梳理

  • core: 核心组件库
  • view: H5 预览
  • editor: H5 编辑器
  • wapEditor: wap 编辑器
  • metaEditor: 标签编辑器
  • appEditor: 混合模式编辑器

目录结构梳理

顶级目录
├── README.md 项目说明
├── build 构建目录
├── docs 文档目录
├── env 环境目录
├── eqxiu.json 自动化部署配置
├── gulpfile.view.js H5预览 gulp 配置
├── node_modules
├── package.json
├── src 源文件目录
├── tsconfig.json typescript 配置
├── types
├── util.js 构建工具的 util
├── webpack.config.js webpack
├── webpack.helper.js 公共 webpack 配置
├── webpack.view.js H5 预览 webpack 配置
源码目录 
src
├── appWpEditor app 混合模式
├── common js common
├── core 核心组件库
├── editor 编辑器
├── metaWpEditor 贺卡编辑器
├── ngcommon ng common
├── view H5 view
└── wpeditor wap 编辑器

Core 核心组件库

核心组件库维护了所有易企秀H5的所有核心组件及其内在逻辑

核心类及继承关系

  • EqxScene 场景
  • EqxPage 页面
    • EqxLongPage 长页面
    • ...
  • EqxLayer 图层
  • EqxPageEffect 页面特效
    • FingerEffect 指纹特效
    • ...
  • EqxItem 组件基类
    • EqxGroup 组合
    • EqxComp 组件
      • EqxText
      • EqxImage
      • ...
      • EqxForm
        • EqxCheckbox
        • EqxRadio
        • EqxDropDownList
        • EqxInput
          • ....
      • wx 微信组件
        • EqxWxImage
      • ...

辅助类

  • ProgressBar 进度条
  • EqxArrow 翻页箭头
  • ...
  • EqxPageScroll
    • 策略模式
    • book, card, cube, fadeIn, fall, flip, horizontal, horizontalinertia, horizontalPush, horizontalSingle, scale, swap, vertiaclinertia, vertical, verticalPush, verticalSingle
  • 工厂
    • PageFactory 页面工厂
    • CompMap 组件工厂
    • PageEffectLoader 特效异步加载工厂
  • manager
    • EqxCommentManager 评论管理
    • EqxFormManager 表单管理
    • EqxSoundManager 音效管理
    • EqxStatManager 统计数据管理
    • EqxScreenManager 幕管理
    • EqxGroupManager 组合管理
    • EqxFtManager 功能模板管理
      • EqxFtRule 功能模板规则
      • EqxFtTerm 功能模板条款
      • EqxFtEditPropManager 功能模板组件可编辑元素管理

H5 预览流程梳理

view预览步骤

  1. 获取场景的基本信息(id, code...)
  2. 根据用户类型调整 API 域名
  3. 获取加载页的配置
  4. 获取用户微信里的信息
  • 从缓存里取用户信息 如果有就直接用
  • 如果没有 请求用户授权
  1. 获取场景列表的数据, 矫正数据 (adapter)
  2. 微信信息获取后 pv打点和微信组件设置
  3. 渲染场景

易企秀 JavaScript 风格指南

编辑器架构

参考 易企秀H5项目重构总结 编辑器功能边界划分及模块化实践, 核心思想并未发生变化, 摘录如下

编辑器理念

  1. 数据驱动
  2. 依赖组件库.
    为了保证编辑器和预览时组件渲染一致, 编辑器将所有和渲染相关的逻辑全部交由组件库.
  3. 全指令 + 模块化
    笔者考虑到未来的团队合作, 希望尽早开始模块化的尝试, 参考了以下文章
    Angular 1.x和ES6的结合 xufei/blog#29 Angular 1.x和ES6的结合
    Angular1.x + ES6 开发风格指南 kuitos/kuitos.github.io#34 Angular1.x + ES6
    笔者决定, 升级 ng1.2 至 1.5. 整个项目采用 ES6 + (webpack + gulp)+ 全指令的形式进行模块化的重构.
  4. service 做到 简易统一的 API; 职责单一; 少依赖; 可复用
  5. 编辑区鼠标操作全部重写

经过项目拆分, 笔者划定了项目的整个边界
包括 模板, 素材, 页面管理, 编辑, 场景设置, 设计师功能等.
其中涉及到编辑组件的功能边界如下
image

编辑器基本框架如下
image

编辑区基本框架如下
qq20170116-3

一个典型的模块及子模块(样式编辑-触发)的代码组织如下
qq20170116-4

后记

从2016年6月开始, 整个项目规模已经达到20w 行代码的规模, 作为易企秀的核心业务, 日 pv 稳定在1亿左右, 是个非常值得骄傲的成绩.

自2017年1月开始, 整个项目就按照当初设想的那样, core+多编辑器实例, 没有太大的变化, 至此笔者有些欣慰, 也有些忧伤.

欣慰的是一年多前的重构架构可以支撑后来一年的迭代, 说明笔者架构的整体思路没有太大问题. 忧伤的也正在此, 笔者知道, 这个架构还远远不够, 还有很多地方可以优化调整. 然而并没有很多大的改动.

当你看到这篇文章时, 笔者已经离开易企秀了, 希望后继者可以提出更加健壮的方案, 助力易企秀再上新台阶.

送给自己的话

在天地之间找一个自己的位置

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions