英文:
React build not working without adding index.html in URL [AWS S3 and Cloudfront deployment]
问题
I am working with React JS application using Hash Routing. On local environment app is working fine.
例如:https://stackoverflow.com/posts/ 应该是应用程序的URL,但它不起作用,我必须使用https://stackoverflow.com/posts/index.html来使其工作。
部署后,我发现它下载了一个名为“download”的空文件,而不是提供构建文件中预设的“index.html”文件。在服务器上运行构建时,我使用S3和CloudFront架构。
现在,我处于一个无法确定HASH路由是否行为不当还是AWS部署存在问题的情况。
React JS的代码片段
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import store from './redux/store';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { HashRouter } from 'react-router-dom/cjs/react-router-dom';
ReactDOM.render(
<Provider store={store}>
<HashRouter>
<App />
</HashRouter>
</Provider>,
document.getElementById('root')
);
部分package.json内容
{
"name": "loremipsum",
"version": "0.1.0",
"private": true,
"homepage": "/loremipsum/"
}
英文:
I am working with React JS application using Hash Routing. On local environment app is working fine.
e.g. https://stackoverflow.com/posts/ should be the URL of application but it is not working and I have to use https://stackoverflow.com/posts/index.html to make it working.
After deployment, I found that it is downloading with name "download" empty file instead of serving index.html file preset in build file. For running build on server I am using S3 and CloudFront architecture.
Now, I am in a situation where I cannot be able to figure out whether HASH routing is behaving wrong or something wrong with AWS deployment.
Code snippet with React JS
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import store from './redux/store';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { HashRouter } from 'react-router-dom/cjs/react-router-dom';
ReactDOM.render(
<Provider store={store}>
<HashRouter>
<App />
</HashRouter>
</Provider>
document.getElementById('root')
);
Partial package.json content
{
"name": "loremipsum",
"version": "0.1.0",
"private": true,
"homepage": "/loremipsum/"
}
答案1
得分: 1
你需要部署在子目录吗?如果是的话,你将需要更改你的 package.json
文件的内容,以强制资源相对于 index.html
文件进行提供。
{
"name": "loremipsum",
"version": "0.1.0",
"private": true,
"homepage": ".",
"scripts": {
"build": "react-scripts build",
"build-prd": "PUBLIC_URL=http://www.foo/relativepath react-scripts build"
// ...
}
}
有了这个配置,我们就可以将我们的应用从 http://www.foo
移动到 http://www.foo/relativepath
,甚至是 https://www.foo/bar1/bar2/
,而无需重新构建。
你还需要覆盖 PUBLIC_URL
以包括你想要托管文件的域和子目录。
英文:
Are you required to deploy on a subdirectory? If yes, you will have to change the contents of your package.json
file to force assets to be served relative to index.html
file.
{
"name": "loremipsum",
"version": "0.1.0",
"private": true,
"homepage": ".",
"scripts": {
"build": "react-scripts build",
"build-prd": "PUBLIC_URL=http://www.foo/relativepath react-scripts build"
// ...
}
}
With this, we'll be able to move our app's hosted in http://www.foo
to http://www.foo/relativepath
or even https://www.foo/bar1/bar2/
without the need for rebuilds.
You will also have to override the PUBLIC_URL
to include the domain and subdirectory where you'd like to host your file
答案2
得分: 1
以下是您提供的内容的中文翻译:
有时静态内容的开发处理(例如 webpack dev server)和部署系统(例如 cloudfront)的行为会有些不同。
在AWS中控制这一点的方法是使用 Lambda Edge 函数,该函数控制路径的解释方式和默认文档的提供方式。我的博客文章提供了一个摘要,而这段代码展示了处理子路径的一种方式:
import { Context } from 'aws-lambda';
const handler = async (event: any, context: Context) => {
const request = event.Records[0].cf.request;
const requestUri = request.uri.toLowerCase();
const extensions = [
'.html',
'.js',
'.css',
'.ico',
];
const knownExtension = extensions.find((ext) => {
return requestUri.endsWith(`${ext}`);
});
if (knownExtension) {
return request;
}
const demoAppBasePath = '/demoapp/';
if (requestUri.startsWith(demoAppBasePath)) {
request.uri = `${demoAppBasePath}index.html`;
return request;
} else {
request.uri = '/index.html';
return request;
};
};
export { handler };
请注意,这是您提供的文本的中文翻译部分。如果您需要进一步的帮助,请告诉我。
英文:
Sonetimes the development processing of static content (eg webpack dev server) and the deployed system (eg cloudfront) behave a little differently.
The way to control this in AWS is to use a lambda edge function that controls how paths are interpreted and the default document served. My blog post provides a summary, and this code shows one way of dealing with subpaths:
import {Context} from 'aws-lambda';
const handler = async (event: any, context: Context) => {
const request = event.Records[0].cf.request;
const requestUri = request.uri.toLowerCase();
const extensions = [
'.html',
'.js',
'.css',
'.ico',
];
const knownExtension = extensions.find((ext) => {
return requestUri.endsWith(`${ext}`);
});
if (knownExtension) {
return request;
}
const demoAppBasePath = '/demoapp/';
if (requestUri.startsWith(demoAppBasePath)) {
request.uri = `${demoAppBasePath}index.html`;
return request;
} else {
request.uri = '/index.html';
return request;
};
};
export {handler};
答案3
得分: 1
在运行npm run build之前,您尝试编辑package.json文件,以使homepage变量具有您的AWS托管站点的完整URL吗?
"homepage": "yourAWSurlexample.com"
我在AWS Amplify上遇到了类似的部署问题,将package中的homepage更改后问题得以解决。
在更新package后,创建一个构建,然后尝试重新推送到AWS。
如果这不起作用,AWS Amplify有一个非常简单的设置。我不确定它是否符合您的需求,但它设置和部署非常迅速。
英文:
Before running npm run build have you tried to edit the package.json file so that the homepage variable has the full URL of your aws hosting site.
"homepage": "yourAWSurlexample.com"
I had trouble with a deployment like this on AWS Amplify and changing the homepage in the package fixed it for me.
After updating the package, create a build and then try to re-push it into AWS.
If this doesn't work AWS Amplify has a really easy setup. I'm not sure if it would meet your needs but it is really quick to setup and deploy on.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论