Vue.js 路由器:历史模式和 AWS S3 (RoutingRules)

Posted

技术标签:

【中文标题】Vue.js 路由器:历史模式和 AWS S3 (RoutingRules)【英文标题】:Vue.js Router: history mode and 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 将处理其余的 【参考方案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 的其他页面。

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

    将您的源代码构建到生产发行版中(例如,使用 npm run build) 确保为您的路由器链接创建每个路径的文件,该文件是原始文件的副本。在我提到的示例的情况下,它将创建 'dist/index.html' 到 'dist/page2.html' 的副本 将 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 || '/')

以上是关于Vue.js 路由器:历史模式和 AWS S3 (RoutingRules)的主要内容,如果未能解决你的问题,请参考以下文章

AWS Amplify 和 Vue 路由器历史模式

Vue 路由器和 Cordova (Vue.js)

Vue之路由

vue-router路由

Vue系列:Vue Router 路由梳理

Vue:vue-router路由