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

时间:2017-03-29 14:04:06

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

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

当我打开索引并浏览到/ 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 Bucket中使用路由规则解决问题。 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>

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

谢谢!

6 个答案:

答案 0 :(得分:19)

我知道这个答案来得很晚但是如果其他人正在寻找另一种方法来解决这个问题,那么在没有找到页面的情况下,不需要在s3重定向用户上创建自定义页面。可以在cloudfront中为分发创建自定义错误响应,而不是这样做。

Custom errors

如果找不到文件,这将始终重定向到/index.html,这将使应用路由触发。

答案 1 :(得分:3)

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

1

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

然而,这并不适用于像Cloudfront这样的CDN,而且可能是Cloudflare。

一个好方法是在S3中使用重定向用户的文件:

jobs / - &gt; /index.html 工作 - &gt; /index.html

例如,如果有人向网站发出请求/他们将获得以下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>"

...其次

  

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

这是我在路由器视图未正确初始化的问题,即使包含路由器视图的组件已加载。

我现在所做的是在主要&#34; App&#34;组件已创建:

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

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

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

答案 2 :(得分:3)

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

答案 3 :(得分:2)

我正在使用“静态网站托管”托管S3上Vue中制作的静态PWA,它可以正常工作。 我所做的非常简单-我添加了以下内容:

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

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

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

希望对您有帮助。

干杯, 亚历克斯

答案 4 :(得分:0)

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

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

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

请注意,步骤1和2的顺序很重要。 这可以通过发布您的网站的脚本轻松完成。 我只是将这种方法用于想要的结果。允许刷新页面并在新标签页中打开链接。

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

答案 5 :(得分:0)

所选答案(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