一. 我们的要求

期望的要求

  1. 基于React语法,将RN项目转化为小程序项目

  2. 该小程序能同时在 微信小程序 和 支付宝小程序这两个平台运行

底线要求

底线是能转成微信小程序,因为目前来说,因为微信先发制人,再加上微信本身的用户黏性,导致在小程序这一块大多数其他平台都难以迎头赶上,包括支付宝小程序,百度小程序,头条小程序等等。

二. 目前可供选择的生态,以及各自存在的问题

  1. 能将已有RN项目转化为微信小程序的工具, 比如 Alita ,但它不能转成支付宝或其他小程序

  2. 从零开发的多端框架,比如Taro(京东),chameleon(滴滴), uni-app等等,问题在于:很多框架,比如uni-app,chameleon是基于Vue语法的,无法适用我们React项目的情况

  3. 专门设计的微信小程序框架(mpvue,webpy) ,问题也是和上面类似,Vue的语法,而且只是针对微信小程序的

三. 最终的工具选择:Alita && Taro

综合我们对React语法的要求,以及对平台转化的需求,最终觉得比较合适的有两个工具/框架,分别是Alita 和 Taro

Alita介绍

  • Alita介绍:它是京东的ARES多端技术团队,开发的React Native一键转化为微信小程序的工具。不过只能转成微信小程序,不能专成支付宝小程序

  • Alita的特性: Alita不是新的框架,也没有提出新的语法规则,她只做一件事,就是把你的React Native代码运行在微信小程序端。所以Alita的侵入性很低,选用与否,并不会对你的原有React Native开发方式造成太大影响。

Taro 介绍

  • Taro介绍:它是由京东凹凸实验室开发的多端框架

  • Taro的定位:它和Alita不同,不是既有项目的转化工具,而是从零开始开发的多端框架。

  • Taro特性:使用 Taro,我们可以只书写一套代码,再通过 Taro 的编译工具,将源代码分别编译出可以在不同端(微信/百度/支付宝/字节跳动/QQ小程序、快应用、H5、React-Native 等)运行的代码。

四. Alita && Taro 的调研总结

改造成本的对比

我们上面说了,Alita是将既有的React-Native项目转化为微信小程序框架的工具,那么它是不是轻轻松松就能实现一键转化呢? 其实不是的,Alita也要求你要完全遵循它的语法规则才能转化成功,否则那个文件将不会转化,这就需要对原有项目进行改造了
Taro自然也是这样了,因为它本身就是一套多端框架,也需要修改成它的代码规范才能运行

综合对比

五. 采用 Alita 方案的改造思路

Alita可以通过运行下面命令的方式基于已有的RN项目生成一个新的小程序项目
  1. alita -i rnProject -o wxProject
不过问题在于,必须要修改代码以符合Alita的转化条件(一开始想着能一键转化,空手套小程序的我还是太单纯了。。)

问题复现: 如果不对原有代码改造就转化会怎样?

1.根据官方案例提供的example,原本目录c下有一个文件:index.js,正确打包后如下图所示
 
2.我这里写入一个Alita禁止的写法: 使用as关键字
  1. // 修改前的 good style
  2. import React, {Component } from 'react';
  3. // 修改后的 bad style
  4. import React, {Component as BadComponent} from 'react';
  5. export default class C extends BadComponent {
  6.  
  7. }
原本打包后c目录下原本有文件的,现在啥都没有了
 
 
3.也就是说项目中一定不能有上面所讲的Alita禁止的写法,必须要进行转化
 

借助eslint排查和修改不符合alita风格的代码

首先我们要把Alita提供的eslint插件导入项目,把不符合Alita要求的代码风格改掉,我们来看下eslint有哪些规则
 

Alita转化前代码风格修改流程

注意一个问题:并不是所有有问题的代码风格alita的eslint插件都会做提示,实际上,它只会对80%的有问题的代码报出警告,所以有部分代码风格我们是要手动发现和修改的。所以我把问题分成了三类,分别按三种方式处理

