【问题标题】:Vue.js Router: history mode and AWS S3 (RoutingRules)Vue.js 路由器:历史模式和 AWS S3 (RoutingRules)
【发布时间】:2017-08-23 01:51:45
【问题描述】:

我有一个使用 Amazon S3 和 Cloudflare 启动并运行的 Vue.js 应用程序。

当我打开索引并浏览到 /dashboard 时,一切正常。但是,当我直接在新选项卡中打开仪表板之类的路线或刷新页面时,我从 S3 收到以下错误:

404 Not Found

Code: NoSuchKey
Message: The specified key does not exist.
Key: unternehmen
RequestId: 6514F8A1F4C29235
HostId: +BVrPLJSGdzSYogzWZ4GMBXkgkdSJWRVJVhcSs4EI/lmMUR422aCtCxpBGU6AMe5VkS1UbEn/Lc=

刚刚看到问题出在 Vue.js 历史模式:https://router.vuejs.org/de/essentials/history-mode.html

我想通过我的 Amazon S3 存储桶中的路由规则来解决问题。 Apache RewriteRule 如何查找 S3?

<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteBase /
  RewriteRule ^index\.html$ - [L]
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteRule . /index.html [L]
</IfModule>

尝试了以下方法,但它不起作用:

<RoutingRules>
  <RoutingRule>
    <Condition>
      <HttpErrorCodeReturnedEquals>404</HttpErrorCodeReturnedEquals>
    </Condition>
    <Redirect>
      <HostName>domain.com</HostName>
      <ReplaceKeyWith>index.html</ReplaceKeyWith>
    </Redirect>
  </RoutingRule>
</RoutingRules>

如果我这样做,我只会渲染我的页眉和页脚,但仅此而已。

谢谢!

【问题讨论】:

  • 所以...你关闭了历史模式?
  • 是的,没有让它在 S3 和历史模式下工作。
  • @mrks 接受的答案 [S3 重定向] 是否适用于您的哈希模式?
  • 当您将 S3 存储桶设置为静态网站存储桶时,您有 2 个字段:索引文档和错误文档。你需要做的就是为 index 和 error 填充相同的值——“index.html”和 vue router 将处理其余的

标签: amazon-s3 vue.js vue-router s3-rewrite-rules


【解决方案1】:

所选答案(403 和 404)对我不起作用。
只有在我添加了类似的 400 规则之后,我的 VUE 应用才在历史模式下运行。

对于使用 AWS SAM 模板的任何人:

  CloudFront:
    Type: AWS::CloudFront::Distribution
    Properties:
      DistributionConfig:
        ...
        CustomErrorResponses:
          - ErrorCode: 404
            ResponseCode: 200
            ResponsePagePath: /index.html
          - ErrorCode: 403
            ResponseCode: 200
            ResponsePagePath: /index.html
          - ErrorCode: 400
            ResponseCode: 200
            ResponsePagePath: /index.html

