2019 农历新年即将到来,是时候总结一下团队过去一年的技术沉淀。过去一年我们支撑的数据相关业务突飞猛进,其中两个核心平台级产品代码量分别达到30+万行和80+万行,TS 模块数均超过1000个,协同开发人员增加到20+人。由于历史原因,开发框架同时基于 React 和 Angular,考虑到产品的复杂性、人员的短缺和技术背景各异,我们尝试了各种方法打磨工具体系来提升开发效率,以下是节选的5项主要方法。

一、基于 Redux 的状态管理

从2013年React发布至今已近6个年头,前端框架逐渐形成 React/Vue/Angular 三足鼎立之势。几年前还在争论单向绑定和双向绑定孰优孰劣,现在三大框架已经不约而同选择单向绑定,双向绑定沦为单纯的语法糖。框架间的差异越来越小,加上 Ant-Design/Fusion-Design/NG-ZORRO/ElementUI 组件库的成熟,选择任一你熟悉的框架都能高效完成业务。

那接下来核心问题是什么?我们认为是 状态管理。简单应用使用组件内 State 方便快捷,但随着应用复杂度上升,会发现数据散落在不同的组件,组件通信会变得异常复杂。我们先后尝试过原生 Redux、分形 Fractal 的思路、自研类 Mobx 框架、Angular Service,最终认为 Redux 依旧是复杂应用数据流处理最佳选项之一。

庆幸的是除了 React 社区,Vue 社区有类似的 Vuex,Angular 社区有 NgRx 也提供了几乎同样的能力,甚至 NgRx 还可以无缝使用 redux-devtools 来调试状态变化。

无论如何优化,始终要遵循 Redux 三原则:

原则 方法 引发的问题 Single source of truth 组件 Stateless,数据来源于 Store 如何组织 Store? State is read-only 只能通过触发 action 来改变 State action 数量膨胀,大量样板代码 Changes are made with pure functions Reducer 是纯函数 副作用如何处理,大量样板代码 这三个问题我们是通过自研 iron-redux 库来解决,以下是背后的思考:

如何组织 Action?

  1. action type 需要全局惟一,因此我们给 action type 添加了 prefix,其实就是 namespace 的概念
  2. 为了追求体验,请求(Fetch)场景需要处理 3 种状态,对应 LOADING/SUCCESS/ERROR 这 3 个action,我们通过 FetchTypes 类型来自动生成对应到 3 个 action

如何组织 Store/Reducer?

  1. reducer 和 view 不必一一对应,应用中同时存在组件树和状态树,按照各自需要去组织,通过 connect 来绑定状态树的一个或多个分支到组件树
  2. 通过构造一些预设数据类型来减少样板代码。对于 Fetch 返回的数据我们定义了 AsyncTuple 这种类型,减少了样板代码
  3. 明确的组织结构,第1层是 ROOT,第2层是各个页面,第3层是页面内的卡片,第4层是卡片的数据,这样划分最深处基本不会超过5层

最终我们得到如下扁平的状态树。虽庞大但有序,你可以快速而明确的访问任何数据。

[Redux 状态树]如何减少样板代码? 使用原生 Redux,一个常见的请求处理如下。非常冗余,这是 Redux 被很多人诟病的原因。

const initialState = { loading = true, error = false, data = []};function todoApp(state = initialState, action) { switch (action.type) { case DATA_LOADING: return { ...state, loading: true, error: false } case DATA_SUCCESS: return { ...state, loading: false, data: action.payload } case DATA_ERROR: return { ...state, loading: false, error: true } default: return state }}

使用 iron-redux 后:

class InitialState { data = new AsyncTuple(true);}function reducer(state = new InitialState(), action) { switch (action.type) { /** 省略其它 action 处理 */ default: return AsyncTuple.handleAll(prefix, state, action); }}

代码量减少三分之二!!

主要做了这2点:

  1. 引入了预设的 AsyncTuple 类型,就是 {data: [], loading: boolean, error: boolean} 这样的数据结构;
  2. 使用 AsyncTuple.handleAll 处理 LOADING/SUCCESS/ERROR 这 3 种 action,handleAll 的代码很简单,使用 if 判断 action.type 的后缀即可,源码在这里。