A类问题

这些不符合eslint的代码是会有警告的

解决办法:逐个文件过一遍,把警告消除就好
  • 高阶组件限制,也就是路由深度不大于5层

  • 动画组件要使用alita的

  • 静态限制

  • global变量不允许使用

  • 一个文件最多只能定义一个组件

  • React Native基本组件不支持属性展开

  • this.props.xxComponent 要写完全

  • 使用高阶组件

B类问题

这些问题,eslint插件没有提示,同时根据我们的使用习惯,有可能会这样用的代码风格

解决办法:下面的大多数问题,都可以通过搜索的方式,找出问题并解决
备注:下面的“(数字)”在 参考资料中找到对应的条目,查看细节解释
  • 路由组件需要用@areslabs/router

  • ref 必须是方法,不支持字符串

  • 不支持 onLayout 方法

  • 代码体积限制:压缩的代码小于 4M,分包 8M,大于的话就不行

  • 函数组件在定义时候没有同时导出

C类问题

这些约束,eslint插件没有提示,但是我们一般都不会这么写,除非作死

解决办法: 发现有问题再来排查
备注:下面的“(数字)”在 参考资料中找到对应的条目,查看细节解释
  • for循环中返回组件,key不指定

  • 作为props的组件进行多层级传递

  • 从外部引用JSX片段

alita自身也在不断改进它的转化限制

六. 采用 Taro 方案的改造思路

问题列表(Problem)

Taro其实也有一个叫eslint-config-taro 的eslint插件帮助检查各种不符合Taro要求的代码风格,总结如下

改造难度从上往下递减,上面难,下面简单

  • P1. Animation, 原生平台组件和第三方组件Taro是不支持的,需要寻找方法规避转化问题

  • P2. 设计稿的单位,尺寸匹配问题等问题需要修改解决的思路

  • P3. RN用的样式编码方式和引用方式需要修改

  • P4. 路由系统要修改为Taro自带的路由系统 和 API

  • P5. 网络请求要修改,fetch/Ajax 等原生的要改成Taro的Taro.request这一API

  • P6. 引用图片、音频、字体等文件的方式要改

  • P7. 部分RN样式属性值Taro是没有的,而且部分样式属性的默认值RN和Taro不一致

  • P8.因为小程序的特殊需求,导致部分代码不符合Taro的编码规范,总结如下

  • P9. aync/await的使用要通过导入taro的包来开启

  • P10.redux的使用改为 @tarojs/redux

解决思路

P1. Animation, 原生平台组件和涉及前两者的第三方组件,这三者Taro是不支持的,需要寻找方法规避转化问题
解决思路
  • 如果是小范围的改动,可以通过平台变量process.env.TARO_ENV去规避(值有 weapp/alipay/h5/rn)

  • 如果是大范围的改动,可以通过脚本后缀名差异的方式区分小程序和RN平台(xxx.weapp.js和xxx.js)

P2. 设计稿的单位,尺寸匹配问题等问题需要修改解决的思路
  • 设计稿的单位要修改, Taro似乎不支持纯数字的长度,所以要改成rem或者Px

  • 设计稿尺寸匹配问题,Taro默认是根据750的设计稿匹配的,可以在配置文件的designWidth属性中进行修改

  • 如果是行内长度样式,那么要做手动转换:Taro.pxTransform(10)

P3. RN用的样式编码方式和引用方式需要修改
  • RN是通过向style中导入对象的方式引入样式,而Taro是通过className结合import样式文件的方式引入样式

  • RN的属性命名方法是驼峰,而Taro是短横线

react-native的样式编码方式

  1. class App extends React.Component {
  2. render () {
  3. return ()
  4. }
  5. }
  6.  
  7. const styles = StyleSheet.create({
  8. container: {
  9. flex: 1,
  10. backgroundColor: '#000',
  11. opacity: 0.6
  12. }
  13. })

