指尖前端重构(React)技术调研分析
摘要:重构前的技术文档调研与分析,包括技术选型为什么选择react,应用过程中的注意事项等。
一、为什么选择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,代码更加模块化,重用代码更容易,结构清晰易维护。
二、在移动端使用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代码可以重用。
三、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的模块使用。
为项目选取合适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来最终使用(稳定性考虑)。
四、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": "."改为相对路径,否则会出现找不到文件的情况,这里推荐最后一种方式。
五、React项目的目录结构
首先IDE选取webstorm,功能强大,之前项目组在用可以沿用下来,但需要注意的一点是当目录中包含了安装的依赖node_modules时,由于该文件夹下文件数量非常多,webstorm在智能建立代码关联时会占用大量资源,在某些电脑上会偶尔会出现卡死现象,这一现象在我配置比较高(固态硬盘加8g运存)的电脑上同样出现了,解决办法是在file-setting-File types中配置ignore node_modules 文件夹。
上图是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则维护了整个应用的路由关系。
上面就是本次调研的技术分析文档,浏览大量技术文档,开源社区以及技术论坛并结合实践摸索得出的选型思路和理由,可能依然会有一些点没有添加进去,以后会结合新知识和实践继续完善。
作者:梁鑫
来源:宜信技术学院
指尖前端重构(React)技术调研分析的更多相关文章
- 微前端框架 qiankun 技术分析
我们在single-spa 技术分析 基本实现了一个微前端框架需要具备的各种功能,但是又实现的不够彻底,遗留了很多问题需要解决.虽然官方提供了很多样例和最佳实践,但是总显得过于单薄,总给人一种&quo ...
- 微前端框架 single-spa 技术分析
在理解微前端技术原理中我们介绍了微前端的概念和核心技术原理.本篇我们结合目前业内主流的微前端实现 single-spa 来说明在生产实践中是如何实现微前端的. single-spa 的文档略显凌乱,概 ...
- [目前最火的前端开发框架]React组件的应用分析
React组件 一.如何创建React组件 方式一:React.createClass 用 React.createClass 构建组件是 React 最传统.也是兼容最好的方法. const But ...
- 重谈react优势——react技术栈回顾
react刚刚推出的时候,讲react优势搜索结果是几十页. 现在,react已经慢慢退火,该用用react技术栈的已经使用上,填过多少坑,加过多少班,血泪控诉也不下千文. 今天,再谈一遍react优 ...
- 【高软作业2】:Java IDE调研分析
一 序言 随着软件项目开发需求的增多,拥有一款优秀的.顺手的IDE(Integrated Development Environment)对程序员来说显得格外重要.本文就Java程序开发,选择了3款I ...
- React技术实践(1)
随着系统越来越庞大,前端也变得越来越复杂,因此,构建一套组件化的前端变得很重要了. 之前一直在使用Asp.net来进行前端的组件化,Asp.net组件化有个很大的缺陷,就是和后台代码绑定太紧密了,不符 ...
- 产品前端重构(TypeScript、MVC框架设计)
最近两周完成了对公司某一产品的前端重构,本文记录重构的主要思路及相关的设计内容. 公司期望把某一管理类信息系统从项目代码中抽取.重构为一个可复用的产品.该系统的前端是基于 ExtJs 5 进行构造的, ...
- 网络统计学与web前端开发基础技术
网络统计学与web前端开发基础技术 学习web前端开发基础技术(网页设计)需要了解:HTML.CSS.JavaScript三种语言.下面我们就来了解一下这三门技术在网页设计中的用途: HTML是网页内 ...
- 前端基于react,后端基于.net core2.0的开发之路(1) 介绍
文章提纲目录 1.前端基于react,后端基于.net core2.0的开发之路(1) 介绍 2.前端基于react,后端基于.net core2.0的开发之路(2) 开发环境的配置,注意事项,后端数 ...
随机推荐
- Linux设备驱动程序学习----3.模块的编译和装载
模块的编译和装载 更多内容请参考Linux设备驱动程序学习----目录 1. 设置测试系统 第1步,要先从kernel.org的镜像网站上获取一个主线内核,并安装到自己的系统中,因为学习驱动程序的编写 ...
- java代码实现搜索elasticsearch索引数据
1.关于获取客户端以及增删改操作请看上一篇文章,文章中有详细的讲解 2.本篇文章讲述关于elasticsearch搜索匹配方式,主要有 match.match_phrase.term.regexp.w ...
- 设计模式(C#)——04原型模式
推荐阅读: 我的CSDN 我的博客园 QQ群:704621321 在软件开发过程中,我们习惯使用new来创建对象.但是当我们创建一个实例的过程很昂贵或者很复杂,并且需要创建多个这样的 ...
- JVM知识点总结
JVM总体梳理 一.jvm体系总体概览 JVM体系总体分四大块:类的加载机制.jvm内存结构.GC算法 垃圾回收.GC分析 命令调优 这里画了一个思维导图,将所有的知识点进行了陈列,因为图比较大可以点 ...
- MSIL实用指南-生成while语句
本篇讲解怎样生成while语句.while语句是编程语言中很重要的循环语句,它的结构是while(<表达式>) <语句或语句块> 当表达式的结果为true时就一直执行语句或语句 ...
- CodeForces 1018B The hat
The hat 题解: 定义d[i]为第i个数和他对面的差值. 然后我们可以发现d[i]和d[i+1]的差值只会有3种情况2, -2, 0. 并且可以知道 d[i] = - d[i+n/2] 所以如果 ...
- codeforces 830 B. Cards Sorting(线段树)
题目链接:http://codeforces.com/contest/830/problem/B 题解:其实这题就是求当前大小的数到下一个大小的数直接有多少个数,这时候可以利用数据结构来查询它们之间有 ...
- Codeforces Round #481 (Div. 3) C. Letters
题目地址:http://codeforces.com/contest/978/problem/C 题解:有n个宿舍,每个宿舍人不一样多,有m封信,每封信送给对应的第m间房间,问这封信是给第几个宿舍,第 ...
- adb命令介绍
1.adb logcat -v time -s ActivityManager:I 获取包名和activity 2. adb logcat "ActivityManager" |g ...
- Spring boot 自定义 Resolver 支持 interface 类型参数
在编写 RestController 层的代码时,由于数据实体类定义了接口及实现类,本着面向接口编程的原则,我使用了接口作为 RestController 方法的入参. 代码大致如下(省略具体业务部分 ...