从 1 到完美,用 js 和 react-native 写一个 APP

从 1 到完美,用 js 和 react-native 写一个 APP

facebook 在 2013 年开源了 react 后,紧接着在 2015 年就又开源了 react-native,就此打开了用 js 和前端技术写原生 android&ios APP 之路。尽管到目前为止 react-native 最新版本是 0.56.0,还没有发布正式 1.0 版,但使用 react-native 开发原生 APP 的技术已经比较成熟了,很多商业公司和商业软件都在用 react-native 做开发,比如 facebook, airbnb, uber, skype 等。

另外,除了 react 在做写原生 APP 的尝试之外,vue 也在尝试,详见 vue-native

1. 前言

  1. 开发时建议用 mac,因为 mac 上的 ios 模拟器能在开发时,快速的重载应用,而 android 就慢很多了
  2. 开发时建议用 yarn, 如果非要用 npm, 务必使用 npm < 5 版本,否则就可能遇到以下的问题(找不到 node_modules 下面的文件):
  • Cannot find entry file node_modules/react-native-scripts/build/bin/crna-entry.js
  • Unable to resolve "react-navigation" from "App.js"
  • expo xde 中: Metro Bundler failed to start. (code: EMFILE)
  • expo xde 中: Metro Bundler failed to start. (code: EAGAIN)

2. 实现原理

react-native 在 APP 内启动并维护了一个 js UI 进程(有可能还有 js background 进程),然后把 js UI 进程中的组件及其样式映射到 APP 的原生 UI 层,这样 js UI 进程中组件的更新就立刻反应到 APP UI 进程中,而其他逻辑和数据等的状态都维持在 js UI 进程中。这样便达到了用 js 和前端技术写原生 APP 的功能。

对应 web 来看,react-native 程序只有两个部分,stylejs,而 js 部分则分为组件和 api

|-- react-native
    |-- style 样式部分,对应 web 的 css 部分
    |-- js 部分
        |-- 组件 预定义基础容器
        |-- api 对原生接口的封装

2.1 style

react-nativestyle 用来描述组件的样式、布局等,用 js 书写。它借鉴了 css 的语法,但只支持部分的语法,并且书写方式和实现方式都有很大的不同:

  • 没有 class, id 等之类的 css 选择器
  • 没有 px, em 等之类的 css 尺寸单位
  • 属性名使用 HTML DOM Style 对象 的语法
  • 使用样式时只有类似于 css 的行内样式这样的写法

比如:

import React, { Component } from 'react';
import { StyleSheet, Text, View } from 'react-native';

export default class LotsOfStyles extends Component {
  render() {
    return (
      <View>
        <Text style={styles.red}>just red</Text>
        <Text style={styles.bigblue}>just bigblue</Text>
        <Text style={[styles.bigblue, styles.red]}>bigblue, then red</Text>
        <Text style={[styles.red, styles.bigblue]}>red, then bigblue</Text>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  bigblue: {
    color: 'blue',
    fontWeight: 'bold',
    fontSize: 30,
  },
  red: {
    color: 'red',
  },
});

详见 Style, StyleSheet, View Style Props, Text Style Props, Image Style Props

2.2 js

react-nativejswebjs 都是 javascript,这点没区别;但 react-nativejs 只是纯 js,并不运行在浏览器环境中,也就没有 DOM,一切与 DOM 相关的语法都不可用,如 window, document 等。所以,在 web 端的纯 js 库(无 DOM)在 react-native 中同样适用,如 redux, lodash, immutable-js 等。

react-nativejs 分为组件和接口。

组件是由 react-native 定义好的基础容器,就像 html 的标签一样,如 View, Text, Image, WebView 等。

接口是 react-native 封装好的原生 APP 的功能,如相机、存储、系统信息等。

3. 决定是否使用 react-native

尽管 react-native 提供了使用 js 和前端技术写原生 APP 的强大功能,但并不是说就可以用 react-native 代替 java, kotlinandroid APP、objective-c, swiftios APP 了,它只是提供了一个选择。

其实,从上面的实现原理中,基本上可以看出 react-native APP 是有很明显的劣势的:

  • 性能不及原生的 APP
  • 自由度也不及原来的 APP,因为被约束的 react-native 模式中
  • apk, ipa 文件变大了

react-native 也有很强大的优势:

  • 开发简单、快速,入门坎比较低
  • 跨平台,一套代码就可以在多个平台上运行

所以,一种不错的选择是:

  1. 如果追求完美性能和体验的 APP,用原生的方式(androi: java, kotlin, ios: objective-c, swift)开发
  2. 对性能和体验不敏感,但对人力成本敏感,并且需要快速开发的,用 react-native 开发
  3. 两者可以混合开发,对性能和体验敏感的用原生的方式开发,对人力成本和时间成本敏感的用 react-native 开发

4. 决定使用何种构建方式

目前 react-native APP 的构建方式有两种:

