一、前言
离了大谱啊,家人们!产品叫我把一个h5的网站打包到app里面去,离线加载。
我:不能直接把h5部署到服务器上去,然后通过域名访问吗?(不管三七二十一,先驳回)
产品:小老弟哇,用你的脚趾头头想想这样能够离线访问吗?
我:哦.哦…好像是不可以(看似唯唯诺诺,实则内心mmp)
二、webview
在react-native新版本里面,webview放到社区维护去了,所以先安装依赖
yarn add react-native-webview
一般来说使用webview加载html有这么几种方式:
- 使用require加载
const html = require('public/webview.html');
const Demo=()=>{
<WebView
originWhitelist={['*']}
scalesPageToFit={false}
useWebKit={true}
javaScriptEnabled
source={html}/>
}
- 加载一个html字符串
const html=`
<html>
<head></head>
<body>
<script>
setTimeout(function () {
window.ReactNativeWebView.postMessage("Hello!")
}, 2000)
</script>
</body>
</html>
`
const Demo=()=>{
<WebView
originWhitelist={['*']}
scalesPageToFit={false}
useWebKit={true}
javaScriptEnabled
source={{html}}/>
}
- 加载在线网址
const Demo=()=>{
<WebView
originWhitelist={['*']}
scalesPageToFit={false}
useWebKit={true}
javaScriptEnabled
source={{uri: 'https://github.com/react-native-webview/react-native-webview'}}/>
}
第一种方式:比较符合要求,但是html里面的css、js资源没有办法找到,这些资源也是放在本地的,但是打包的时候并没有把这些资源打包进去,无法加载这些资源
第二种方式:存在和第一种方式一样的问题,而且更加不好书写、调试代码
第三种方式:网上很多例子都是加载的在线地址,那么可不可以加载本地资源呢?
思路
将html及其相关资源放在一个文件夹下面,打包的时候直接复制到apk或者ipa包里面,然后webview访问本地路径加载html
创建文件
创建一个文件夹public/webview
,文件夹名字可以随便起,在我项目里面public用于放置需要被copy到apk或ipa包里面的资源
我们可以看到webview文件夹里面的结构很像以前前端没有工程化的时候的目录结构,对于现在有工程化的项目,那就是把打包好的文件放过来就可以了
配置打包时候copy资源
android配置
在android/app/build.gradle
文件中添加如下代码
...
android{
...
sourceSets {
main {
assets.srcDirs = ['src/main/assets', '../../public']
}
}
}
src/main/assets
是android默认的资源路径,全路径是这样的android/app/src/main/assets
;../../public
是我们刚刚添加的public文件夹,这个配置会告诉app,在打包的时候把public文件夹下的资源复制包中,注意public文件夹不会被复制
在使用的时候就可以通过这个路径来访问资源:
const Demo=()=>{
<WebView
originWhitelist={['*']}
scalesPageToFit={false}
useWebKit={true}
javaScriptEnabled
source={{uri: 'file:///android_asset/webview/index.html'}}/>
}
ios配置
打开在xcode中打开项目,然后把webview
文件夹拖到项目根目录下
这个时候会有一个弹窗,如下所示:
选Create folder references
,建一个文件夹链接,这个链接会关联到public/webview
这个文件夹
接下来找到项目的’Build Phases –> Copy Bundle Resources’ 点击’+’,把刚刚的webview添加进来,看名字就知道这个配置是打包的时候把webview这个文件夹复制到包中。
ios在使用的时候和android有点区别,因为ios没类似android里面的’android_asset’提供便捷的资源访问方式,所以需要加一个第三方库,react-native-fs
.(注意:RNFS.MainBundlePath
这个路径每次安装app之后都会变化的,所以不能写死,只能通过RNFS.MainBundlePath
来获取)
import RNFS from 'react-native-fs';
const Demo=()=>{
<WebView
originWhitelist={['*']}
scalesPageToFit={false}
useWebKit={true}
javaScriptEnabled
source={{uri: `file:///${RNFS.MainBundlePath}/webview/index.html`}}/>
}
调试
我们可以像一般的前端项目一样在浏览器上调试h5的项目,缺点是对于app和h5有通信的还是不太方便调试。
总结
希望大家看完之后有所收获。
参考文章:
【1】.文章1