一、创建项目
expo init MyProject
创建项目,选择托管工作流的TypeScript的空白模板,然后用 expo eject
退出到裸漏工作流。
之所以选择这种方式创建项目,是因为灵活性很大,可以在托管和裸漏之间做开发(android&ios/android)。
因为很多库是依赖裸漏工作流开发的且打包android apk的时候可以减少size,但是同时也可以使用Expo开发的库而节省了手动配置的时间。
特别注意:在退出之前,必须先expo login登录,否则在构建的时候会报错;在app.json中将基础的配置配置好,比如屏幕方向设置为 ‘default’,背景色设置为 ‘#00000088’ 等。免去之后手动配置的步骤。
android package name 的命名方式:https://developer.android.com/studio/build/application-id
二、从托管managed工作流中退出到裸漏bare工作流
Step1. 退出
expo eject
Step2. 在项目根目录执行下载密钥
expo fetch:android:keystore
Step3.将命令行窗口中的密钥复制保存到 temporary_dev_files/build_apk_key 临时文件夹中,便于之后打包apk使用
三、查看项目环境信息
Expo/RN项目根目录下可执行以下命令
react-native info
Expo项目根目录下也可执行
expo diagnostics
四、项目根目录最好新建一个 temporary_dev_files 临时开发文件夹,便于管理许多开发阶段临时存放的文件
五、关于修改node_modules软件包的事宜
有时候安装的软件包不符合自己的要求或者存在bug,需要自己修改软件包源代码,进入到node_modules中找到相关的软件包源码进行修改。
在不影响开发的情况下,最省事的做法是,将修改好的代码复制一份保存到 temporary_dev_files/modules (注意不要命名为node_modules,因为github不会提交) 临时文件夹,项目会自动读取modules的修改文件。
六、.d.ts 文件
很多时候,很多库都没有直接安装的TypeScript版本,但是往往带有 index.d.ts 文件。
可以将它放置到 no_modules/对应的软件包根目录中,就可以生效了,当然,也可在项目根目录新建一个d.ts文件夹,里面可以放置各种库的d.ts文件。
也可以更省事在项目根目录新建type.d.ts
或者
或者(推荐)
项目根目录新建 type.d.ts
declare module 'react-native-static-server'
declare module 'react-native-fs'
七、关于expo启动图片不显示和裸漏工作流打包失败的问题
expo sdk40 启动图片不显示,连官方都给不到答案。github issues
同时,裸漏工作流打包失败。裸漏工作流和托管工作流打包出来的apk都不显示图像。
问题分析,本地java sdk和托管服务器java sdk没有升级。
解决办法:
升级java8到最新版本就可以解决了。
从8u271 升级到 8u281 。
裸漏工作流中打包没有问题了,同时apk启动图像也可以显示了。
至于托管工作流,由于服务器在Expo,要等到他们升级了估计才能正常显示图片。
八、打包apk的尺寸和性能提升
用裸漏工作流打包要比托管工作流尺寸要小不少,这对于对体积有要求的项目是个选择。
压缩及优化apk包 –启用Hermes爱马仕 + 构建不同架构的apk
图片会对性能有很大的影响(cpu和内存等峰值),建议使用webp格式的图像
// Step1. android/app/build.gradle
project.ext.react = [
entryFile: "index.js",
- enableHermes: false // clean and rebuild if changing
+ enableHermes: true // clean and rebuild if changing
]
- def enableHermes = project.ext.react.get("enableHermes", false);
+ def enableHermes = project.ext.react.get("enableHermes", true);
- def enableSeparateBuildPerCPUArchitecture = false
+ def enableSeparateBuildPerCPUArchitecture = true
// Step2. 清理构建
cd android && ./gradlew clean
// Step3. 重新构建
gradlew assembleRelease
九、裸漏工作流打包apk后,github上传文件过大
由于打包后的android代码增加了一个.hprof
和一个 BasePackageList.java
大文件,所以在上传到github的时候文件超大了,由于expo用expo eject
退出到裸漏工作流的时候没有自动生成对.hprof和BasePackageList.java的限制新.gitignore
文件,所以要手动自己添加进去。最省事就是去到Expo的github根目录拿现成的来用 https://github.com/expo/expo/blob/master/.gitignore
十、gradlew clean
yarn android
过程中,报Task :app:processDebugResources FAILED
等等错误。
Step1. android 文件夹中 执行清理构建
gradlew clean
Step2. 然后再返回项目根目录 执行
yarn android
十一、Could not download groovy-all-2.4.15.jar
由于中国共产党邪教的原因
* What went wrong:
Could not determine the dependencies of task ':app:lintVitalRelease'.
> Could not resolve all artifacts for configuration ':app:debugCompileClasspath'.
> Could not download groovy-all-2.4.15.jar (org.codehaus.groovy:groovy-all:2.4.15)
> Could not get resource 'https://jcenter.bintray.com/org/codehaus/groovy/groovy-all/2.4.15/groovy-all-2.4.15.jar'.
> Could not GET 'https://jcenter.bintray.com/org/codehaus/groovy/groovy-all/2.4.15/groovy-all-2.4.15.jar'.
> Remote host terminated the handshake
解决办法
Step1.
android/build.gradle
repositories {
- google()
- jcenter()
//用阿里镜像替换
+ maven { url 'https://maven.aliyun.com/repository/google'}
+ maven { url 'https://maven.aliyun.com/repository/jcenter'}
+ maven { url 'http://maven.aliyun.com/nexus/content/groups/public'}
}
Step2. 然后再打包apk
gradlew assembleRelease
十二、深层链接 DeepLink + android backbutton 安卓返回键 例子
在
/android/app/src/main/AndroidManifest.xml
中配置 scheme 访问前缀
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="myapp"/>
<data android:scheme="com.notbrent.mofengfs"/>
<data android:scheme="a08"/>
</intent-filter>
配置深层链接
import * as Linking from 'expo-linking';
export default {
prefixes: ['a08://'],
config: {
screens: {
Root: {
screens: {
TabOne: {
screens: {
TabOneScreen: 'one',
},
},
TabTwo: {
screens: {
TabTwoScreen: 'two',
},
},
},
},
// NotFound: '*',
List: {
path: 'list/:id',
parse: {
id: (id: any) => `${id}`
}
},
Detail: {
path: 'detail/:id',
parse: {
id: (id: any) => `${id}`
}
}
}
},
};
NavigationContainer
中调用深层链接
<NavigationContainer
linking={LinkingConfiguration}
theme={colorScheme === 'dark' ? DarkTheme : DefaultTheme}>
<RootNavigator />
</NavigationContainer>
android backbutton 不能返回上一页的解决办法
每个非首页屏幕都要添加goBack代码
import { BackHandler } from 'react-native';
export const listScreen = ({ navigation: { goBack } }) => {
// 返回上一屏 start
function handleBackButtonClick() {
goBack();
return true;
}
useEffect(() => {
BackHandler.addEventListener('hardwareBackPress', handleBackButtonClick);
return () => {
BackHandler.removeEventListener('hardwareBackPress', handleBackButtonClick);
};
}, []);
// 返回上一屏 end
...
...
唤醒深层链接,执行例如:
npx uri-scheme open a08://detail/123 --android
完整例子:https://github.com/mofengfs/DeepLink-BackHandler-Example
十三、启动屏幕白闪解决
使用 react navigation v5和 eva 主题, 在 NavigationContainer 中配置深色主题即可
Step1.
import { NavigationContainer, DarkTheme, DefaultTheme } from '@react-navigation/native';
import * as eva from '@eva-design/eva';
Step2.
const navigationTheme = eva.dark ? DarkTheme : DefaultTheme;
Step3.
<NavigationContainer theme={navigationTheme} linking={deepLinking}>
<MainStack />
</NavigationContainer>
十四、worker cmd 假死状态
有时候打印没有即时显示,可以尝试敲回车键
十五、error: Android project not found. Are you sure this is a React Native project?
很可能是丢失了./android/app/src/main/AndroidManifest.xml
文件
十六、Deprecated Gradle features were used in this build, making it incompatible with Gradle 7.0
./android/build.gradle
- classpath("com.android.tools.build:gradle:3.5.3")
+ classpath("com.android.tools.build:gradle:3.5.4")
十七、文件更新,标记
任意能持久保存数据的地方/方式都可以做版本标记,总之就是让程序自己知道哪些逻辑执行过了,哪些需要执行,执行完了做标记,不管啥迁移都是这么个流程
通过拉去服务器返回的版本号与本地数据库保存的版本号做对比,判断是否应该执行文件的更新操作。
注意:压缩文件必须是能够直接解压不带根文件夹名称,压缩的时候需要注意,操作如下: 全选添加到 www.zip 操作
十八、UI方向
默认UI横向。 只要进入了项目,就可以随意更改方向了。
有关如何控制应用程序方向的信息,请参见app.json
中的方向键
有效值:自响应default
,纵向portrait
,横向landscape
App.json中配置
{
"expo": {
"name": "my-app",
"slug": "my-app",
"version": "1.0.0",
- "orientation": "portrait",//纵向
+ "orientation": "default",//自响应
"icon": "./assets/icon.png",
"splash": {
"image": "./assets/splash.png",
"resizeMode": "contain",
"backgroundColor": "#ffffff"
},
"updates": {
"fallbackToCacheTimeout": 0
},
"assetBundlePatterns": [
"**/*"
],
"ios": {
"supportsTablet": true
},
"android": {
"adaptiveIcon": {
"foregroundImage": "./assets/adaptive-icon.png",
"backgroundColor": "#FFFFFF"
}
},
"web": {
"favicon": "./assets/favicon.png"
}
}
}
十九、Expo&UI-Kitten(web端报错的问题)
解决办法:
//1.安装
expo install @expo/webpack-config
//2.根目录新建`webpack.config.js`添加
const createExpoWebpackConfigAsync = require('@expo/webpack-config');
module.exports = async function(env, argv) {
const config = await createExpoWebpackConfigAsync({
...env,
babel: {
dangerouslyAddModulePathsToTranspile: ['@ui-kitten/components']
}
}, argv);
return config;
};
二十、Expo Web 项目抽屉
-
轮播图适合用的不多,
react-native-banner-carousel
是其中一个 -
react-native-webview
不支持web端渲染html,替代方案是使用react-native-web-webview
-
在线客服
function Link(props: any) {
return (
<Text
{...props}
accessibilityRole="link"
style={StyleSheet.compose(styles.link, props.style)}
/>
);
}
<Link href="http://wpa.qq.com/msgrd?v=3&uin=QQ号&site=qq&menu=yes" style={styles.item}>
<TouchableOpacity style={styles.link}>
<FontAwesome5 name="comments" size={24} color="#1296db" />
<Text style={styles.item_text}>在线客服</Text>
</TouchableOpacity>
</Link>
-
模态框使用
react-native-modalize
-
由于expo build:web 构建的是单页面应用,所以,在刷新页面的时候会找不到路由对应的文件,所以,最便捷的方式是通过npx serve –single启动服务,通过云服务配置对应的端口号,比如配置5000, 那么npx serve –single启动的服务也应该是5000, IIS配置的端口号随便了,只要不与5000或者其他端口冲突就行了。
除了5000端口号,还可通过以下命令自定义端口号(基于Vercel服务库)
npx serve --single -l 1337
//or
npx serve --single --listen 1337