【讨论】:

    【解决方案2】:

    如果您在 AWS S3 上使用静态托管并且这是 SPA 应用程序(React、Vue、Angular 等),您应该将 index.html 设置为错误页面:

    【讨论】:

      【解决方案3】:

      我知道这个答案来晚了,但如果其他人正在寻找另一种在云端解决此问题的方法,则无需在找不到页面时在 s3 上创建自定义页面重定向用户。可以在云端为分发创建自定义错误响应,而不是这样做。

      这将始终重定向到/index.html,以防找不到文件并触发应用程序路由。

      【讨论】:

      • 我在八月份使用了以下答案。现在 7 个月后,对于一个新应用程序有同样的问题,你的答案会更好。谢谢!
      • 这已经为我解决了,无需更改应用程序代码或向 S3 或任何内容添加任何重写规则。就这样,现在一切正常。
      • 如果我能对这个答案投票超过 100 倍。它还解决了我在使用 OAI 启用受限存储桶访问后遇到的默认目录问题;而不需要实现 ambda@Edge 重定向功能。
      • 这不是一个完全正确的答案,缓存会失效。 x-cache:来自云端的错误
      【解决方案4】:

      我正在使用“静态网站托管”在 S3 上托管 Vue 制作的静态 PWA,它按预期工作。 我所做的很简单——我添加了这个:

      <RoutingRules>
        <RoutingRule>
          <Condition>
            <HttpErrorCodeReturnedEquals>403</HttpErrorCodeReturnedEquals>
          </Condition>
          <Redirect>
            <ReplaceKeyWith></ReplaceKeyWith>
          </Redirect>
        </RoutingRule>
      </RoutingRules>
      

      到 S3 存储桶的属性。见下图:

      对于我的 S3 存储桶,每次您尝试访问不存在的文件时,您都会收到 403(禁止)而不是 404。这就是我将 HttpErrorCodeReturnedEquals 更改为 403 的原因。我也替换了ReplaceKeyWith 空字符串为“index.html”,因为没有触发正确的路由。

      希望对你有帮助。

      干杯, 亚历克斯

      【讨论】:

      • 如果您为 404 再添加一条路由规则,那么刷新 (F5) 也会正确处理
      • 新的 S3 控制面板只接受 JSON - 这里也添加 JSON 规则[{"Condition":{"HttpErrorCodeReturnedEquals":"403"},"Redirect":{"ReplaceKeyWith":""}}]
      【解决方案5】:

      在历史模式下使用路由而不使用 CloudFront 的一种方法是创建您的 URI 将指向的文件。因此,假设您使用 index.html 作为入口点,并且只有一个您提供路径 page2.html 的其他页面。

      然后您应该调整您的构建和部署过程以执行以下操作:

      1. 将您的源代码构建到生产发行版中(例如,使用 npm run build
      2. 确保为您的路由器链接创建每个路径的文件,该文件是原始文件的副本。在我提到的示例的情况下,它将创建 'dist/index.html' 到 'dist/page2.html' 的副本
      3. 将 dist 文件夹内容复制到您的 S3 存储桶

      请注意,第 1 步和第 2 步的顺序很重要。 这可以在发布您的网站的脚本中轻松完成。 我刚刚使用了这种方法,得到了我想要的结果;允许刷新页面并在新选项卡中打开链接。

      我看到的缺点是: - 存储文件副本的开销 - 必须确保添加页面时不要忘记更新构建和部署脚本。

      【讨论】:

        【解决方案6】:

        我认为这个问题有两个组成部分:

        1.

        如果直接(在 Javascript 应用程序之外)向 /jobs 等子路径发出请求,则 S3 将返回 404,因为路径/对象不存在。解决此问题的最简单方法是在 S3 内部,将所有错误页面重定向回 index.html。

        但是,这不适用于 Cloudfront 等 CDN,并且可能是 Cloudflare。

        一个很好的技巧是使用 S3 中的文件来重定向用户,如下所示:

        jobs/ -> /index.html 工作 -> /index.html

        例如,如果有人向 site/ 发出请求,他们将获得以下 html 文件:

        "redirect":"<html><head><meta http-equiv=\"refresh\" content=\"0; url=http://example.com/site/index.html\" /></head>
        <body>Redirecting to <a href=\"http://example.com/site/index.html\">Home</a></body></html>"
        

        其次...

        如果我这样做,我只会渲染我的页眉和页脚,但是 仅此而已。

        这是我遇到的一个问题,路由器视图没有正确初始化,即使包含路由器视图的组件已经加载。

        我现在所做的是在创建主“App”组件时重定向我的路由器:

        created () {
        console.log('route', this.$route.path)
        this.$router.replace(this.$route.query.redirect || '/')
        }
        

        这有一个额外的好处,即从你的路径中删除 index.html(这是你的新重定向放在那里的),同时强制你的路由器视图呈现......

        我的#app 组件是父组件,带有导航栏、页脚和渲染所有子页面/组件的路由器视图。

        【讨论】:

        • 注意:虽然这个答案被接受,但它doesn't work
        • 我能够让它工作实现这一行:this.$router.replace(this.$route.fullPath || '/')
        猜你喜欢
        • 2020-08-14
        • 2020-02-13
        • 2023-03-09
        • 1970-01-01
        • 2018-07-29
        • 2017-06-11
        • 2021-02-04
        • 1970-01-01
        • 2020-01-27
        相关资源
        最近更新 更多