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)的主要内容,如果未能解决你的问题,请参考以下文章