Taro的样式编码方式(类似传统的CSS编码方式)

  1. // index.js
  2. import "index.css"
  3. class App extends React.Component {
  4. render () {
  5. return ()
  6. }
  7. }
  8. // index.css
  9. .bar {
  10. height: 10Px;
  11. background-color:'10px'
  12. }

P4.路由系统要修改为Taro自带的路由系统 和 API

比我们可能会选择react-navigation模块作为我们的导航工具,而我们需要改造成Taro自带的
  1. import Taro from '@tarojs/taro'
  2. Taro.navigateTo(params).then(...)

P5. 网络请求要修改,fetch/Ajax 等原生的要改成Taro的Taro.request这一API

  1. import Taro from '@tarojs/taro'
  2.  
  3. Taro.request({
  4. url: 'http://localhost:8080/test',
  5. data: { foo: 'foo' },
  6. header: { 'content-type': 'application/json' }
  7. }).then(
  8. res => console.log(res.data)
  9. )
P6. 引用图片、音频、字体等文件的方式要改 
  • RN用的是<Image source={...} />和<ImageBackground source />

  • Taro用的是<Image src={...} />

  1. // 引用文件
  2. import namedPng from '../../images/path/named.png'
  3. // 使用
  4. <View>
  5. <Image src={namedPng} />
  6. </View>

P7. 部分RN样式属性值Taro是没有的,而且部分样式属性的默认值RN和Taro不一致

  • 部分属性值存在差异,例如marginVertical,paddingVertical等等,RN有,但是Taro没有

  • 部分属性的默认值存在区别,在RN中,flexDirection默认是column,而在其他的平台中,flexDirection默认是row

P8.因为小程序的特殊需求,导致部分代码不符合Taro的编码规范,总结如下
因为这些坑很少会主动踩到,除非作死
(1)事件参数(props)都要以on开头
  1. // 错误
  2. const element = <View bindtap={this.onTag} />
  3. // 正确
  4. const element = <View onClick={this.onTag} />

(2)不能对this.props.children做任何操作

  1. // 错误的两种写法
  2. this.props.children && this.props.children
  3. this.props.children[0]

(3)不能使用 Array#map 之外的方法操作 JSX 数组

  1. // 错误,JSX数组不能用非Map方法,普通数组才可以
  2. const components = [<Component />...];
  3. components.find(component => {
  4. return component === <View />
  5. })

P9. aync/await的使用要通过导入taro的包来开启

很简单,不用考虑工作量
  1. import '@tarojs/async-await'
  2. // 下面就可以正常使用async/await了
P10.redux的使用改为 @tarojs/redux
API似乎没有变?应该是无需担心了

参考资料

  1. Alita官网 https://github.com/areslabs/alita
  2. Taro官网 https://taro.aotu.io/

React-Native转小程序调研报告:Taro & Alita的更多相关文章

  1. react与微信小程序

    由组员完成 原文链接 都说react和微信小程序很像,但是像在什么部分呢,待我稍作对比. 生命周期 1.React React的生命周期在16版本以前与之后发生了重大变化,原因在于引入的React F ...

  2. 微信小程序调研

    小程序入口 微信发现,小程序 公众号主体查看小程序 好友分享,群分享 公众号自定义菜单跳转 APP页面跳转 第三方服务 附近的小程序 扫普通链接二维码打开小程序 需要后台开启功能,开启后,用户在微信& ...

  3. React Native工作小技巧及填坑记录

    以下是本人在React Native开发工作中使用的一些小技巧,记录一下. 1.从网络上拉取下来的React Native缺少React和React Native库. 终端 1. cd 项目根目录 2 ...

  4. 3个微信小程序体验报告

    1.小程序摩拜单车.腾讯视频.JD的体报告 2.小程序的入口存在不公平 3.小程序2.0会怎么样?WSO浅谈 KEVIN常用的APP是以摩拜单车与JD商城和大众点评等,那么今天也就通过这上个进行对比 ...

  5. 去除富文本中的html标签及vue、react、微信小程序中的过滤器

    在获取富文本后,又只要显示部分内容,需要去除富文本标签,然后再截取其中一部分内容:然后就是过滤器,在微信小程序中使用还是挺多次的,在vue及react中也遇到过 1.富文本去除html标签 去除htm ...

  6. 微信小程序插件组件-Taro UI

    微信小程序组件使用以下官网查看 ↓  ↓  ↓ https://taro-ui.jd.com/#/docs/fab

  7. 2018年1月12日--微信小程序----出错报告(40kb的原因)---并解决方法

    一. 报错的原因是因为,图片的文件太大了,已经超过了40kb...不能超过40kb. 在这里查看图片文件的大小:

  8. Native VS React Native VS 微信小程序

    随着React Native和 微信小程序的出现,Native一家独大的局面出现裂痕,很多小公司使用已经正在着手微信小程序和React Native了,我公司就已经走上React Native之路.那 ...

  9. 微信小程序踩坑集合

    1:官方工具:https://mp.weixin.qq.com/debug/w ... tml?t=1476434678461 2:简易教程:https://mp.weixin.qq.com/debu ...

