[英]How should I configure create-react-app to serve app from subdirectory?
I have classic web application rendered on server.我在服务器上呈现了经典的 Web 应用程序。 I want to create admin panel as single page application in React.我想在 React 中创建管理面板作为单页应用程序。 I want to server admin panel from https://smyapp.example.com/admin/ .我想从https://smyapp.example.com/admin/服务器管理面板。 I try to use create-react-app
but it assumes that i serve SPA from root URL.我尝试使用create-react-app
但它假定我从根 URL 提供 SPA。 How should I configure create-react-app
to serve app from "admin"
subdirectory?我应该如何配置create-react-app
以从"admin"
子目录提供应用程序? In documentation I found "homepage"
property but if I properly understand it requires complete url.在文档中我找到了"homepage"
属性,但如果我正确理解它需要完整的 url。 I can't give complete url because my app is deployed in few environments.我无法提供完整的 url,因为我的应用程序部署在少数环境中。
In addition to your requirements , I am adding mine:除了您的要求外,我还添加了我的:
I also had to implement it in Angular2+ project not long ago, I found it harder to implement in React then in Angular2+ where you are good to go with ng build --base-href /<project_name>/
.不久前,我还不得不在 Angular2+ 项目中实现它,我发现在 React 中实现它比在 Angular2+ 中实现它更难,你最好使用ng build --base-href /<project_name>/
。 source 资源
PUBLIC_URL
env variable to the value of your subdirectory, let use /subdir
for example.在构建之前,将PUBLIC_URL
变量设置为子目录的值,例如使用/subdir
。 You can also put this variable into your .env.production
( in case you do not have that file you can check the doc )您也可以将此变量放入您的.env.production
中(如果您没有该文件,您可以查看文档)public/index.html
add the base element bellow, this is for static files like images.在public/index.html
中添加基本元素波纹管,这是用于静态文件,如图像。<base href="%PUBLIC_URL%/">
public/index.html
, if you have custom link
element, make sure theyre are prefixed with %PUBLIC_URL%
(like manifest.json
and favicon.ico
href).同样在public/index.html
中,如果您有自定义link
元素,请确保它们以%PUBLIC_URL%
为前缀(如manifest.json
和favicon.ico
href)。BrowserRouter
, you can add basename
prop:如果你使用BrowserRouter
,你可以添加basename
属性:<BrowserRouter basename={process.env.PUBLIC_URL} />
Router
instead, because you need access to history.push
method, to programmatically change page, do the following:如果您改用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
links from scss to jsx/tsx files (note that you may not need to do that if you use css files):将您的background-image
链接从 scss 移动到 jsx/tsx 文件(请注意,如果您使用 css 文件,您可能不需要这样做):/*remove that*/
background-image: url('/assets/background-form.jpg');
<section style={{backgroundImage: `url('assets/background-form.jpg')`}}>
...
You should be done.你应该完成了。
I preferred to use PUBLIC_URL
instead of homepage
in package.json
because I want to use env variable set on gitlab to set the subdir.我更喜欢在package.json
中使用PUBLIC_URL
而不是homepage
,因为我想使用 gitlab 上设置的 env 变量来设置子目录。 Relevant resources about the subject:关于该主题的相关资源:
PUBLIC_URL
override homepage
, and PUBLIC_URL
also take the domain name, if you provide one. PUBLIC_URL
覆盖homepage
,并且PUBLIC_URL
也采用域名,如果您提供一个。 If you set only homepage
, PUBLIC_URL
will be set to the value of homepage
.如果只设置homepage
, PUBLIC_URL
将设置为homepage
的值。
If you do not want to use a base element in your index.html (I would not know why), you will need to append process.env.PUBLIC_URL
to every link yourself.如果您不想在 index.html 中使用基本元素(我不知道为什么),您需要自己将process.env.PUBLIC_URL
附加到每个链接。 Note that if you have react-router with a base element, but have not set basename
prop, you will get a warning.请注意,如果您有带有基本元素的 react-router,但尚未设置basename
属性,您将收到警告。
Sass won't compile with an incorrect relative path. Sass 不会使用不正确的相对路径进行编译。 It also won't compile with correct relative path to your ../public/assets
folder, because of ModuleScopePlugin
restrictions, you can avoid the restriction by moving your image inside the src folder, I haven't tried that.它也不会以正确的相对路径编译到您的../public/assets
文件夹,因为ModuleScopePlugin
限制,您可以通过将图像移动到 src 文件夹中来避免限制,我没有尝试过。
There seem to be no way of testing relative path in development mode (npm start).似乎没有办法在开发模式下测试相对路径(npm start)。 see comment 见评论
Finnaly, theses stackoverflow link have related issues:最后,这些stackoverflow链接有相关问题:
For create-react-app v2 and react-router v4, I used the following combo to serve a production (staging, uat, etc) app under "/app":对于 create-react-app v2 和 react-router v4,我使用以下组合在“/app”下为生产(staging、uat 等)应用程序提供服务:
package.json:包.json:
"homepage": "/app"
Then in the app entry point:然后在应用入口点:
<BrowserRouter basename={process.env.PUBLIC_URL}>
{/* other components */}
</BrowserRouter>
And everything "just works" across both local-dev and deployed environments.在本地开发和部署环境中,一切都“正常工作”。 HTH! !
You should add entry in package.json
for this.为此,您应该在package.json
中添加条目。
Add a key "homepage": "your-subfolder/" in your package.json All static files will be loaded from "your-subfolder"在你的package.json中添加一个键 "homepage": "your-subfolder/" 所有静态文件都将从 "your-subfolder" 加载
If there is no subfolder and you need to load from same folder you need to add the path as "./" or remove the entire line which has "homepage": "xxxxxxxxxx"
如果没有子文件夹并且您需要从同一文件夹加载,则需要将路径添加为“./”或删除具有"homepage": "xxxxxxxxxx"
"homepage": "./"
From the official docs来自官方文档
By default, Create React App produces a build assuming your app is hosted at the server root.默认情况下,Create React App 会生成一个构建,假设您的应用程序托管在服务器根目录中。 To override this, specify the homepage in your package.json, for example:要覆盖它,请在 package.json 中指定主页,例如:
"homepage": "http://mywebsite.com/relativepath", "主页": "http://mywebsite.com/relativepath",
Note: If you are using react-router@^4
, you can route <Link>
s using the basename prop on any <Router>
.注意:如果您使用react-router@^4
,您可以使用任何<Router>
上的 basename 属性路由<Link>
> 。
From here and also check the official CRA docs从这里查看官方 CRA 文档
要获取相对 URL,您可以像这样构建应用程序:
PUBLIC_URL="." npm run build
Maybe you could use react-router
and its relative basename
parameter which allows you to serve your app from a subdirectory.也许您可以使用react-router
及其相对的basename
参数,它允许您从子目录中为您的应用程序提供服务。
basename
is the base URL for all locations. basename
是所有位置的基本 URL。 If your app is served from a sub-directory on your server, you'll want to set this to the sub-directory.如果您的应用程序是从服务器上的子目录提供的,您需要将其设置为子目录。 A properly formatted basename should have a leading slash, but no trailing slash.格式正确的基本名称应该有一个前导斜杠,但没有尾随斜杠。
For instance:例如:
<BrowserRouter basename="/calendar"/>
So <Link to="/today"/>
will render <a href="/calendar/today">
所以<Link to="/today"/>
将呈现<a href="/calendar/today">
See: https://reacttraining.com/react-router/web/api/BrowserRouter/basename-string请参阅: https ://reacttraining.com/react-router/web/api/BrowserRouter/basename-string
put in package.json something like this:在 package.json 中放入如下内容:
"homepage" : " http://localhost:3000/subfolder ", “主页”:“ http://localhost:3000/subfolder ”,
and work fine on any public or local server.并在任何公共或本地服务器上正常工作。 Of course, subfolder must be your folder.当然,子文件夹必须是您的文件夹。
In our case, we did everything as described in Ambroise's answer , but got a blank page in production with no errors or warnings in the console.在我们的例子中,我们按照Ambroise 的回答中的描述做了所有事情,但是在生产中得到了一个空白页面,在控制台中没有错误或警告。 It turned out to be a problem with BrowserRouter - we got it working by setting BrowserRouter's basename like so:原来是 BrowserRouter 的一个问题——我们通过设置 BrowserRouter 的基本名称来让它工作,如下所示:
<BrowserRouter basename="/our_subfolder/" />
You can specify the public path in your webpack configuration along with use of react route basepath.您可以在 webpack 配置中指定公共路径以及使用 react route basepath。
Link to Public Path: https://webpack.js.org/guides/public-path/公共路径链接: https ://webpack.js.org/guides/public-path/
Note that public path will be both leading and trailing slashes / to be valid.请注意,公共路径将同时是前导和尾随斜杠 / 才有效。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.