我们没有使用 eas 或 expo go,而是使用我们自己的配置文件以及 app.json 和 babel.config.js 的组合。
我们希望从开发环境过渡到质量保证/临时环境。我们正在使用 azure pipelines 运行 expo 的 ios 和 android 构建预构建命令。例如:
npx expo prebuild --platform ios --clean --npm
我成功设置了开发环境以使用以下命令运行...
npx expo run dev-android
(指向package.json中的以下脚本"dev-android": "cross-env NODE_ENV=development npx expo run:android --port 8082"
开发环境成功打印出以下内容...
import React, { useEffect } from 'react';
import * as SplashScreen from 'expo-splash-screen';
import '@app/utils/IgnoreWarnings';
import Toast from 'react-native-toast-message';
import { SafeAreaProvider } from 'react-native-safe-area-context';
import { GlobalContextProvider, useLoadingStore } from '@app/stores';
import { ToastInit } from '@app/components';
import { NavigationConductor } from '@app/navigation';
import { toastFailedProps } from '@app/utils';
import { RANDOM_ENV_DEV, RANDOM_ENV_QA } from '@env';
import type { LoadingStore } from '@app/types';
// Keep the splash screen visible while we fetch resources
SplashScreen.preventAutoHideAsync();
export default function App() {
// variables
const { loadInitialAppData } = useLoadingStore((store: LoadingStore) => store);
// setup
useEffect(() => {
console.log('NODE_ENV:', process.env.NODE_ENV);
console.log('RANDOM_ENV_DEV:', RANDOM_ENV_DEV);
console.log('RANDOM_ENV_QA:', RANDOM_ENV_QA);
const loadApp = async () => {
try {
await loadInitialAppData();
} catch (error: any) {
Toast.show(toastFailedProps(error.message));
} finally {
await SplashScreen.hideAsync();
}
};
loadApp();
}, [loadInitialAppData]);
// render
return (
<GlobalContextProvider>
<SafeAreaProvider>
<NavigationConductor />
<ToastInit />
</SafeAreaProvider>
</GlobalContextProvider>
);
}
RANDOM_ENV_DEV=HelloWorldDev
RANDOM_ENV_QA=HelloWorldQa
module.exports = function (api) {
api.cache(true);
return {
presets: ['module:metro-react-native-babel-preset', 'babel-preset-expo'],
plugins: [
[
require.resolve('babel-plugin-module-resolver'),
{
extensions: ['.js', '.jsx', '.ts', '.tsx', '.android.js', '.android.tsx', '.ios.js', '.ios.tsx'],
alias: {
'@': './',
'@app': './app'
}
}
],
[
'module:react-native-dotenv',
{
envName: 'APP_ENV',
moduleName: '@env',
path: '.env',
blocklist: null,
allowlist: null,
blacklist: null, // DEPRECATED
whitelist: null, // DEPRECATED
safe: false,
allowUndefined: true,
verbose: false
}
]
]
};
};
{
"expo": {
"name": "PROJECTNAME",
"slug": "PROJECTSLUG",
"version": "1.0.0",
"scheme": "msauth",
"orientation": "portrait",
"icon": "./assets/images/qa-icon-1024.png",
"userInterfaceStyle": "light",
"backgroundColor": "#001689",
"splash": {
"image": "./assets/images/qa-splash.png",
"resizeMode": "contain",
"backgroundColor": "#001689"
},
"assetBundlePatterns": ["**/*"],
"ios": {
"supportsTablet": true,
"bundleIdentifier": "com.example.qa",
"buildNumber": "1.0.0"
},
"android": {
"adaptiveIcon": {
"foregroundImage": "./assets/images/qa-icon-1024.png",
"backgroundColor": "#001689"
},
"package": "com.example.qa",
"versionCode": 1
},
"web": {
"favicon": "./assets/favicon.png"
},
"plugins": [
[
"expo-build-properties",
{
"android": {
"minSdkVersion": 23
}
}
],
[
"expo-image-picker",
{
"photosPermission": "Allow $(PRODUCT_NAME) to access your photos",
"cameraPermissions": "Allow $(PRODUCT_NAME) to access your camera"
}
]
]
}
}
{
"name": "Project-Name",
"version": "1.0.0",
"main": "node_modules/expo/AppEntry.js",
"scripts": {
"ts:check": "tsc",
"dev-android": "cross-env NODE_ENV=development npx expo run:android --port 8082",
"dev-ios": "cross-env NODE_ENV=development npx expo run:ios --port 8082",
"android": "expo run:android",
"ios": "expo run:ios"
},
"dependencies": {
"@expo/vector-icons": "^13.0.0",
"@react-native-async-storage/async-storage": "1.18.2",
"@react-native-community/netinfo": "9.3.10",
"@react-navigation/native": "^6.1.9",
"@react-navigation/stack": "^6.3.20",
"axios": "^1.6.2",
"core-js": "^3.35.0",
"expo": "~49.0.15",
"expo-auth-session": "~5.0.2",
"expo-build-properties": "^0.8.3",
"expo-constants": "~14.4.2",
"expo-file-system": "~15.4.5",
"expo-image-manipulator": "~11.3.0",
"expo-image-picker": "~14.3.2",
"expo-secure-store": "~12.3.1",
"expo-splash-screen": "~0.20.5",
"expo-status-bar": "~1.6.0",
"expo-system-ui": "~2.4.0",
"expo-web-browser": "~12.3.2",
"formik": "^2.4.5",
"jwt-decode": "^4.0.0",
"lodash": "^4.17.21",
"react": "18.2.0",
"react-native": "0.72.10",
"react-native-device-info": "^11.1.0",
"react-native-element-dropdown": "^2.10.1",
"react-native-gesture-handler": "~2.12.0",
"react-native-get-random-values": "~1.9.0",
"react-native-safe-area-context": "4.6.3",
"react-native-screens": "~3.22.0",
"react-native-toast-message": "^2.1.9",
"react-query": "^3.39.3",
"scandit-react-native-datacapture-barcode": "^6.21.3",
"scandit-react-native-datacapture-core": "^6.21.3",
"uri-scheme": "^1.1.0",
"uuid": "^9.0.1",
"yup": "^1.3.2",
"zustand": "^4.4.7"
},
"devDependencies": {
"@babel/core": "^7.20.0",
"@types/lodash": "^4.14.202",
"@types/react": "~18.2.14",
"@types/uuid": "^9.0.7",
"cross-env": "^7.0.3",
"react-native-dotenv": "^3.4.10",
"typescript": "^5.1.3"
},
"private": true
}
declare module '@env' {
export const RANDOM_ENV_DEV: string;
export const RANDOM_ENV_QA: string;
}
declare var process: {
env: {
NODE_ENV: string;
};
};
这是在开发环境中工作的,其中
process.env.NODE_ENV
读作 development
。
现在,当我们使用 expo
prebuild
命令来打包包含 process.env.NODE_ENV
的构建时,我们该如何使其读取为 uat
或 qa
?
由于您已经有了react-native-dotenv,您可以创建多个.env文件来满足您对UAT或QA的需求
.env.dev
.env.uat
.env.qa
在您的 package.json 文件中
"scripts": {
"dev-android": "cross-env NODE_ENV=development npx expo run:android --port 8082",
"dev-ios": "cross-env NODE_ENV=development npx expo run:ios --port 8082",
"uat-android": "cross-env NODE_ENV=uat npx expo run:android --port 8082",
"uat-ios": "cross-env NODE_ENV=uat npx expo run:ios --port 8082",
"qa-android": "cross-env NODE_ENV=qa npx expo run:android --port 8082",
"qa-ios": "cross-env NODE_ENV=qa npx expo run:ios --port 8082",
},