曾经 React 和 Angular 是两个很难调和的框架,开发中浪费了我们大量的人力。通过使用轻量级的 iron-redux,完全遵循 Redux 核心原则下,我们内部 实现了除组件层以外几乎所有代码的复用。开发规范、工具库达成一致,开发人员能够无缝切换,框架差异带来的额外成本降到很低

二、全面拥抱 TypeScript

TypeScript 目前可谓大红大紫,根据 2018 stateofjs,超过 50% 的使用率以及 90% 的满意度,甚至连 Jest 也正在从 Flow 切换到 TS。如果你还没有使用,可以考虑切换,绝对能给项目带来很大提升。过去一年,我们从部分使用 TS 变为全面切换到 TS,包括我们自己开发的工具库等。

TS 最大的优势是它提供了强大的静态分析能力,结合 TSLint 能对代码做到更加严格的检查约束。传统的 EcmaScript 由于没有静态类型,即使有了 ESLint 也只能做到很基本的检查,一些 typo 问题可能线上出了 Bug 后才被发现。

下图是一个前端应用常见的4层架构。 代码和工具全面拥抱 TS 后,实现了从后端 API 接口到 View 组件的全链路静态分析,具有了完善的代码提示和校验能力。

[前后端协作简图]除了上面讲的 iron-redux,我们还引入 Pont 实现前端取数,它可以自动把后端 API 映射到前端可调用的请求方法。

Pont 实现原理:(法语:桥) 是我们研发的前端取数层框架。对接的后端 API 使用 Java Swagger,Swagger 能提供所有 API 的元信息,包括请求和响应的类型格式。Pont 解析 API 元信息生成 TS 的取数函数,这些取数函数类型完美,并挂载到 API 模块下。最终代码中取数效果是这样的:

Pont 实现的效果有:

  1. 根据方法名自动匹配 url、method,并且对应到 prams、response 类型完美,并能自动提示
  2. 后端 API 接口变更后,前端相关联的请求会自动报错,再也不担心后端悄悄改接口前端不知晓
  3. 再也不需要前后端接口约定文档,使用代码保证前端取数和后端接口定义完全一致

另外 iron-redux 能接收到 Pont 接口响应数据格式,并推导出整个 Redux 状态树的静态类型定义,Store 中的数据完美的类型提示。效果如下:

最终 TS 让代码更加健壮,尤其是对于大型项目,编译通过几乎就代表运行正常,也给重构增加了很多信心

三、回归 Sass/Less

2015 年我们就开始实践 CSS Modules,包括后来的 styled-components 等,到 2019 年 css-in-js 方案依旧争论不休,虽然它确实解决了一些 CSS 语言天生的问题,但同时增加了不少成本,新手不够友好、全局样式覆盖成本高涨、伪类处理复杂、与AntD等组件库结合有坑。与此同时 Sass/Less 社区也在飞速发展,尤其是 Stylelint 的成熟,可以通过技术约束的手段来避免 CSS 的 Bad Parts。

  1. 全局污染:约定每个样式文件只能有一个顶级类,如 .home-page{ .top-nav {/**/}, .main-content{ /**/ } }。如果有多个顶级类,可以使用 Stylelint rule 检测并给出警告。
  2. 依赖管理不彻底。借助 webpack 的 css-loader,已够用。
  3. JS 和 CSS 变量共享。关于 JS 和 Sass/Less 变量共享,我们摸索出了自己的解法:
// src/styles/variables.jsmodule.exports = { // 主颜色 'primary-color': '#0C4CFF', // 出错颜色 'error-color': '#F15533', // 成功颜色 'success-color': '#35B34A',};// webpack.config.jsconst styleVariables = require('src/styles/variables');// ... { test: /.scss$/, use: [ 'style-loader', 'css-loader?sourceMap&minimize', { loader: 'sass-loader', options: { data: Object.keys(styleVariables) .map(key => `$${key}: ${styleVariables[key]};`) .join(''), sourceMap: true, sourceMapContents: true } } ] }//...

在 scss 文件中,可以直接引用变量

// page.scss.button { background: $primary-color;}

四、开发工具覆盖全链路

