React Native 项目运行在 Web 浏览器上面
React Native 的出现,让前端工程师拥有了使用 JavaScript 编写原生 APP 的能力。相比之前的 Web app 来说,对于性能和用户体验提升了非常多。
但是 React Native 的代码只兼容两个平台(iOS 和 Android),并没有兼容 Web 端访问。这里是因为 Facebook 开发人员认为 Web 端天生兼容性就巨麻烦,而且平台差异性是注定存在而且也要保留的,所以 React Native 的目标是 Learn once, write anywhere ,而不是 Write once, run anywhere 。
然而 Write once, run anywhere 又是一个刚需。从产品还是用户的角度试想一下,APP 的安装成本还是很高的,如何让用户马上体验到你产品的功能再决定是否要安装?此外,尤其是重要的产品,除了 APP 客户端之外,还要有一套兜底的 Web 端以便用户在某些特殊场景下使用。React Native 可以让你写一份代码跑在两个平台,但是你却还要再写一份 Web 的一模一样的应用。就显得十分蛋疼了。
于是 React web 就出现了。
React Web 介绍
简单的一句话描述 React Web 就是:它帮你把 React Native 的组件做了一个 Web 端的实现,并提供相关打包工具,让你可以直接打包出一份可以跑在 Web 端的代码。
将 React Native 应用创建一个 Web 版的几个步骤
为了重点突出转换过程,这里使用 React Native init 的最简 Demo 来做实验(名字叫 Awes 代码在 https://github.com/taobaofed/demo/tree/gh-pages/react-web )。 React Web 已经把 React Native 比较复杂的 UI Explorer Demo 跑起来了 ,所以只要你的代码能跑在 iOS 或者 Android 上面,你基本不用担心有什么组件上的问题。当然如果有,可以马上提 Issue 过来,我们有一个小组在支持 React web :)。
第一步:安装 React web 并进行相关配置
这一步操作主要是安装 react-web 包以及相关依赖,并配置 webpack 打包脚本等。
为了简化这一步操作,我们开发了命令行工具 react-web-cli 只需要执行两行命令即可。同时命令行工具还支持启动调试服务器、打包等功能,在后面介绍。
安装 cli 工具:
npm install react-web-cli -g
安装配置 React web 等:
react-web init <当前项目目录>
执行完成之后,会在你项目目录下面 npm install 相关库,并自动创建 web/webpack.config.js 文件,里面有一份写好的配置。此时目录结构为:
.
├── README.md
├── android/
├── index.android.js
├── index.ios.js
├── ios/
├── package.json
└── web/
└── webpack.config.js
第二步:添加入口文件并进行相关配置
每个项目都需要有一个入口文件,通常用来引入调用其他组件并初始化项目,比如 index.ios.js 表示 iOS 平台上的该项目的入口文件。为了符合 React Native 的文件命名规范,我们创建一个 index.web.js 作为入口文件,并且需要在 webpack 中指定该文件为入口文件。打开 web/webpack.config.js 文件,修改 config 变量:
var config = {
paths: {
src: path.join(ROOT_PATH, '.'),
index: path.join(ROOT_PATH, 'index.web'),
},
};
然后我们创建 index.web.js 文件。这个文件其实跟 index.ios.js 非常像,只是略有不同。主要区别在于:iOS 只需要 AppRegistry.registerComponent('Awes', () => Awes); 即可让 Xcode 的 Native 代码接收处理你的 JS 代码,而 Web 端是需要插入到 DOM 节点中才可以用。因此我们需要在 index.web.js 最下面添加如下代码:
AppRegistry.registerComponent('Awes', () => Awes);
if (Platform.OS == 'web') {
var app = document.createElement('div');
document.body.appendChild(app);
AppRegistry.runApplication('Awes', {
rootTag: app
});
}
然后在最上面 require 部分需要引入 Platform 组件。这样配置部分就已经处理完成了,执行 react-web start 命令即可启动调试服务器啦!
可以随便修改试下,跟 React Native 模拟器里面的体验几乎一样。
第三步:测试并打包 Web 版本代码
当你修改开发完,并对 Web 端也测试好了,就可以打包发布了。 react-web-cli 工具打包的命令是:
react-web bundle
打包完成后,文件会存放在 web/output/ 目录下面,可以直接打开 index.html (如果 app 有请求操作,需要起本地服务器查看),再检查一下就可以发布了。
这个过程中发生了什么?
好奇的同学看到这里可能会有一些疑问,上面命令行工具的一些命令做了什么事情?为什么 React web 将 React Native 代码打包出一份用在 Web 端的代码?React web 安全可靠吗,里面都是什么东西?
这里简单的介绍下 React web 的实现原理和上面步骤实际做的事情。
React Web 将 React Native 组件做了 Web 端的实现
React 将代码与平台环境分离,多了一层,这样开发者可以在平台环境层面做一些处理,使得同样一份代码适应更多的平台环境等。
- 比如 react-canvas 按照 React 的语法书写代码,在平台环境层面做一些处理(将你 React 代码运行并用 canvas 渲染),然后实现特定目标(在移动端提高性能)。
- React Native 中,一份代码能同时跑在 iOS 和 Android 上面,也是一样的道理。React Native 团队在对应平台的 Native app 上面做了一些处理,使其可以解析执行 React 语法的代码。
- 还有同构(isomorphic)的应用,服务器端使用 React + Node.js 生成 HTML,客户端使用 React 获取进行客户端相关交互和功能,也是一样的道理。
为此, React v0.14.x 版本开始,专门分成两个库 react 和 react-dom,其实是把对浏览器平台的特殊处理剥离了出来,单独变成了 react-dom 库。
React Native 比较特殊的地方在于,组件最底层的实现是 Native 的实现,所以就不支持 span 、 div 等标签。而动画等,也是直接调用 Native 进行界面渲染。所以不支持 Web 端,但是绝大部分组件,都是可以用 Web 技术进行模拟实现。动画可以用 CSS3 、基础元素可以用同等 HTML 标签模拟、布局以及兼容性问题可以用 CSS 来处理,所以 React web 只需要把 React Native 的组件用 Web 技术重新实现一遍,借助 React 这一层,即可实现一份代码运行在多个平台上面。
举一个非常简单的例子, Text 组件:
- React Native 的实现 是调用了很多 React Native 底层的代码实现的。
- 对于 Web 端,输出一行文本使用 <span> 标签即可,所以 React web 的实现 就直接搞一个 <span> 标签,绑一些事件什么的就 OK 了。
在 UI Explorer demo 中能跑起来的 React Native 组件,你都可以放心的用。
webpack 帮你切换打包目标
做出了兼容 Web 端的组件,那打包的时候岂不是要把所有要打包的组件中的 require('react-native') 全部更换成 require('react-web') ?不然怎么用的我的 Web 组件打包?
强大的 webpack 附带了 alias 配置项可以帮你解决这个问题:
resolve: {
alias: {
'react-native': 'react-web',
'ReactNativeART': 'react-art',
},
extensions: ['', '.js', '.jsx'],
},
这样在打包时,但凡 require('react-native') 的地方全都用 react-web 包替换,而 react-web 的 module.exports 与 react-native 的保持一致即可让代码不替换也可以工作。
此外配合插件还可以实现另外一种引入方法,请看下面。
通过 Haste 方法引入组件以提高性能
webpack 以及其他的支持 CommonJS 规范的打包工具,都会把文件中 require 的所有组件都打包在一起。对于 React Native 来说代码体积大小无关紧要,而在 Mobile web 来说,就要稍微重要一些了。特别是如果你的项目只需要 Text 组件,但由于 require('react-web') 结果把所有的组件全部打包进来了,就比较伤感。
基于 webpack 插件,还可以用另一种方式引入组件以解决这个问题,你可以叫它 Haste 方式。使用这种方式需要加载 webpack 插件 haste-resolver-webpack-plugin ,默认的 webpack 配置已经帮你加载好了,你可以直接在组件里面这样用:
var Text = require('ReactText');
而不是以前那样:
var {Text} = require('react-native');
这样 webpack 打包时,对于前者,只会把那一个组件内容打包进来,因此可以减小体积、提升性能。这是怎么实现的呢?
加载了插件的 webpack 打包时,会先扫描所有组件并读取组件头部 @providesModule 的信息(比如 Text 组件的信息 ),然后当其他文件中 require 了这个组件名称,就会自动定位到这个文件进行打包。同时还可以区分平台,即便是同一个名字,打包时会区分平台去打包对应的文件(根据 index.xxx.js 的命名规则确定文件)。
一些存在的问题
在 Web 端兼容性是个非常麻烦头疼的事情,React Web 已经尽力帮你抹平兼容性问题和代码差异,尽可能的让你减少改动就可以创建 Web 版本的应用。但受限于 Web 端的一些固有限制(比如请求跨域),不可避免的就会有一些需要你改代码的地方。
为此,可以通过 if (Platform.OS == 'web') 的方式判断目标平台,并针对性的做一些平台兼容性处理。同样的,也可以将 web 替换为 ios 或者 android 判断其他平台。
在 React web 官方文档上面已经列出来了一些平台差异问题 ,这里就不再赘述了。
链接:
三步将 React Native 项目运行在 Web 浏览器上面
三步将 React Native 项目运行在 Web 浏览器上面(原文)
使用 Babel + React + Webpack 搭建 Web 应用
React Native 项目运行在 Web 浏览器上面的更多相关文章
- [转] 三步将你的 React Native 项目运行在 Web 浏览器上面
React Native 的出现,让前端工程师拥有了使用 JavaScript 编写原生 APP 的能力.相比之前的 Web app 来说,对于性能和用户体验提升了非常多. 但是 React Nati ...
- 解决升级到Xcode10,react native项目运行报错问题
今天刚升级到Xcode10,就遇到两个报错问题 错误一:Xcode 10: Build input file double-conversion cannot be found error: Buil ...
- 技术实践丨React Native 项目 Web 端同构
摘要:尽管 React Native 已经进入开源的第 6 个年头,距离发布 1.0 版本依旧是遥遥无期."Learn once, write anywhere",完全不影响 Re ...
- 安装android Studio和运行react native项目(基础篇)
ANDROID_HOME环境变量 确保ANDROID_HOME环境变量正确地指向了你安装的Android SDK的路径. 打开控制面板 -> 系统和安全 -> 系统 -> 高级系统设 ...
- 【腾讯Bugly干货分享】React Native项目实战总结
本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/577e16a7640ad7b4682c64a7 “8小时内拼工作,8小时外拼成长 ...
- windows安装React Native开发运行环境
React Native是什么 React Native是facebook开源的一个用于开发app的框架.React Native的设计理念:既拥有Native (原生) 的用户体验.又保留React ...
- Expo大作战(三)--针对已经开发过react native项目开发人员有针对性的介绍了expo,expo的局限性,开发时项目选型注意点等
简要:本系列文章讲会对expo进行全面的介绍,本人从2017年6月份接触expo以来,对expo的研究断断续续,一路走来将近10个月,废话不多说,接下来你看到内容,讲全部来与官网 我猜去全部机翻+个人 ...
- React Native 项目整合 CodePush 全然指南
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/y4x5M0nivSrJaY3X92c/article/details/81976844 作者 | 钱 ...
- React Native移动开发实战-2-如何调试React Native项目
在实际开发中,还有一个影响开发效率的重要因素:调试. 在1.4.3节中已经介绍了Enable Live Debugger的使用.本节来介绍另一个非常重要的调试选项:Debug JSRemotely选项 ...
随机推荐
- iOS底层基础知识-文件目录结构
一:iOS沙盒知识 出于安全考虑,iOS系统把每个应用以及数据都放到一个沙盒(sandbox)里面,应用只能访问自己沙盒目录里面的文件.网络资源等(也有例外,比如系统通讯录.照相机.照片等能在用户授权 ...
- Binder中的asInterface解析
在使用AIDL通信的时候,在Stub类中都会生成一个asInterface函数,以<Android开发艺术探索>中的例子来分析,其生成的asInterface函数源码为: /** * Ca ...
- Android AsyncTask 源码解析
1. 官方介绍 public abstract class AsyncTask extends Object java.lang.Object ↳ android.os.AsyncTask&l ...
- 【代码笔记】iOS-手机验证码
一,效果图. 二,代码. RootViewController.h #import <UIKit/UIKit.h> @interface RootViewController : UIVi ...
- Caliburn.Micro 关闭父窗体打开子窗体
比如我们在做登录的时候需要关闭父窗体打开子窗体.使用Caliburn.Micro它的时候我们关闭登录窗口的时候主页面也会关闭. 解决方法就是在登录页面的CS里面写 IndexView iv = new ...
- file get contents 访问不了域名原因
file get contents('域名'); 居然不好用 后来发现 etc/hosts 127.0.0.1 www.baidu.com 这样的 #127.0.0.1 www.baidu.co ...
- vs 只能没有智能提示的解决方法
我vs今天出现一点比较诡异的情况,莫名奇妙就不能自动生成我拖的控件的后端代码了(****.aspx.designer.cs) 我在网上找了下,找到一个解决方法,这里把解决方法贴下来. 网上解决方法的出 ...
- 十大广泛使用的Linux发行版
回到上世纪90年代,Mandrake Linux还是唯一的Linux发行版:而今天,Linux发行版的数量变得数不胜数.本文为大家整理出了十大广泛使用的Linux发行版,希望能帮助大家在选择合适的Li ...
- 在VC环境下执行代码出现错误
这是在执行代码过程中出现的错误,源代码在别的电脑上能运行,在自己的VC里运行就出现错误,在网上也搜过解决办法,但还是有点不太理解,是编程环境的问题h还是代码本身也存在问题???
- 字节流InputStream/OutputStream
字节流InputStream/OutputStream 本篇将对JAVA I/O流中的字节流InputStream/OutputStream做个简单的概括: 总得来说,每个字节流类都有一个对应的用途, ...