写点什么

指尖前端重构(React)技术分析报告

  • 2020-02-14
  • 本文字数:4875 字

    阅读完需:约 16 分钟

指尖前端重构(React)技术分析报告

1. 为什么选择 React


React 是当前前端应用最广泛的框架。三大 SPA 框架 Angular,React,Vue 比较,Angular 出现最早,但其在原理上并没有 React 创新的性能优化,且自身相对来说显得笨重。Vue 出现最晚,其核心原理学习了 React,只是语法形式的变化,关系上来说 React 是开拓者,Vue 是学习者。React 社区有强大活力与创新能力,不断涌现革命性的创新产品,其中包括可以使用 JS 操作原生控件的 React Native,Vue 后来跟进学习出了类似的 Weex,但两者成熟度差很多。目前来看 React 的生态系统要比 Vue 大的多,在 github, stackoverflow 等最大的技术社区搜索两者,React 的搜索结果是 Vue 的十倍左右,另外据近期统计使用 React 的站点是 Vue 的几百倍以上。更大的生态意味着更多可用的资源,以及遇到问题可以得到更多的有效参考与帮助,这也是除了性能之外选择 React 的核心原因。


选择 React 之后,应用会在以下几个方面有提升。第一,原先的 html 间跳转会有短暂的白屏现象,这一点在安卓性能较差的机器上尤为明显,而 React 作为单页应用没有这个问题。第二,React 提供的虚拟 DOM 包含 Diff 算法,即将原 dom copy 一份,与改动后的 dom 对比,只渲染不同的 dom 节点,实现最小代价渲染,vdom 创新的性能优化方式对性能的提升毋庸置疑。第三,React 中核心组件化技术,更加容易的绑定事件行为,动态更新特定的 dom,代码更加模块化,重用代码更容易,结构清晰易维护。


2. 在移动端使用 React


三大框架在移动端分别有自己的东西。Angular 的 ionic,React 的 React Native,Vue 的 Weex。其中 ionic 是基于 cordova 技术,依然是浏览器应用。而后两者已上升到操作原生控件的层面,做出来的是原生界面,其中 React Native 的成熟度远高于 Weex,已经被很多公司使用,而 Weex 使用者很少。


综合来看选择 React 生态明显最佳,由当前的 cordova 过渡为 cordova+Reactjs,然后可以平滑地过渡到 React Native,媲美原生性能的最优混合开发方式。之所以说平滑是因为 React Native 中近 90%的代码(JS)可以在 IOS 和 Android 端使用,剩余的涉及原生的代码也基本可以找到可用的资源,就像 cordova 的插件一样。毕竟如果需要同时掌握 JS, OC(或 swift),java(或 kotlin)才能开发 React Native 的话,那这门技术不会有人用;当然反过来如果有原生开发知识的话会对开发 React Native 有一定帮助。


直接转型为 React native 的话涉及了应用底层架构的变动,有比较大的跨度,而转为 cordova+Reactjs 相对容易,而由 cordova+Reactjs 到 React Native 同样容易不少,因为其中大部分 Reactjs 代码可以重用。


3. Reactjs 开发工具的选择


首先开发脚手架官方出了 Create-react-app,集成了 webpack-当前最流行的打包工具,babel-提高 js 版本兼容性的转码器,以及 ESLint-代码检测工具和其它一些常用工具,同时对这些工具进行了比较优的配置。值得一提的是该脚手架将这些工具的配置文件进行了隐藏,本意是让使用者专注于编码即可,但实际使用时通常会有自己配置的需求,此时执行 npm run eject 即可出现被隐藏配置文件。


React-router 是官方推荐的路由管理工具,由于是单页应用区别于原先的 html 界面间跳转,跳转实质是在组件间进行,所以需要有路由管理工具来统一化管理。这里值得一提的是,React-router 配合 webpack 可以实现代码的按需加载。一般来说,webpack 打包后会在生成一个压缩的 js 文件,在单页应用打开会整体加载这个文件,由于该 js 文件包含之前所有的 js 代码,虽然进行了压缩,一般仍至少有几百 kb,当应用稍微复杂点,打包后文件会相应变大。而加载的时候,不管那些代码有没有执行到,都会下载下来并进行加载,造成性能浪费,这一点在显然在 web 端很重要,而在 cordova 中是将 js 代码直接打包在本地,等于跳过了下载步骤但仍然会有加载过程。通过在 router 中写 require.ensure 代码并在 webpack 中相应地修改配置即可将 js 分成多个文件,在需要时加载对应的 js 文件,实现按需加载。