2019 年,你几乎不可能再开发出 React/Angular/Vue 级别的框架,也没必要再造 Ant-Design/Fusion-Design/Ng-Zorro 这样的轮子。难道就没有机会了吗?

当然有,结合你自身的产品开发流程,依旧有很多机会。下面是常规项目的开发流程图,任何一个环节只要深挖,都有提升空间。如果你能通过工具减少一个或多个环节,带来的价值更大。

单拿其中的【开发】环节展开,就有很多可扩展的场景:

  1. 一个有代表性的例子是,我们开发了国际化工具 kiwi。它同样具有 TS 的类型完美,非常强大的文案提示,另外还有:VS Code 插件 kiwi linter,自动对中文文案标红,如果已有翻译文案能自动完成替换
  2. Shell 命令全量检查出没有翻译的文案,批量提交给翻译人员
  3. Codemod 脚本自动实现旧的国际化方案向 Kiwi 迁移,成本极低

除了以上三点,未来还计划开发浏览器插件来检查漏翻文案,利用 Husky 在 git 提交前对漏翻文案自动做机器翻译等等。

未来如果你只提供一个代码库,那它的价值会非常局限。你可以参照上面的图表,开发相应的扩展来丰富生态。如果你是新手,推荐学习下编译原理和对应的扩展开发规范。

五、严格彻底的 Code Review

过去的一年,我们一共进行了 1200+ 多次 Code Review(CR),很多同事从刚开始不好意思提 MR 到后来追着别人 Review,CR 成为每个人的习惯。通过 CR 让项目中任何一行代码都至少被两人触达过,减少了绝大多数的低级错误,提升了代码质量,这也是帮助新人成长最快的方式之一。

【其中一个项目MR截图】Code Review 的几个技巧:

  1. No magic
  2. Explicit not implicit
  3. 覆盖度比深度重要,覆盖度追求100%
  4. 频率比仪式感重要,坐公交蹲厕所打开手机都可以 Review 别人代码,不需要专门组织会议
  5. 粒度要尽可能小,一个组件一个方法均可,可以结合 Git Flow
  6. 24h 小时内处理,无问题直接 merge,有问题一定要留 comment,并且提供 action
  7. 对于亟待上线来不及 Review 的代码,可以先合并上线,上线后再补充 Review
  8. 需要自上而下的推动,具有完善的规范,同时定期总结 Review 经验来丰富开发规范
  9. CR 并不只是为了找错,看到好的代码,不要吝啬你的赞美
  10. 本质是鼓励开发者间更多的沟通,互相学习,营造技术文化氛围

总结

以上5点当然不是我们技术的全部。除此之外我们还实践了移动端开发、可视化图表/WebGL、Web Worker、GraphQL、性能优化等等,但这些还停留在术的层面,未来到一定程度会拿出来分享。

如果你也准备或正在开发复杂的前端应用,同时团队人员多样技术背景各异,可以参考以上5点,使用 Redux 实现规范清晰可预测的状态管理,深耕 TypeScript 来提升代码健壮性和可维护性,借助各种 Lint 工具回归简单方便的 CSS,不断打磨自己的开发工具来保证开发规范高效,并严格彻底实行 Code Review 促进人的交流和提升。

作者:前端新能源

链接:https://juejin.im/post/5c617c576fb9a049e93d33a4

