世博会,React Native:URL 问题和刷新
Expo, React Native: Issue with URL & Refreshing
大家好,我遇到了一个小问题,我一直在为以下平台构建测试插件 [Web、Phones、Desktop]
我正在使用以下框架,
世博会
React Native
反应本机导航
我的问题是在构建应用程序后的 PWA 构建中,我遇到了一个问题,如果用户想直接导航到特定路径或刷新网站页面 returns 404 显然有效在下面的 GIF 示例中。
-- Expo 开发工具:https://gyazo.com/0abc4161810cb14e74543b3dcb854b49
-- 在 运行 世博会之后 build:web
然后在世博会完成构建 PWA 之后我 运行 npx serve web-build
: https://gyazo.com/ed699dcc4b13830647552b07ee112c62
我不确定我需要添加什么配置或什么?我一直在搜索我的问题,但找不到任何东西
如果有人可以提供帮助,那就是你们!!
添加注释 >>>
我没有编写登录系统或任何类型的现金等,这只是一个页面的组件,该页面有一个将用户发送到页面(配置文件)的按钮
App.js
import LoginScreen from './views/login'
import ProfileScreen from './views/profile'
export default function App() {
return React.createElement(
(Platform.OS == 'web') ? web_navigator : mobile_navigator
);
}
function mobile_navigator() {
const Tab = createBottomTabNavigator();
return (
<NavigationContainer>
<Tab.Navigator
screenOptions={{
headerShown: false,
tabBarStyle: {
backgroundColor: "#242629",
borderTopWidth: 0
},
tabBarOptions: {
showLabel: false,
}
}}
>
<Tab.Screen name="Login" component={LoginScreen} />
<Tab.Screen name="Profile" component={ProfileScreen} />
</Tab.Navigator>
</NavigationContainer>
);
}
function web_navigator() {
const Stack = createStackNavigator();
return (
<NavigationContainer linking={{
config: {
screens: {
Login: "/",
Profile: "/Profile/:Username?"
}
},
}}>
<Stack.Navigator
screenOptions={{
headerShown: false
}}>
<Stack.Screen name="Login" component={LoginScreen} />
<Stack.Screen name="Profile" component={ProfileScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
Login.js
const Login = ({navigation}) => {
const [userName, setUserName] = useState('');
const [userPassword, setUserPassword] = useState('');
return (
<View style={styles.Body} >
{Platform.OS === 'web' ?
<View style={styles.Body_left} >
<Image
source={require("../assets/LeftPanel3.png")}
style={styles.Body_left_Picture}
/>
</View>
: null}
<SafeAreaView style={styles.Body_right} >
<View style={styles.Body_Container} >
<Image
source={require("../assets/PlaceHolderLogo.png")}
style={styles.Logo}
/>
<Text h1 style={styles.Login_Title}>Let's Sign In</Text>
<Text style={styles.Login_Title_Child}>Welcome Back!</Text>
<View style={styles.Input_Group} >
<TextInput value={userName} placeholder={'Enter Username'} placeholderTextColor="#fff" onChangeText={(inputOne) => setUserName(inputOne)} style={styles.Input} />
<TextInput value={userPassword} placeholder={'Enter Password'} placeholderTextColor="#fff" onChangeText={(inputTwo) => setUserPassword(inputTwo)} style={styles.Input} />
<Pressable style={styles.Btn_Main} onPress={() => navigation.navigate("Profile", {Username: userName})}>
<Text style={styles.Btn_Text}>Sign In</Text>
</Pressable>
</View>
</View>
</SafeAreaView >
</View>
);
}
export default Login;
Profile.js
export default function App({route}) {
const Profile_Username = route.params ? route.params.Username : "UnKnown"
const Profile_Picture = "https://www.trickscity.com/wp-content/uploads/2019/02/pubg-dp.jpeg"
return (
<View style={{ position: 'relative', backgroundColor: "#242629", flex: 1 }} >
<View style={{ position: 'relative', backgroundColor: "#242629", flex: 0.3 }} ></View>
<View style={{ position: 'relative', backgroundColor: "#16161a", flex: 1 }} >
<View style={styles.ProfileParent} >
<View style={styles.ProfilePictureParent}>
<Image
source={{uri: Profile_Picture}}
style={styles.ProfilePicture}
/>
</View>
<View style={styles.ProfileTitleBox}>
<Text style={styles.ProfileName}>{Profile_Username}</Text>
<Text style={styles.ProfileTag}>Member</Text>
</View>
</View>
</View>
</View>
);
}
---[PWA 文件]---
serve.json
{
"headers": [
{
"source": "static/**/*.js",
"headers": [
{
"key": "Cache-Control",
"value": "public, max-age=31536000, immutable"
}
]
}
]
}
manifest.json
{
"background_color": "#ffffff",
"display": "standalone",
"lang": "en",
"name": "DevBuild",
"short_name": "DevBuild",
"start_url": "/?utm_source=web_app_manifest",
"orientation": "portrait",
"icons": [
{
"src": "\pwa\chrome-icon\chrome-icon-144.png",
"sizes": "144x144",
"type": "image/png"
},
{
"src": "\pwa\chrome-icon\chrome-icon-192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "\pwa\chrome-icon\chrome-icon-512.png",
"sizes": "512x512",
"type": "image/png"
}
]
}
您的问题不在于 expo 或 react-native,您需要在主机中使用 htaccess 将所有请求发送到 index.html 您的 PWA 所在的位置。
第一次导航到 PWA 时,它将加载 index.html 并且每个路由都加载到该 HTML 文件中,并且 URL 地址栏根据您的链接配置而变化,但是当您刷新时页面主机认为它必须转到子文件夹,因为它不知道你的路由不存在于你的 PWA 之外
只需在您的 PWA 文件夹中创建一个 .htaccess 文件并将此代码添加到其中,它应该可以解决您的问题
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
RewriteRule ^ - [L]
RewriteRule ^ /index.html [L]
</IfModule>
针对您的本地环境编辑 serve.json 并添加以下代码
"rewrites": [
{ "source": "/**", "destination": "/index.html" }
]
有关重写的更多信息,您可以查看https://github.com/vercel/serve-handler#options
解决方案
感谢@pfndesign
让我编辑 serve.json 以包含
"rewrites": [
{ "source": "/**", "destination": "/index.html"}
]
请注意,我不是 100% 确定它的作用,但它对我有用,
pfndesign 也将我链接到此:https://github.com/vercel/serve-handler#options
希望这对阅读本文的人有所帮助 :D
大家好,我遇到了一个小问题,我一直在为以下平台构建测试插件 [Web、Phones、Desktop]
我正在使用以下框架,
世博会
React Native
反应本机导航
我的问题是在构建应用程序后的 PWA 构建中,我遇到了一个问题,如果用户想直接导航到特定路径或刷新网站页面 returns 404 显然有效在下面的 GIF 示例中。
-- Expo 开发工具:https://gyazo.com/0abc4161810cb14e74543b3dcb854b49
-- 在 运行 世博会之后 build:web
然后在世博会完成构建 PWA 之后我 运行 npx serve web-build
: https://gyazo.com/ed699dcc4b13830647552b07ee112c62
我不确定我需要添加什么配置或什么?我一直在搜索我的问题,但找不到任何东西
如果有人可以提供帮助,那就是你们!!
添加注释 >>>
我没有编写登录系统或任何类型的现金等,这只是一个页面的组件,该页面有一个将用户发送到页面(配置文件)的按钮
App.js
import LoginScreen from './views/login'
import ProfileScreen from './views/profile'
export default function App() {
return React.createElement(
(Platform.OS == 'web') ? web_navigator : mobile_navigator
);
}
function mobile_navigator() {
const Tab = createBottomTabNavigator();
return (
<NavigationContainer>
<Tab.Navigator
screenOptions={{
headerShown: false,
tabBarStyle: {
backgroundColor: "#242629",
borderTopWidth: 0
},
tabBarOptions: {
showLabel: false,
}
}}
>
<Tab.Screen name="Login" component={LoginScreen} />
<Tab.Screen name="Profile" component={ProfileScreen} />
</Tab.Navigator>
</NavigationContainer>
);
}
function web_navigator() {
const Stack = createStackNavigator();
return (
<NavigationContainer linking={{
config: {
screens: {
Login: "/",
Profile: "/Profile/:Username?"
}
},
}}>
<Stack.Navigator
screenOptions={{
headerShown: false
}}>
<Stack.Screen name="Login" component={LoginScreen} />
<Stack.Screen name="Profile" component={ProfileScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
Login.js
const Login = ({navigation}) => {
const [userName, setUserName] = useState('');
const [userPassword, setUserPassword] = useState('');
return (
<View style={styles.Body} >
{Platform.OS === 'web' ?
<View style={styles.Body_left} >
<Image
source={require("../assets/LeftPanel3.png")}
style={styles.Body_left_Picture}
/>
</View>
: null}
<SafeAreaView style={styles.Body_right} >
<View style={styles.Body_Container} >
<Image
source={require("../assets/PlaceHolderLogo.png")}
style={styles.Logo}
/>
<Text h1 style={styles.Login_Title}>Let's Sign In</Text>
<Text style={styles.Login_Title_Child}>Welcome Back!</Text>
<View style={styles.Input_Group} >
<TextInput value={userName} placeholder={'Enter Username'} placeholderTextColor="#fff" onChangeText={(inputOne) => setUserName(inputOne)} style={styles.Input} />
<TextInput value={userPassword} placeholder={'Enter Password'} placeholderTextColor="#fff" onChangeText={(inputTwo) => setUserPassword(inputTwo)} style={styles.Input} />
<Pressable style={styles.Btn_Main} onPress={() => navigation.navigate("Profile", {Username: userName})}>
<Text style={styles.Btn_Text}>Sign In</Text>
</Pressable>
</View>
</View>
</SafeAreaView >
</View>
);
}
export default Login;
Profile.js
export default function App({route}) {
const Profile_Username = route.params ? route.params.Username : "UnKnown"
const Profile_Picture = "https://www.trickscity.com/wp-content/uploads/2019/02/pubg-dp.jpeg"
return (
<View style={{ position: 'relative', backgroundColor: "#242629", flex: 1 }} >
<View style={{ position: 'relative', backgroundColor: "#242629", flex: 0.3 }} ></View>
<View style={{ position: 'relative', backgroundColor: "#16161a", flex: 1 }} >
<View style={styles.ProfileParent} >
<View style={styles.ProfilePictureParent}>
<Image
source={{uri: Profile_Picture}}
style={styles.ProfilePicture}
/>
</View>
<View style={styles.ProfileTitleBox}>
<Text style={styles.ProfileName}>{Profile_Username}</Text>
<Text style={styles.ProfileTag}>Member</Text>
</View>
</View>
</View>
</View>
);
}
---[PWA 文件]---
serve.json
{
"headers": [
{
"source": "static/**/*.js",
"headers": [
{
"key": "Cache-Control",
"value": "public, max-age=31536000, immutable"
}
]
}
]
}
manifest.json
{
"background_color": "#ffffff",
"display": "standalone",
"lang": "en",
"name": "DevBuild",
"short_name": "DevBuild",
"start_url": "/?utm_source=web_app_manifest",
"orientation": "portrait",
"icons": [
{
"src": "\pwa\chrome-icon\chrome-icon-144.png",
"sizes": "144x144",
"type": "image/png"
},
{
"src": "\pwa\chrome-icon\chrome-icon-192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "\pwa\chrome-icon\chrome-icon-512.png",
"sizes": "512x512",
"type": "image/png"
}
]
}
您的问题不在于 expo 或 react-native,您需要在主机中使用 htaccess 将所有请求发送到 index.html 您的 PWA 所在的位置。 第一次导航到 PWA 时,它将加载 index.html 并且每个路由都加载到该 HTML 文件中,并且 URL 地址栏根据您的链接配置而变化,但是当您刷新时页面主机认为它必须转到子文件夹,因为它不知道你的路由不存在于你的 PWA 之外
只需在您的 PWA 文件夹中创建一个 .htaccess 文件并将此代码添加到其中,它应该可以解决您的问题
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
RewriteRule ^ - [L]
RewriteRule ^ /index.html [L]
</IfModule>
针对您的本地环境编辑 serve.json 并添加以下代码
"rewrites": [
{ "source": "/**", "destination": "/index.html" }
]
有关重写的更多信息,您可以查看https://github.com/vercel/serve-handler#options
解决方案
感谢@pfndesign
让我编辑 serve.json 以包含
"rewrites": [
{ "source": "/**", "destination": "/index.html"}
]
请注意,我不是 100% 确定它的作用,但它对我有用,
pfndesign 也将我链接到此:https://github.com/vercel/serve-handler#options
希望这对阅读本文的人有所帮助 :D