React构建在不在URL中添加index.html时无法正常工作[AWS S3和Cloudfront部署]

huangapple go评论63阅读模式
英文:

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 &#39;react&#39;;
import ReactDOM from &#39;react-dom&#39;;
import { Provider } from &#39;react-redux&#39;;
import store from &#39;./redux/store&#39;;
import App from &#39;./App&#39;;
import reportWebVitals from &#39;./reportWebVitals&#39;;
import { HashRouter } from &#39;react-router-dom/cjs/react-router-dom&#39;;

ReactDOM.render(
 &lt;Provider store={store}&gt;
    &lt;HashRouter&gt;
      &lt;App /&gt;
    &lt;/HashRouter&gt;
  &lt;/Provider&gt;

  document.getElementById(&#39;root&#39;)
);

Partial package.json content

{
  &quot;name&quot;: &quot;loremipsum&quot;,
  &quot;version&quot;: &quot;0.1.0&quot;,
  &quot;private&quot;: true,
  &quot;homepage&quot;: &quot;/loremipsum/&quot;
}

答案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.

{
  &quot;name&quot;: &quot;loremipsum&quot;,
  &quot;version&quot;: &quot;0.1.0&quot;,
  &quot;private&quot;: true,
  &quot;homepage&quot;: &quot;.&quot;,
  &quot;scripts&quot;: {
    &quot;build&quot;: &quot;react-scripts build&quot;,
    &quot;build-prd&quot;: &quot;PUBLIC_URL=http://www.foo/relativepath react-scripts build&quot;
    // ...
  }
}

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 &#39;aws-lambda&#39;;

const handler = async (event: any, context: Context) => {

    const request = event.Records[0].cf.request;
    const requestUri = request.uri.toLowerCase();

    const extensions = [
        &#39;.html&#39;,
        &#39;.js&#39;,
        &#39;.css&#39;,
        &#39;.ico&#39;,
    ];

    const knownExtension = extensions.find((ext) => {
        return requestUri.endsWith(`${ext}`);
    });

    if (knownExtension) {
        return request;
    }

    const demoAppBasePath = &#39;/demoapp/&#39;;
    if (requestUri.startsWith(demoAppBasePath)) {
        
        request.uri = `${demoAppBasePath}index.html`;
        return request;

    } else {

        request.uri = &#39;/index.html&#39;;
        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 &#39;aws-lambda&#39;;

const handler = async (event: any, context: Context) =&gt; {

    const request = event.Records[0].cf.request;
    const requestUri = request.uri.toLowerCase();

    const extensions = [
        &#39;.html&#39;,
        &#39;.js&#39;,
        &#39;.css&#39;,
        &#39;.ico&#39;,
    ];

    const knownExtension = extensions.find((ext) =&gt; {
        return requestUri.endsWith(`${ext}`);
    });

    if (knownExtension) {
        return request;
    }

    const demoAppBasePath = &#39;/demoapp/&#39;;
    if (requestUri.startsWith(demoAppBasePath)) {
        
        request.uri = `${demoAppBasePath}index.html`;
        return request;

    } else {

        request.uri = &#39;/index.html&#39;;
        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.

huangapple
  • 本文由 发表于 2023年6月26日 19:44:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/76556361.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定