鼎信诺审计前端取数工具_给2019前端的5个建议相关推荐

  1. 鼎信诺oracle取数步骤,鼎信诺审计软件常见问题

    (1)在前端取数文件夹sjinputv3.2下找到相应类型的Excel手工取数模板文件,复制并保存至自己知道的一个目录下,然后在复制出的文件中进行编辑. 文件名分别如下: 序号 文 件 名 应用范围 ...

  2. 鼎信诺虚拟服务器导数,鼎信诺审计前端取数讲解.ppt

    鼎信诺审计前端取数讲解.ppt 鼎信诺审计前端取数 财务软件介绍 财务软件本身不存储任何财务数据财务软件存取在后台数据库中财务软件只是告诉用户在什么模块做什么操作 在财务软件凭证录入模块输入凭证信息 ...

  3. 鼎信诺服务器取数不显示账套,鼎信诺审计前端取数

    <鼎信诺审计前端取数>由会员分享,可在线阅读,更多相关<鼎信诺审计前端取数(15页珍藏版)>请在人人文库网上搜索. 1.精品 料推荐鼎信诺审计前端取数一.财务软件介绍财务软件本 ...

  4. 鼎信诺服务器取数不显示账套,鼎信诺审计前端取数.doc

    文档介绍: 鼎信诺审计前端取数 财务软件介绍 ●财务软件本身不存储任何财务数据; ●财务软件数据存取在后台数据库中; ●财务软件只是告诉用户在什么模块做什么操作. ●常见的财务软件数据库 鼎信诺数据采 ...

  5. 鼎信诺oracle_鼎信诺审计系统操作说明

    目 录 取数概述 . ......................................................................................... ...

  6. 10鼎信诺为什么安装不了_鼎信诺审计软件一周常见问题(4.134.17)

    今天介绍一下近期咨询较多的两款财务软件在取数后不能显示辅助核算明细的问题,分别是诺诺云和亿企代账,这两款软件都是采用云记账方式,均可以通过其平台中的导出审计数据的功能导出一个备份文件夹,备份文件夹中都 ...

  7. 鼎信诺oracle_鼎信诺,oracle数据库还原操作详解.ppt

    DMP数据还原 1.dmp还原完毕后,会有提示:成功终止导入,没有出现警告.此时我们便把NC.dmp这个数据还原到了本机orcl数据库中 DMP数据还原 1.接着打开审计前端取数工具 2.在软件列表中 ...

  8. win10鼎信诺为什么安装不了_2016年鼎信诺常见问题处理

    以下内容为鼎信诺审计软件使用常见问题归纳.鼎信诺 6118 和 鼎信诺 6508 在下文统称鼎信诺 6000 系列. 一.打开底稿报表没有数据 / 没有合计数 1. 随便打开一张底稿先确定 Excel ...

  9. win10鼎信诺为什么安装不了_win10 企业版系统 office2007办公软件 鼎信诺数据导不出来 为什么呢|鼎信诺如何导出excle底稿...

    鼎信诺5000 打开未申报表这一步,excel所有公式都是#NAME #NAME是公式里面的函数不认识,或者名称未定义,请你粘贴公式具体内容,大家可以帮你看看是属于2016版新增加公式呢,还是加载宏里 ...

最新文章

  1. python http接口_python实现http接口测试
  2. ThreadPool基础之RegisterWaitForSingleObject
  3. C++ const char* 学习
  4. mactex中文配置
  5. 图片在线转换base64
  6. 驾乘华为云 成就 AI 开发者的不凡
  7. 20220227:力扣第282场周赛(上)
  8. 数据科学家应该掌握的12种机器学习算法(附信息图)
  9. iOS维码的生成和扫描
  10. Appium下载和安装
  11. 筱筱看博客(uni-app、mumu模拟器、真机测试)
  12. 将android手机屏幕投影到电脑端
  13. 像素、分辨率、尺寸概念与关系
  14. SpringBoot:EasyExcel动态字段(不创建对象)多sheet、多文件|压缩包格式导出
  15. 鸿蒙操作系统细节曝光,华为鸿蒙系统曝光细节,不像安卓也不像iOS,确认是华为自研!...
  16. 一次哔哩哔哩面试经历,看这一篇就够了!
  17. python语言的特点-Python语言的特点有哪些?
  18. python+selenium提取数据
  19. OpenStack Victoria版——6.2计算节点-Nova计算服务组件
  20. 安霸S2L交叉编译环境搭建

热门文章

  1. python建立py文件夹过程_Pycharm创建python文件自动添加日期作者等信息(步骤详解)...
  2. 三张表有重复字段_什么?搞不定Kafka重复消费?
  3. Spring MVC源码——Root WebApplicationContext
  4. tp框架中引入php文件,Laravel框架及ThinkPHP框架超级简单的公共文件引入(保留变量)...
  5. 弱电工程集成商_弱电工程楼宇自控系统基础知识培训资料
  6. LDAP命令介绍---dstune
  7. Nginx(四):负载均衡Load balancing
  8. javascript编译压缩
  9. HTML meta使用
  10. mall整合SpringBoot+MyBatis搭建基本骨架