Redux 是应用最广泛的第三方状态管理工具,其作用是当应用中多数据状态交互时,可以更有方便且代码结构清晰地统一管理状态,下图给出了形象的阐释。由于在实际开发中一般是分人员/分功能模块独立开发,考虑引入 redux 的成本(redux 本身略复杂),可以在没有多数据交互的模块不使用 redux,而在类似涉及增删改查的表单以及即时通讯 websocket 等契合 redux 的模块使用。


1516331424059027809.png


为项目选取合适 UI 组件库,一定程度上简化 UI 样式的开发并且考虑使用其提供的过渡动画效果。这方面有比较多的选择,Google Material Design 风格的 Material-UI 在 github 上最受欢迎,但其设计语言与我们当前 APP 截然不同,腾讯的 weui 和阿里的 antd-mobile 较为相近,其中 antd-mobile 与 create-react-app 脚手架配合使用时配置项比较繁杂,因为阿里本意是用来配合自己的脚手架 dva(封装了 react-router 和 redux),因此暂时选择 weui,后期开发有特定组件需求可结合其他 ui 库使用。


至于页面跳转时的过渡动画,有些 UI 库给出了一些过渡样式,比如 touchstone。但该库已不再维护,文档不佳,且与新版本的 react-router 配合使用有不兼容情况。后来浏览官方文档发现官方有动画库 react-addons-css-transition-group,使用该库结合 css3 的动画三件套 animation,transition,transform 即可实现各种动画效果包括基本的过渡效果,比如渐进平移等。


另外关于 css,因为是单页应用,所以如果不加处理,直接 import css 文件的话最终打包生成一个 css 文件会导致样式应用到全局,造成同类名样式相互污染影响。解决这个问题有很多种方案。Facebook 积极探索 css in js 方式,但直接写内联样式代码可读性太差。目前解决方案中应用最广泛的是 css-modules,即在 webpack 配置中开启 module 选项,使用 styles 对象来写样式。解决的原理是将 css 类名在打包后编译成哈希字符串,保持其唯一性。但当想要使用全局样式时要再配置,稍显繁杂,且它类名编写的方式为对象的方式,需要整体修改,另外在使用它时,发现不支持-横线的类命名方式,支持下划线方式,推荐驼峰式,而我们之前 html 中的样式类名大多是横线命名,这意味着原 html 和 css 中的类名都要对应修改,考虑到样式类名非常多,这一方式舍弃。另外有基于 css-modules 使用高阶组件的 react-css-modules 使用人数也比较多,允许横线命名方式且全局本地样式区分简单,但有 benchmark 测试表明其会较大程度拖累性能,所以也舍弃。解决这个问题要最大程度兼容原先 css 的写法,即改动最小,因为之前的 css 类样式数量庞大。Webpack css-loader 有个属性 :local 加上之后类会变成局部作用域,即 webpack 会对该类型的类进行自动哈希转码处理,但显然类名一个个加:local 是有些呆板的工作,于是想到可以利用 scss 的嵌套属性将:local 在一个 css 文件中统一加到类名前。这里涉及到在脚手架 create-react-app 添加对 scss 的支持,在命令行执行安装,并在 package.json 的 scripts 中添加 watch-css 指令,将原 css 文件改为 scss 文件,然后在最外层添加:local,执行 watch-css 命令,即可在 scss 文件旁自动产生 css 文件,且类名前自动添加:local 前缀,这种方法实践中发现并非所有类的样式都与:local 兼容良好,相应的可以使用文件名代替:local,要做的就是保持文件名的唯一性,这一点原工程下的文件名已满足。这样原先文件中引入 css 的方式,全局 css 引入的方式都不需要变化,做到最小代价。scss 是 sass 3 引入新的语法,其语法完全兼容 css3,并且继承了 sass 的强大功能,sass 和 less 是前端扩充 css 常用的方式,添加了嵌套,变量,继承等语法,但需要编译成 css 来最终使用(稳定性考虑)。


