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.
的页面
那么您应该调整构建和部署过程以执行以下操作:
- 将您的源构建到生产发行版中(例如,使用
npm run build
)
- 确保为您的路由器链接创建每个路径的文件,该文件是原始文件的副本。在我提到的示例中,它将创建 'dist/index.html' 到 'dist/page2.html'
的副本
- 将 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
我有一个 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.
的页面那么您应该调整构建和部署过程以执行以下操作:
- 将您的源构建到生产发行版中(例如,使用
npm run build
) - 确保为您的路由器链接创建每个路径的文件,该文件是原始文件的副本。在我提到的示例中,它将创建 'dist/index.html' 到 'dist/page2.html' 的副本
- 将 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