我在服务器上呈现了经典的 Web 应用程序。我想在 React 中创建管理面板作为单页应用程序。我想从https://smyapp.example.com/admin/服务器管理面板。我尝试使用,create-react-app
但它假定我从根 URL 提供 SPA。我应该如何配置create-react-app
以从"admin"
子目录提供应用程序?在文档中,我找到了"homepage"
属性,但如果我正确理解它需要完整的 url。我无法提供完整的 url,因为我的应用程序部署在少数环境中。
我应该如何配置 create-react-app 以从子目录提供应用程序?
除了您的要求之外,我还要添加我的要求:
- 它应该由 CD 通过环境变量完成。
- 如果我需要重命名子目录,我应该只需要更改 env 变量。
- 它应该与react-router一起使用。
- 它应该适用于 scss (sass) 和 html。
- 一切都应该在开发模式(npm start)下正常工作。
不久前,我还不得不在 Angular2+ 项目中实现它,我发现在 React 中实现它比在 Angular2+ 中更难实现,在那里你可以很好地使用ng build --base-href /<project_name>/
. 来源
简洁版本
- 在构建之前,将
PUBLIC_URL
env 变量设置为子目录的值,/subdir
例如使用。您也可以将此变量放入您的.env.production
(如果您没有该文件,您可以查看文档) - 在
public/index.html
加入碱元素波纹管,这是对于像图像静态文件。
<base href="%PUBLIC_URL%/">
- 同样在 中
public/index.html
,如果您有自定义link
元素,请确保它们以%PUBLIC_URL%
(likemanifest.json
和favicon.ico
href)为前缀。 - 如果使用
BrowserRouter
,则可以添加basename
props:
<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')`}}>
...
你应该完成。
附加信息
我更喜欢使用PUBLIC_URL
而不是homepage
inpackage.json
因为我想使用在 gitlab 上设置的 env 变量来设置子目录。关于该主题的相关资源:
- https://create-react-app.dev/docs/deployment/#building-for-relative-paths
- https://create-react-app.dev/docs/advanced-configuration/
- https://github.com/facebook/create-react-app/issues/998
PUBLIC_URL
override homepage
,PUBLIC_URL
如果您提供域名,还可以使用域名。如果只设置homepage
,PUBLIC_URL
将设置为 的值homepage
。
如果您不想在 index.html 中使用基本元素(我不知道为什么),您将需要自己附加process.env.PUBLIC_URL
到每个链接。请注意,如果您有带有基本元素的 react-router,但尚未设置basename
prop,您将收到警告。
Sass 不会使用不正确的相对路径进行编译。它也不会使用正确的../public/assets
文件夹相对路径编译,由于ModuleScopePlugin
限制,您可以通过将图像移动到 src 文件夹中来避免限制,我还没有尝试过。
似乎没有办法在开发模式下测试相对路径(npm start)。看评论
最后,这些 stackoverflow 链接有相关问题:
对于 create-react-app v2 和 react-router v4,我使用以下组合在“/app”下提供生产(暂存、uat 等)应用程序:
包.json:
"homepage": "/app"
然后在应用程序入口点:
<BrowserRouter basename={process.env.PUBLIC_URL}>
{/* other components */}
</BrowserRouter>
并且在本地开发和部署环境中一切都“正常工作”。哼!
您应该package.json
为此添加条目。
在package.json 中添加一个关键的 "homepage": "your-subfolder/" 所有静态文件将从 "your-subfolder" 加载
如果没有子文件夹并且您需要从同一文件夹加载,则需要将路径添加为“./”或删除具有 "homepage": "xxxxxxxxxx"
"homepage": "./"
来自官方文档
默认情况下,假设您的应用程序托管在服务器根目录下,Create React App 会生成一个构建。要覆盖它,请在 package.json 中指定主页,例如:
"主页": "http://mywebsite.com/relativepath",
注意:如果您使用的是react-router@^4
,则可以<Link>
在任何<Router>
.
要获取相对 URL,您可以像这样构建应用程序:
PUBLIC_URL="." npm run build
也许您可以使用react-router
它的相关 basename
参数,它允许您从子目录为您的应用程序提供服务。
basename
是所有位置的基本 URL。如果您的应用程序是从服务器上的子目录提供的,您需要将其设置为子目录。格式正确的基本名称应该有一个前导斜杠,但没有尾随斜杠。
例如:
<BrowserRouter basename="/calendar"/>
所以<Link to="/today"/>
会渲染<a href="/calendar/today">
请参阅:https : //reacttraining.com/react-router/web/api/BrowserRouter/basename-string