Description
回顾
在上一篇易企秀H5项目重构总结 中, 笔者详细记录了重构项目的缘由, 技术选型及实践, 灰度及 bug 修复, 编辑器功能边界划分及模块化实践, code review 实践 及 总结.
距离上次总结已经过去了一年的时间, 在这段时期, 笔者又基于当初的项目架构, 横向扩展了 wap 编辑器和 混合模式编辑器, 其中 wap 编辑器在线上正常运营, 而混合模式则碰到了很多技术瓶颈, 虽达到测试上线标准, 但是最终夭折腹中, 没有正式上线; 除此之外, 我与明纯 共同重构了另外一项复杂业务: 组合, 图层和功能模板. 最近, 有关组合, 图层的设计和一些复杂的算法明纯会在他的博客分享, 敬请期待 :D
回过头看上一篇总结, 有些思想和方法是非常具有前瞻性的, 有些决定则看起来缺乏魄力, 显得略显保守. 接下来, 笔者将会就第一次重构进行复盘, 对目前项目的构建过程, 核心组件库, 编辑器架构等方面做最后一次易企秀 H5 项目的架构梳理.
第一次重构复盘
第一次重构的正确选择:
- 淘汰 grunt, 采用 gulp + webpack, 大大提高了构建速度
- 引入面向对象思想, 构建核心组件库, 至今组件库都是整个项目的基石. Core + 多编辑器实例构成了目前的多编辑器框架.
- 引入 ES6, 面向下一代语言标准
- 编辑器全指令+模块化开发
- 积极 code review
- 灰度方案
第一次重构时保守的选择:
- 没有一开始就拥抱模块化标准, 采用了挂载全局变量的方式
- 没有彻底的 OO 化, 对于触发, 动画, 事件系统等仍然采用面向过程式的编程
- 没有做好是否使用新框架的调研 保守的采用了当时的 ng1 + jquery 的方案
重新来过, 有哪些可以做的更好
- 明确目标, 拆分项目, 灰度方案, 技术选型, 重构和优化 应该分步走. 避免时间上无法量化的重构
- 数据结构的梳理和规范应该是重构的第一步
- (这一步居然是项目启动三年后才开始的... eqxiu-scene-data-spec)
- 数据规范后应该采用 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
- loaders
- 使用 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预览步骤
- 获取场景的基本信息(id, code...)
- 根据用户类型调整 API 域名
- 获取加载页的配置
- 获取用户微信里的信息
- 从缓存里取用户信息 如果有就直接用
- 如果没有 请求用户授权
- 获取场景列表的数据, 矫正数据 (adapter)
- 微信信息获取后 pv打点和微信组件设置
- 渲染场景
易企秀 JavaScript 风格指南
编辑器架构
参考 易企秀H5项目重构总结 编辑器功能边界划分及模块化实践, 核心思想并未发生变化, 摘录如下
编辑器理念
- 数据驱动
- 依赖组件库.
为了保证编辑器和预览时组件渲染一致, 编辑器将所有和渲染相关的逻辑全部交由组件库. - 全指令 + 模块化
笔者考虑到未来的团队合作, 希望尽早开始模块化的尝试, 参考了以下文章
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)+ 全指令的形式进行模块化的重构. - service 做到 简易统一的 API; 职责单一; 少依赖; 可复用
- 编辑区鼠标操作全部重写
经过项目拆分, 笔者划定了项目的整个边界
包括 模板, 素材, 页面管理, 编辑, 场景设置, 设计师功能等.
其中涉及到编辑组件的功能边界如下
后记
从2016年6月开始, 整个项目规模已经达到20w 行代码的规模, 作为易企秀的核心业务, 日 pv 稳定在1亿左右, 是个非常值得骄傲的成绩.
自2017年1月开始, 整个项目就按照当初设想的那样, core+多编辑器实例, 没有太大的变化, 至此笔者有些欣慰, 也有些忧伤.
欣慰的是一年多前的重构架构可以支撑后来一年的迭代, 说明笔者架构的整体思路没有太大问题. 忧伤的也正在此, 笔者知道, 这个架构还远远不够, 还有很多地方可以优化调整. 然而并没有很多大的改动.
当你看到这篇文章时, 笔者已经离开易企秀了, 希望后继者可以提出更加健壮的方案, 助力易企秀再上新台阶.
送给自己的话
在天地之间找一个自己的位置