三端开发调研之 Taro
Taro https://github.com/NervJS/taro 是由凹凸实验室打造的一套遵循 React 语法规范的多端统一开发框架.
使用 Taro, 我们可以只书写一套代码, 再通过 Taro 的编译工具, 将源代码分别编译出可以在不同端 (微信小程序, H5,App 端等) 运行的代码. 实现 一次编写, 多端运行.
和 JDreact 的关系
Taro 是基于 Nerv.JS 搞的. Nerv 是在 2017 年初就已经开发了的基于 virutal-dom 的 web 框架, 没有依赖任何第三方库.
解决的痛点
主要是将解决怎么将同一套 Web 端代码适配日益兴起的各种小程序的问题
支持端
H5, 微信小程序, 百度智能小程序, 支付宝小程序 -------- 这些功能适配的很好
App 端(基于 Expo)[个人感觉不是很好用, 有点坑] -------- 有局限, Expo 的局限就是 Taro
上线项目示例:
现代前端开发流程
和微信自带的小程序框架不一样, Taro 积极拥抱社区现有的现代开发流程, 包括但不限于:
NPM 包管理系统
ES6+ 语法
自由的资源引用
CSS 预处理器和后处理器(SCSS,Less,PostCSS)
对于微信小程序的编译流程, Taro 从 Parcel https://parceljs.org/ 得到灵感, 自研了一套打包机制将 AST 不断传递, 因此代码分析的速度得到了很大的提高, 并且保证一键傻瓜式命令编译, 不增加入门或者学习门槛.
和 React 完全一致的 API 和组件化系统
在 Taro 中, 你不用像小程序一样区分什么是 App 组件, 什么是 Page 组件, 什么是 Component 组件, Taro 全都是 Component 组件, 并且和 React 的生命周期完全一致. 可以说, 一旦你掌握了 React, 那就几乎掌握了 Taro. 而学习 React 的资源也几乎是汗牛充栋, 完全不用担心学不会.
Taro 和 React 一样, 同样使用声明式的 JSX 语法. 相比起字符串的模板语法, JSX 在处理精细复杂需求的时候会更得心应手.
- // 一个典型的 Taro 组件
- import Taro, { Component } from '@tarojs/taro'
- import { View, Button } from '@tarojs/components'
- export default class Home extends Component {
- constructor (props) {
- super(props)
- this.state = {
- title: '首页',
- list: [1, 2, 3]
- }
- }
- componentWillMount () {}
- componentDidMount () {}
- componentWillUpdate (nextProps, nextState) {}
- componentDidUpdate (prevProps, prevState) {}
- shouldComponentUpdate (nextProps, nextState) {
- return true
- }
- add = (e) => {
- // dosth
- }
- render () {
- const { list, title } = this.state
- return (
- <View className='index'>
- <View className='title'>{title}</View>
- <View className='content'>
- {list.map(item => {
- return (
- <View className='item'>{item}</View>
- )
- })}
- <Button className='add' onClick={this.add}>添加</Button>
- </View>
- </View>
- )
- }
- }
看代码我们可以看出, Taro 基于 Nerv, 同时结合微信小程序, React Native 的优点, 并且结合 react-h5 的代码编写优势, 让我们在基本上不改变编写习惯的同时, 顺便过渡到 Taro 上面来, 摒弃了 react native 里面编写样式那种变态且又臃肿的代码编写方式<没有完全解决, 没有完全解决, 没有完全解决!!!>
Taro 的 H5 端对于 react.JS 的优势
Taro 对于 H5 端的优势, 不仅仅有一套代码可以编译成其他端的天然开发优势外, 还有 NervJS 的优势, 主要有:
性能对比:
更多信息: https://nerv.aotu.io
Nerv 产生的原因:
日常开发中, 相对于 vue , 我们更倾向于选择 React 模式作为我们的开发标准, 因为 React 天生组件化且函数式编程的方式, 更加灵活且便于维护. 然而, React 仍然有一些不能满足我们需求的地方:
IE8 浏览器兼容性: 当前环境所限, 即便很不情愿, 我们仍然要支持 IE8.
体积: React 大概 130kb 的体积. 在低网速 / 低版本浏览器 / 低配置设备的加载速度和解析速度都不能让我们满意.
性能: React 的 Virtual Dom 算法 (React 自己叫 Reconciler) 并没有做太多的优化.
而我们的新轮子 -- Nerv, 它完全能提供上述 React 的所有优点, 并且它也能完全满足我们自己的需求: 更好的兼容性, 更小的体积, 更高的性能.
NPM install nervjs --save
从 react 迁移到 Nerv
Nerv 提供了比 React 更好的浏览器兼容性和更高的性能, 与此同时也不会放弃 React 庞大的生态系统. 兼容 React 生态系统是开发 Nerv 的重要目标之一.
在 webpack 中只需要在 alias 把 nervjs 和 react,react-dom 关联起来即可:
- {
- resolve: {
- alias: {
- 'react': 'nervjs',
- 'react-dom': 'nervjs'
- }
- }
- }
其他类工具可以参考: 官网
Taro 的设计思路
做一款能够适配多端的解决方案, 结合业务场景, 技术选型和前端历史发展进程, 我们的解决方案必须满足下述要求:
代码多端复用, 不仅能运行在时下最热门的 H5, 微信小程序, React Native, 对其他可能会流行的端也留有余地和可能性.
完善和强大的组件化机制, 这是开发复杂应用的基石.
与目前团队技术栈有机结合, 有效提高效率.
学习成本足够低
背后的生态强大
同时满足这几个需求并不容易, 在我们经过充分地调研和思考之后发现只有 React 体系能够满足我们的需求. 而对于微信小程序而言, 使用 React 完全没有办法进行开发 -- 直到我们从 https://github.com/facebook/codemod 得到灵感:
也就是说, 对于微信小程序这样不开放不开源的端, 我们可以先把 React 代码分析成一颗抽象语法树, 根据这颗树生成小程序支持的模板代码, 再做一个小程序运行时框架处理事件和生命周期与小程序框架兼容, 然后把业务代码跑在运行时框架就完成了小程序端的适配.
对于 React 已经支持的端, 例如 Web,React Native 甚至未来的 React VR, 我们只要包一层组件库再做些许样式支持即可. 鉴于时下小程序的热度和我们团队本身的业务侧重程度, 组件库的 API 是以小程序为标准, 其他端的组件库的 API 都会和小程序端的组件保持一致.
解释如下:
意思就是: 用户根据基本上和 react 一样的语法, 同时结合 Taro 自己的一套组件, 像正常编写 Web 一样去开发, 最终根据用户输入命令, 命令通过 Taro 转化器, 将组件转化为相应平台的组件, 语法还是遵循 react 语法.
Taro 组件有以下[可以在 node_modules 里 @tarojs/components 完全找到]:
共 27 个, 对比与 react native, 增加了一些 Web 熟悉并常用的组件
转 App
Taro 转 App 主要还是基于 react native, 并且结合神器 Expo, 转化为可以在 App 中正常运行的项目
什么是 Expo???
Expo 是一组工具, 库和服务, 可以通过编写 JavaScript 来构建本地的 iOS 和 Android 应用程序.
Expo Apps 是包含了 Expo SDK 的 react native Apps,SDK 是一个 native-and-JS 的库, 它包提供对设备系统的访问功能, 像照相机, 联系人, 本地存储和其他硬件). 这意味着你不需要使用 Xcode 或 Android 的环境, 或写任何代码也使得你的 pure-JS 项目非常便携, 因为它可以运行在任何自然环境包含 Expo SDK.
Expo 还提供 UI 组件来处理各种应用程序, 几乎所有应用程序都将被覆盖, 但它不会突破 react native Core 的核心代码, 例如图标, 模糊视图, 等等.
最后, Expo SDK 提供了访问服务, 这些服务虽然很难管理, 但几乎每个应用程序都需要它. 其中最受欢迎的是: Expo 可以为您管理您的资产, 它可以为您处理推送通知, 并且它可以构建准备部署到应用程序商店的本地二进制文件.
说了这么多, 什么意思啊???
就是咱们平时开发, 虽然写了一套代码, 但是环境还是要单独配置的, 也就是说即使你用 Mac 开发, 用 react native 开发 App 的话, Xcode 和安卓环境还是要配置的, 毕竟 App 的运行和打包都是需要这样的环境的, 但是有了 Expo 就不用了, 他有自己的 SDK, 开发者不用关心是什么系统了, 但是唯一的要求就是你用的是什么版本的 React Native, 就要安装对应版本的 Expo SDK[Expo 针对不同的 react native 版本开发不同版本对应的 SDK]
说了这么多, 其实开发者要干嘛呢, 怎么才能运行一个 Taro 项目呢, 总结一下啊:
Taro 建项目 - 跑命令 taro build --type rn -watch - 出现上图 - 确保在和电脑统一域下用安卓或者 iOS 手机中的 Expo App 扫上图码
不过我试了一下, 还有其他方法, 就是直接打开模拟器, 并在模拟器中安装还 Expo 的 App, 并且打开, 这时候直接跑命令即可, 整个过程还算顺利, 不过想打开 Expo 这个 App, 还是有点门槛的, 就是你得首先注册个账号并登陆, 不过人家目的是为了更好的为你服务. 传送 -> https://expo.io/tools#client
贴一下网页端图片和 App 图:
左侧是网页端, 右侧是安卓模拟器中, 可以看出来, 基本上是 OK 的, 但是由于不同环境的 App 端和 H5 端还是有一写小差别呢, 不过覆盖一下默认样式还是可以解决的, 实在解决不了的, 只能用下面这种方法了:
ENV_TYPE.WEAPP 微信小程序环境
ENV_TYPE.SWAN 百度小程序环境
ENV_TYPE.ALIPAY 支付宝小程序环境
ENV_TYPE.TT 字节跳动小程序环境
ENV_TYPE.Web Web(H5)环境
ENV_TYPE.RN ReactNative 环境
总结
整体上上手还是较顺手的, 基于 https://github.com/facebook/codemod 的灵感, 同时整合一些比较优秀的第三方库, 实现了一套代码, 经过编译, 多端运行的目标, 也遇到一些坑, 比如缺少 webpack-runner https://www.jianshu.com/p/5e4ad6ee06fd , 我试了一下缺的还蛮多, 并且需要到 node_modules 下的 @Taro 文件夹下手动一个一个安装, 不过还是能慢慢解决的, 算是一个解决三端问题比较好的一个解决方案.
来源: https://juejin.im/post/5c80716b6fb9a049ec6bd955