我有一个经典的Web应用程序,由服务器渲染。我想在React中创建单页管理面板。我想从https://smyapp.example.com/admin/提供管理面板服务。我尝试使用create-react-app
,但它假定我从根URL提供SPA。我应该如何配置create-react-app
来使应用程序从"admin"
子目录中提供服务?在文档中我找到了"homepage"
属性,但如果我正确理解它,它需要完整的URL。我无法提供完整的URL,因为我的应用程序部署在几个环境中。
我有一个经典的Web应用程序,由服务器渲染。我想在React中创建单页管理面板。我想从https://smyapp.example.com/admin/提供管理面板服务。我尝试使用create-react-app
,但它假定我从根URL提供SPA。我应该如何配置create-react-app
来使应用程序从"admin"
子目录中提供服务?在文档中我找到了"homepage"
属性,但如果我正确理解它,它需要完整的URL。我无法提供完整的URL,因为我的应用程序部署在几个环境中。
除了你的要求,我添加了我的:
不久前,我还不得不在Angular2+项目中实现它,我发现在React中比在Angular2+中实现更难,在Angular2+中只需使用ng build --base-href /<project_name>/
即可。 来源
PUBLIC_URL
环境变量设置为您的子目录的值,例如/subdir
。您也可以将此变量放入.env.production
文件中。(如果您没有该文件,请查看文档)public/index.html
中添加基本元素如下,这是用于静态文件(如图像)的。<base href="%PUBLIC_URL%/">
public/index.html
中有自定义的 link
元素,请确保它们以 %PUBLIC_URL%
为前缀(例如,manifest.json
和 favicon.ico
的 href 属性)。BrowserRouter
,可以添加 basename
属性:<BrowserRouter basename={process.env.PUBLIC_URL} />
Router
,因为您需要访问history.push
方法以编程方式更改页面,请执行以下操作:// history.tsx
import {createBrowserHistory} from 'history';
export default createBrowserHistory({ basename: process.env.PUBLIC_URL });
<!-- Where your router is, for me, App.tsx -->
<Router history={history}>
...
</Router>
<!-- "./assets/quotes.png" is also ok, but "/assets/quotes.png" is not -->
<img src="assets/quotes.png" alt="" />
background-image
链接从scss移动到jsx/tsx文件中(如果使用css文件可能不需要这样做):/*remove that*/
background-image: url('/assets/background-form.jpg');
<section style={{backgroundImage: `url('assets/background-form.jpg')`}}>
...
你应该完成了。
我更喜欢在 package.json
中使用 PUBLIC_URL
而不是 homepage
,因为我想使用在 GitLab 上设置的环境变量来设置子目录。有关此主题的相关资源:
PUBLIC_URL
会覆盖 homepage
,如果提供域名,则 PUBLIC_URL
也会接受它。 如果只设置了 homepage
,则 PUBLIC_URL
将被设置为 homepage
的值。
如果您不想在 index.html 中使用 base 元素(我不知道为什么),则需要自己添加 process.env.PUBLIC_URL
到每个链接中。请注意,如果您有带有基础元素的 react-router,但没有设置 basename prop,则会收到警告。
使用错误的相对路径编译 Sass 也将无法编译。由于 ModuleScopePlugin
的限制,即使使用正确的相对路径到您的 ../public/assets
文件夹,它也不会编译。您可以通过将图像移动到 src 文件夹中来避免此限制,我还没有尝试过。
似乎没有办法在开发模式(npm start)下测试相对路径。请参见评论
最后,这些 stackoverflow 链接有相关问题:
对于 create-react-app v2 和 react-router v4,我使用以下组合来在 "/app" 下提供生产环境(staging、uat 等)应用:
package.json:
"homepage": "/app"
然后在应用程序入口点中:
<BrowserRouter basename={process.env.PUBLIC_URL}>
{/* other components */}
</BrowserRouter>
一切在本地开发和部署环境下都“只是工作”。祝好运!
<base href="/app/" />
,以使资源正常工作 - 资源使用相对URL(例如<link href="css.css" rel="stylesheet" />
)。 - kjetilh您需要在package.json
中添加条目。
在您的package.json中添加一个键“homepage”:“your-subfolder /”,所有静态文件都将从“your-subfolder”加载
如果没有子文件夹并且您需要从相同文件夹加载,则需要将路径添加为“./”,或者删除具有"homepage":"xxxxxxxxxx"
的整行
"homepage": "./"
来自官方文档
默认情况下,Create React App会生成一个构建,假设您的应用程序托管在服务器根目录下。 要覆盖此设置,请在您的package.json中指定主页,例如:
"homepage": "http://mywebsite.com/relativepath",
注意: 如果您正在使用react-router@^4
,则可以在任何<Router>
上使用basename prop路由<Link>
要获取相对URL,您可以像这样构建应用程序:
PUBLIC_URL="." npm run build
react-router
和它的 相对 basename
参数,这样您就可以从子目录中提供您的应用程序。
basename
是所有位置的基本网址。如果您的应用程序是从服务器上的子目录提供的,则需要将其设置为该子目录。格式正确的 basename 应该有一个前导斜杠,但没有尾随斜杠。<BrowserRouter basename="/calendar"/>
因此,<Link to="/today"/>
将呈现为<a href="/calendar/today">
参见:https://reacttraining.com/react-router/web/api/BrowserRouter/basename-string
<BrowserRouter basename="/our_subfolder/" />
按照以下步骤从子目录中提供React应用程序的服务。
在package.json
文件中添加homepage
条目。
"homepage": "xyz/",
如果您正在从子目录提供应用程序,请更改基本路由名称。
<BrowserRouter basename={"/xyz"}>
<Routes/>
</BrowserRouter>
如果您正在使用Nginx服务器,则必须指定位置,如下所示:
location /xyz {
alias /build-folder-path;
try_files $uri /$uri /xyz/index.html;
}
注意:xyz是子目录名称。
<BrowserRouter basename={process.env.PUBLIC_URL}>
{/*Your components*/}
</BrowserRouter>
<html> <head>
<title>welcome to example_123</title>
<!--<meta http-equiv="refresh" content="0.2; URL=web/index.html"> -->
<meta name="keywords" content="automatic redirection">
</head>
<body> </body>
</html>
奖金
如果想将您的内容放在 /web 中,并且不想要上下文路径,请按照以下步骤进行:
您可以在webpack配置中指定公共路径,同时使用React路由基础路径。
链接到公共路径:https://webpack.js.org/guides/public-path/
请注意,公共路径需要以斜杠 / 开头和结尾才能有效。