随机推荐

  1. scrapy框架来爬取壁纸网站并将图片下载到本地文件中

    首先需要确定要爬取的内容,所以第一步就应该是要确定要爬的字段: 首先去items中确定要爬的内容 class MeizhuoItem(scrapy.Item): # define the fields ...

  2. java.nio.ByteBuffer中的flip()、rewind()、compact()等方法的使用和区别

    java.nio.ByteBuffer 1. ByteBuffer中的参数position.limit.capacity.mark含义: position:表示当前指针的位置(下一个要操作的数据元素的 ...

  3. HTML5-常用正则表达式

    有关H5正则表达式的一些常用式子,希望热爱编程的同学们多多指教,还有也希望可以关注收藏本站哦!❤^_^❤ 一.校验数字的表达式 1. 数字:^[0-9]*$ 2. n位的数字:^\d{n}$ 3. 至 ...

  4. 基于Docker搭建大数据集群(二)基础组件配置

    主要内容 jdk环境搭建 scala环境搭建 zookeeper部署 mysql部署 前提 docker容器之间能免密钥登录 yum源更换为阿里源 安装包 微云分享 | tar包目录下 JDK 1.8 ...

  5. ZK 网络故障应对法

    网络故障可以说是分布式系统天生的宿敌.如果永远不发生网络故障,我们实际上可以设计出高可用强一致的分布式系统.可惜的是不发生网络故障的分布式环境还不存在,ZK 使用过程中也需要小心的应付网络故障. 让我 ...

  6. Spring Data JPA 梳理 - JPA与“Spring、Spring Data JPA”的关系

    JPA其实也就是java实体对象和关系型数据库建立起映射关系,通过面向对象编程的思想操作关系型数据库的规范. Spring 框架对 JPA 提供的支持主要体现在如下几个方面: 首先,它使得 JPA 配 ...

  7. docker 运行容器时指定--sysctl参数来设置系统参数

    指定--sysctl参数来设置系统参数,通过这些参数来调整系统性能,Docker通过一个 ValidateSysctl函数来限制 sysctl参数可以传入的项,源码如下: // docker/opts ...

  8. 什么是Affordance?

    什么是Affordance? 在人机交互领域中,我们常常提到某个设计的affordance.其中文对应的意思并没有一个统一的意见.Wikipedia2上先这个词被译为“承担特质”或者“环境赋使”(非常 ...

  9. Spark 学习笔记之 优雅地关闭Spark Streaming

    优雅地关闭Spark Streaming: 当touch stop文件后,程序仍然会再执行一次,执行完成后退出.

  10. 利用Dockerfile部署SpringBoot项目

    利用Dockerfile部署SpringBoot项目 1.创建一个SpringBooot项目并且打成jar包 2.在Linux中创建一个文件夹,来做docker测试 [root@izwz90lvzs7 ...