  1. 使用 Android Studio 或 Xcode 开发
  2. 使用 expo 方式开发

4.1 使用 Android Studio 或 Xcode 开发

这种方式是目前使用比较多的一种方式,不管是纯 react-native APP 还是混合型 APP(原生与 react-native 混合开发),都是适用的。

这种方式的好处是可以进行原生开发、自定义打包,但对大部分前端开发人员来说,这种方式对环境的要求比较高,需要 Android Studio 或 Xcode,并且配置复杂,入门坎很高。

初始化

# 安装 react-native-cli
npm install -g react-native-cli

# 新建项目
react-native init demo

# 切换到项目根目录
cd demo

开发

# 开启本地 `js` UI 进程服务(开发模式)
npm run start

# 运行 ios 程序
react-native run-ios

# 运行 android 程序
react-native run-android

打包 apk, ipa

# 打包 android APP 所需的 js bundle 文件
react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/res/ 

# 打包 apk
# 按照正常的 android 打包方式进行


# 打包 ios APP 所需的 js bundle 文件
react-native bundle --platform ios --dev false --entry-file index.js --bundle-output ios/bundle/index.ios.jsbundle --assets-dest ios/bundle

# 打包 ipa
# 按照正常的 ios 打包方式进行

4.2 使用 expo 方式开发

expo 是 facebook 与 expo 合作专门为 react-native 开发的一套工具,它让 react-native 开发从 Android Studio 和 Xcode 中解放出来,使开发者只关注 react-native 开发部分,而不理会复杂的原生开发。

这种方式是目前纯 react-native APP 开发的推荐方式。

这种方式的好处是不需要 Android Studio 或 Xcode(包括开发和打包),对环境的要求低,配置简单,入门坎低,但不能进行原生开发、自定义打包。

初始化

# 安装 create-react-native-app
npm install -g create-react-native-app

# 新建项目
create-react-native-app demo

# 切换到项目根目录
cd demo

或者

# 安装 expo
npm install -g expo-cli

# 新建项目
expo init

# 切换到项目根目录
cd demo

开发

# 运行 ios 程序
npm run ios

# 运行 android 程序
npm run android

或者

# 手机上安装 expo 客户端

# 开启本地 `js` UI 进程服务(开发模式)
expo start

# 运行 ios 程序
# 用 expo 客户端扫描二维码

# 运行 android 程序
# 用 expo 客户端扫描二维码

打包 apk, ipa

# 打包 apk
expo build:android

# 打包 ipa
expo build:ios

可能遇到的问题

  1. 如果构建出错,尝试删除项目根目录下的 .expo 文件夹之后,再试
  2. Packager is not running at ...: 尝试重新打开一个终端,并尝试删除项目根目录下的 .expo 文件夹之后,再试

5. 选择合适的组件库

6. 选择合适的模板

使用 react-native initcreate-react-native-app 初始化的项目,只是搭建好了基础的骨架,项目的其他部分需要开发者自己去搭建,如 storybook 组件预览、enzyme + jest 测试、eslint + prettier 代码矫正与优化等。

所以,选择一个合适的、已经搭建好大部分架子的模板就很受用了:

ignite 举例:

# 安装 ignite-cli
npm install -g ignite-cli

# 初始化项目
ignite new demo

# 切换目录
cd demo

# 现在就可以对项目进行操作了,如添加 screen,运行程序等

# 运行 storybook 组件预览
npm run storybook

# 开启本地 `js` UI 进程服务(开发模式)
npm run start

# android 打包
npm run android:build

# ios 打包需要用 Xcode

7. 开发应用

除了 stylecss 的区别和 jsDOM 外,其他与开发 web 项目一致。

8. 应用实例

diary 便是使用 expo 开发的一个日记 APP。

9. 后续

更多博客,查看 https://github.com/senntyou/blogs

作者:深予之 (@senntyou)

版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,928评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,192评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,468评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,186评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,295评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,374评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,403评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,186评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,610评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,906评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,075评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,755评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,393评论 3 320
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,079评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,313评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,934评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,963评论 2 351

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,928评论 25 707
  • 时光飞逝,如今我已经成为一名中学生。在这12年中,是母亲抚育我成长,与我在12年的点点滴滴中快乐生活。陪我...
    韩佳成2号阅读 243评论 1 1
  • 没等手机闹钟响,就醒了。从床头拿过手机一看,果然06:00。不知道从什么时候开始自己竟然已经不会懒床了,奇迹...
    枯柯阅读 215评论 0 0
  • 今天是周末,天气特别好,上午爷爷带你出去玩,妈妈便在家收拾家务,快到中午的时候,你玩回来了,满头的大汗,...
    梓浩妈妈阅读 200评论 0 0
  • 于12月8日上映的《鲨海》猫眼评分6.6分。这个分给这部电影一点都不冤枉。 就是作死姐妹花海底逃生的故事。 影片剧...
    腋毛妹妹阅读 1,320评论 0 2