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

Vue.js Router: history mode and AWS S3 (RoutingRules)

我有一个 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 存储桶中的路由规则解决问题。 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>

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

谢谢!

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

1.

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

然而,这不适用于 Cloudfront 和 Cloudflare 等 CDN。

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

工作/ -> /index.html 工作 -> /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>"

其次...

If I do it like that I just get my Header and Footer rendered but nothing more.

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

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

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

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

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

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

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

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

的页面

那么您应该调整构建和部署过程以执行以下操作:

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

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

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

我正在使用 "Static website hosting" 在 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" 因为没有触发正确的路由。

希望对您有所帮助。

干杯, 亚历克斯

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

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