4.Reactjs 和 cordova 结合有哪些需要注意的


开发 Reactjs 使用官方提供的脚手架 Create-react-app,最终通过 npm run build 生成一个单页网页应用,放入 cordova 的 www 目录下即可。由于这两部分开发时独立,而原先开发是在含 www 目录的 cordova 工程目录下直接开发,这种不同会产生一些问题。比如 cordova 中某些插件安装后 export 函数或者变量供引入使用,因为一开始是分离的,在 create-react-app 中并找不到这些变量,就造成在 build 的时候产生变量 undefined 的错误,尽管最终放到 cordova 工程中后可以找到变量并正常运行,但在第一步 react 开发时控制台报一堆 error 会妨碍调试,影响开发体验。在 github 上有一些 react cordova 库,但实质上它们都需要通过 npm run build 来打包,所以并没有解决引入插件变量的问题,且会与 create-react-app 有相斥的地方。所以要想办法使插件提供的变量在 React 中不报错,这里在不影响 ESLint 检错机制的情况下可以采取迂回的方式。Build 时控制台报错仅针对 src 文件夹下的代码,而在 public 文件夹下还有个 index.html 这个文件会最终被打包放到 www 目录下,因此可以在这个文件中 deviceready 时添加全局的插件变量(注意该类全局变量的唯一性,可以添加 plugin 前缀或使用命名空间等方式保证),并将值传给 src 目录下的代码中,这样即可绕过控制台 build 以及调试时的报错。


另外一个小技巧可以将 react 工程直接放在 cordova 工程目录下,指定最终 build 生成的文件放入 www 目录下,省掉手动转移文件的过程。


还有需要注意的一点是由于 React 中默认配置的公共路径是绝对路径,当放在 cordova 中时需要使用 file 协议放本地,需要在 webpack 的 production 配置的 public 路径前加".",或者在 package.json 文件增加一行"homepage": “…/www"或"homepage”: "."改为相对路径,否则会出现找不到文件的情况,这里推荐最后一种方式。


5. React 项目的目录结构


首先 IDE 选取 webstorm,功能强大,之前项目组在用可以沿用下来,但需要注意的一点是当目录中包含了安装的依赖 node_modules 时,由于该文件夹下文件数量非常多,webstorm 在智能建立代码关联时会占用大量资源,在某些电脑上会偶尔会出现卡死现象,这一现象在我配置比较高(固态硬盘加 8g 运存)的电脑上同样出现了,解决办法是在 file-setting-File types 中配置 ignore node_modules 文件夹。


1516331435896074726.png


上图是 create-react-app 项目的目录,主要代码放在 src 目录下。Components 中包含所有组件。React 严格地执行组件技术,组件化不仅方便重用,同样可以将一个页面清晰地分割为几个部分最后放入一个父组件展示,因为 jsx 技术将 js 和 html 放在了一起,分割后每个部分有自己的功能逻辑与页面展示,这样更加清晰易维护。事实上 react 提出了一切皆组件的思想,只是有的组件 render 了部分界面,而有的没有 render。上图中 components 下有 common 文件用来放项目成员自己写的公用组件比如公共请求方法等,external 放外部引入的组件,work_log 里放的是我写的工作日志模块的组件,各个功能模块都各自创建一个文件夹,命名规则统一使用下划线方式,这也是之前使用的方式。具体功能模块的划分与层级关系可以参考之前的,值得一提的,以前 html 的层级关系必须严格为两层(涉及到跳转路径的逻辑),导致最后出现没有把一个功能模块放到一个文件夹里的情况,比如上面的工作日志之前所包含的各个文件直接和其它的一些功能模块一起放到了 setting 文件夹内。而现在只要在 React-router 统一配置好路由,实质上是往某个组件跳转,不存在跳转路径的限制。


Constants 文件夹下存放各种常量,比如各种接口路径。Fonts 存放字体图标文件,images 存放图片,redux 文件夹下是 redux 的几个组成部分,styles 下放 scss/css 样式文件。Index.js 是入口也是最顶层的父组件,router.js 则维护了整个应用的路由关系。


上面就是本次调研的技术分析文档,浏览大量技术文档,开源社区以及技术论坛并结合实践摸索得出的选型思路和理由,可能依然会有一些点没有添加进去,以后会结合新知识和实践继续完善。


