英文:
How to deploy a build react app in your existing Laravel site as subdomain?
问题
npm run build
我构建了一个简单的React应用;这是我在build/
文件夹中看到的内容
jdoe@AIR ~/Sites/react/alphabets/build main ± tree
.
├── asset-manifest.json
├── favicon.png
├── index.html
└── static
├── css
│ ├── main.f05a5dc1.css
│ └── main.f05a5dc1.css.map
└── js
├── main.cec1e2e8.js
├── main.cec1e2e8.js.LICENSE.txt
└── main.cec1e2e8.js.map
4 directories, 8 files
由于我还有一个部署的Laravel站点。
我以为我可以将它放入我的public/
目录并像这样导航到它。
https://www.bunlongheng.com/react/alphabets/
我尝试将我的build/
文件夹上传到服务器的public/react/alphabets/build
目录。
当我访问它时,我看到没有错误,没有禁止访问,但是是一个白屏。
我需要一种尽可能简单地部署React项目的方式,因为我的目标是部署多个...例如:
mysite/react/first-project
mysite/react/second-project
mysite/react/third-project
mysite/react/forth-project
等等...
对我有什么提示吗?我知道我离成功很近。
英文:
npm run build
I build a simple react app; this is what I see in build/
folder
jdoe@AIR ~/Sites/react/alphabets/build main ± tree
.
├── asset-manifest.json
├── favicon.png
├── index.html
└── static
├── css
│   ├── main.f05a5dc1.css
│   └── main.f05a5dc1.css.map
└── js
├── main.cec1e2e8.js
├── main.cec1e2e8.js.LICENSE.txt
└── main.cec1e2e8.js.map
4 directories, 8 files
Since
I also have a Laravel site that I deployed.
I thought I could drop it in my `public/ and navigate to it like so.
https://www.bunlongheng.com/react/alphabets/
I tried SCP my build/
it to public/react/alphabets/build
in my server.
When I go to it, I see no error, no forbidden, but a white screen.
I need a way to deploy react projects as simply as possible since my goal is to deploy more than one... ex.
mysite/react/first-project
mysite/react/second-project
mysite/react/third-project
mysite/react/forth-project
and so on...
& leave my main site as it...
Any hints for me ? I know I am close.
答案1
得分: 1
你的标题说作为子域名,但你的示例URL是子目录/子文件夹。所以我认为你的意思是如何将React应用程序构建为子目录。
空白页面意味着资源未加载,因为资源路径使用了根路径(/
)。要更改基本路径,你只需在路由器中添加 basename
:
<Router basename={'/react/alphabets/build'}>
<Route path='/' component={Home} />
</Router>
还需要在 package.json
中添加 homepage
。例如:
{
"name": "react-example",
"homepage": "/react/alphabets/build",
}
或者另一种方法是将public/react/alphabets/build/static
移动/复制到 public/static/
。
英文:
Your title said as subdomain, but your example URLs are subdirectory/subfolder. So I assume you meant how to build react app as subdirectory.
the blank page mean the resource is not loaded because the resource path is using root path(/
). To change the base path, you just need to add basename
to your router :
<Router basename={'/react/alphabets/build'}>
<Route path='/' component={Home} />
</Router>
and also you need to add homepage
to package.json. example:
{
"name": "react-example",
"homepage": "/react/alphabets/build",
or another way you need to move/copy public/react/alphabets/build/static
to public/static/
答案2
得分: 1
如果你想要一个子域名(例如https://alphabets.bunlongheng.com
),你需要编辑路由模块,因为所有的SPA都在根目录上工作得很好。
如果你想要在你的域名下创建一个路由(例如https://alphabets.bunlongheng.com/react/alphabets
),在Laravel方面更容易,因为你只需要复制构建内容,但你需要覆盖默认的假设,即你的应用程序是在不同级别的服务器根目录上托管的:模块绑定器和客户端路由。
模块绑定器
我个人在我的项目中使用 https://vitejs.dev/,但一个非常流行的绑定器是 https://create-react-app.dev/。
这个绑定器链接文件时会引用根目录!!
访问 https://www.bunlongheng.com/react/alphabets/
并打开开发工具,我们可以在控制台错误中看到网页正在搜索 https://www.bunlongheng.com/static/css/main.f05a5dc1.css
,但该文件实际上位于 https://www.bunlongheng.com/react/alphabets/static/css/main.f05a5dc1.css
。
请查阅你的绑定器文档以修复此问题。如果你使用的是 CRA,这是关于绝对和相对引用的文档。
客户端路由
如果你的下一个项目将使用像 React Router 这样的客户端路由,你需要在客户端路由上配置一个基准路径文档。
英文:
If you want a subdomain (ex https://alphabets.bunlongheng.com
) you need to edit routing module, all SPA is working fine becouse you are working on the root.
If you want a route into your domain (ex https://alphabets.bunlongheng.com/react/alphabets
) is easier on Lavarel side because you just need to copy build content, but you need to override the default assumption that your app is hosted at the server root at different level: module bundler and client side routing.
Module Bundler
I personally use https://vitejs.dev/ in my projects but a very popular bundler is https://create-react-app.dev/.
The bundler links file referring to the root!!
Visiting https://www.bunlongheng.com/react/alphabets/
and opening the dev tools we can see on console errors that the webpage is searching for https://www.bunlongheng.com/static/css/main.f05a5dc1.css
but the file is on https://www.bunlongheng.com/react/alphabets/static/css/main.f05a5dc1.css
Please check your bundler documentation to fix this. If you are using CRA this is the docs for absolute and relative reference.
Client side routing
If your next project will use a client side routing like react router, you will need to configure a basename on client router docs
答案3
得分: 1
以下是您要翻译的内容:
确保在您的 package.json
中如下所示:
// package.json
{
"name": "alphabets",
"homepage": "alphabets",
// ....
}
注意:使用 sed 自动更新主页。
- 在项目根目录(即 package.json 所在位置)创建一个名为
.env
的文件,并在该文件中写入以下内容:
REACT_APP_BASENAME=react/alphabets
注意:最好使用 cross-env 或其他替代方法(dotenv ...)来进行构建处理。
将
REACT_APP_BASENAME=
设置为空值,或者删除homepage
,或者将其设置为/
,如果您想在本地主机上运行。
- 更新您的
BrowserRouter
以解决白屏问题,按照以下方式操作:
import React from "react";
import { BrowserRouter } from "react-router-dom";
const baseName = process.env.REACT_APP_BASENAME ?? "";
const App: React.FC<> = () => {
return (
<>
<BrowserRouter basename={baseName}>
....
</BrowserRouter>
</>
);
}
export default App;
- 将构建文件移动到:
mv ~/Sites/react/alphabets/build/* ~/Sites/react/alphabets/
英文:
Make sure in ur package.json
like:
// package.json
{
"name": "alphabets",
"homepage": "alphabets",
....
}
> Note: Use sed to update homepage automatically.
- Create a file called
.env
at your project root (where package.json is located),
and write in this file:
REACT_APP_BASENAME=react/alphabets
> Note: is better to use cross-env or any other alt (dotenv ...) on your build proccess.
> Put empty value for REACT_APP_BASENAME=
and remove homepage
or put /
if you want to run on localhost.
- Update your
BrowserRouter
to fix white screen issue, follow:
import React from "react";
import { BrowserRouter } from "react-router-dom";
const baseName = process.env.REACT_APP_BASENAME ?? "";
const App: React.FC<> = () => {
return (
<>
<BrowserRouter basename={baseName}>
....
</BrowserRouter>
</>
);
}
export default App;
- Move build files to:
mv ~/Sites/react/alphabets/build/* ~/Sites/react/alphabets/
答案4
得分: 1
HTML标准将允许您在Laravel或任何其他提供商上实现所需的静态托管行为。
INDEX.HTML
首先添加一个像这样的base
元素。默认情况下将其设置为/
,或者在部署时将其设置为像/spa/
这样的值:
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='utf-8'>
<meta name='viewport' content='width=device-width, initial-scale=1, shrink-to-fit=no'>
<base href='/spa/' />
<title>Demo App</title>
<link rel='stylesheet' href='bootstrap.min.css'>
<link rel='stylesheet' href='app.css'>
</head>
<body>
<div id='root' class='container'></div>
<script type='module' src='vendor.bundle.js'></script>
<script type='module' src='app.bundle.js'></script>
</body>
</html>
REACT
React对基于路径的路由提供了很好的支持,正如上面也提到的。当React应用程序启动时,您可以从index.html的运行时值初始化React路由:
const props = {
viewModel: new AppViewModel(),
};
const baseElement = document.querySelector('base') as HTMLElement;
const base = baseElement?.getAttribute('href') || '/';
const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement);
root.render (
<ErrorBoundary>
<BrowserRouter basename={base}>
<App {...props} />
</BrowserRouter>
</ErrorBoundary>
);
然后,您可以像这样定义路由,您的代码无需意识到完整的URL形式为/spa/products
:
<Routes>
<Route path='/products/:id' element={<ProductsView {...productsProps} />} />
<Route path='/*' element={<HomeView {...homeProps} />} />
</Routes>
然后,您可以使用其他React导航功能,例如以下方式,以从子文件夹开始的路径:
import {useNavigate, useLocation} from 'react-router-dom';
const navigate = useNavigate();
const currentPath = useLocation().pathname;
navigate("/products");
<Link to="/products">View Products</Link>
部署
您只需在部署步骤中编辑index.html
。如果需要,可以通过一些脚本来自动化此过程:
const oldData = fs.readFileSync('index.html', 'utf8');
var regex = new RegExp("href='/'", 'g');
const newData = oldData.replace(regex, "href='/spa/'");
fs.writeFileSync('index.html', newData, 'utf8');
我的演示SPA使用上述技术,我通过将静态内容放入AWS Cloudfront或基于Docker的环境中进行部署。它也可以在Laravel上运行。
英文:
The HTML standards will enable the static hosting behavior you want, on Laravel or any other provider.
INDEX.HTML
First add a base
element like this. Set it to /
by default, or set it to a value like /spa/
when deployed:
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='utf-8'>
<meta name='viewport' content='width=device-width, initial-scale=1, shrink-to-fit=no'>
<base href='/spa/' />
<title>Demo App</title>
<link rel='stylesheet' href='bootstrap.min.css'>
<link rel='stylesheet' href='app.css'>
</head>
<body>
<div id='root' class='container'></div>
<script type='module' src='vendor.bundle.js'></script>
<script type='module' src='app.bundle.js'></script>
</body>
</html>
REACT
React has some nice support for path based routing, as selllami also pointed out above. When the React app starts, you can initialize React routes from the index.html runtime value:
const props = {
viewModel: new AppViewModel(),
};
const baseElement = document.querySelector('base') as HTMLElement;
const base = baseElement?.getAttribute('href') || '/';
const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement);
root.render (
<ErrorBoundary>
<BrowserRouter basename={base}>
<App {...props} />
</BrowserRouter>
</ErrorBoundary>
);
You can then define routes like this, and your code needs no awareness that the full URLs are of the form /spa/products
:
<Routes>
<Route path='/products/:id' element={<ProductsView {...productsProps} />} />
<Route path='/*' element={<HomeView {...homeProps} />} />
</Routes>
You can then use other React navigation features, such as these, with paths beginning from the subfolder:
import {useNavigate, useLocation} from 'react-router-dom';
const navigate = useNavigate();
const currentPath = useLocation().pathname;
navigate("/products");
<Link to="/products">View Products</Link>
DEPLOYMENT
You just need to edit the index.html
as part of a deployment step. This can be automated by some script if required:
const oldData = fs.readFileSync('index.html', 'utf8');
var regex = new RegExp("href='/'", 'g');
const newData = oldData.replace(regex, "href='/spa/'");
fs.writeFileSync('index.html', newData, 'utf8');
My demo SPA uses the above techniques, and I deploy it by dropping static content into either AWS Cloudfront or Docker based environments. It would also work on Laravel.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论