接下来抛开思路,给出具体配置方式和相关执行代码供开发人员参考。


本文转载自宜信技术学院网站。


原文链接:http://college.creditease.cn/detail/147


2020-02-14 18:481389

评论

发布
暂无评论
发现更多内容

浪潮 KaiwuDB x 大数据中心 | 数据驱动政府治理能力快速提升

KaiwuDB

KaiwuDB 大数据中心建设

直播回顾 | 一体化智能可观测平台如何保障电商节大促

博睿数据

可观测性 智能运维 博睿数据 618 电商行业

Java代码性能测试实战之ContiPerf

javalover123

单元测试 性能测试 压测 JUnit Java'

对线面试官-线程池(四)

派大星

Java 面试题

深度学习应用篇-自然语言处理-命名实体识别[9]:BiLSTM+CRF实现命名实体识别、实体、关系、属性抽取实战项目合集(含智能标注)

汀丶人工智能

人工智能 自然语言处理 深度学习 命名实体识别 6 月 优质更文活动

从分布式到微服务解密“架构”原理与实战笔记

小小怪下士

Java 程序员 分布式 微服务

3 个技巧,让你像技术专家一样解决编码问题

LigaAI

程序人生 技术专家 技术人成长 问题分析及解决 企业号 6 月 PK 榜

科兴未来|2023年扬中高层次人才创新创业大赛

科兴未来News

【零售电商系列】走进亚马逊之自建仓储&物流

小诚信驿站

6 月 优质更文活动

教培行业的“智能GPT私教”?WorkPlusAI助理帮助教培机构实现十倍人效!

BeeWorks

深度学习应用篇-自然语言处理[10]:N-Gram、SimCSE介绍,更多技术:数据增强、智能标注、多分类算法、文本信息抽取、多模态信息抽取、模型压缩算法等

汀丶人工智能

人工智能 自然语言处理 深度学习 命名实体识别 6 月 优质更文活动

通过技术变革,推动全面预算管理前行

智达方通

全面预算管理

赋能矿山 | KaiwuDB 智慧矿山解决方案

KaiwuDB

解决方案 智慧矿山 KaiwuDB

相约未名湖畔,百度商业AI技术创新大赛携手北大学子共探AI发展

百度Geek说

人工智能 百度 企业号 6 月 PK 榜

分享几款 Mac 上非常好用的的免费软件

搞大屏的小北

数据可视化 数据库工具 截图软件 视屏转 gif 视频号下载

“敏捷教练进阶课程”7月22-23日 ·A-CSM认证在线周末班【提前报名特惠】CST导师亲授

ShineScrum

敏捷教练

智慧生活垃圾焚烧发电厂Web3D可视化平台

2D3D前端可视化开发

物联网 数字孪生 三维可视化 工业组态 智慧垃圾焚烧发电厂

Win服务器图床配置

路北路陈

6 月 优质更文活动

HummerRisk获中国开源创新大赛优秀奖

HummerCloud

开源 云安全

千万级数据的可视化交互展示:Vue.js 技术解析

xfgg

Vue eCharts 6 月 优质更文活动

喜讯 | 华秋电子荣获证券时报年度高成长企业

华秋电子

数据分析:电子商务需要关注的重要指标有哪些?

搞大屏的小北

电子商务 销售指标

精耕丝路,智胜全球 | 新华三助力中企跑好“出海”赛道

新消费日报

Web网页端IM产品RainbowChat-Web的v5.0版已发布

JackJiang

网络编程 即时通讯 IM

NFTScan | 06.05~06.11 NFT 市场热点汇总

NFT Research

NFT 热点

平台即产品:数字化转型的全新驱动力

SEAL安全

平台工程 平台即产品

数据可视化设计四大原则透析

搞大屏的小北

数据可视化 设计要素 大屏设计

DevEco创建项目时的错误解决

路北路陈

6 月 优质更文活动

Java线程池三、调优和性能优化

echoes

Java 线程池

科兴未来|2023”福地句才”海外人才创业大赛

科兴未来News

“数字创新产品课程”7月29-30日 · CSPO认证周末班【提前报名特惠】CST导师亲授

ShineScrum

指尖前端重构(React)技术分析报告_文化 & 方法_梁鑫_InfoQ精选文章