单页应用程序应该如何提供永久链接?
Posted
技术标签:
【中文标题】单页应用程序应该如何提供永久链接?【英文标题】:How should single page applications provide permalinks? 【发布时间】:2016-09-02 03:03:28 【问题描述】:为通过单页应用程序管理的资源提供可公开访问的 URL 的约定是什么?我认为这是一个架构设计问题,但我预计在 AngularJS 中开发一个 SPA,以防万一。我是 SPA 新手。
用户将通过 SPA 创建、查看和修改各种资源(例如基于服务器的对象)。公众也可以通过永久链接 URL 访问这些相同的资源。我对 SPA 在访问资源的永久链接 URL 时向访问者显示资源感到满意。
我只能想到这两种方法:
-
将所有资源放在
http://example.com/resourcetype/resourceID
,在此处实现 RESTful API(改变 HTTP 方法)。
将所有永久链接放在http://example.com/resourcetype/resourceID
并让SPA 点击http://example.com/api/resourcetype/resourceID
。
(在/api
下设置永久链接似乎不合理。“永久链接”是指资源的公共未登录 URL。)
我希望通过 SPA 导航到资源的用户到达可共享的 URL,因为想要共享该页面的用户会首先考虑共享其 URL,而不是首先找到指向永久链接的链接页。这建议使用第一种方法,但第二种方法更适合通过 URL 对 API 进行版本控制,例如 /api/v1
、/api/v2
等。
最好避免 URL 中的哈希值。我知道我可以在 AngularJS 中使用 html5 模式将它们隐藏在支持该模式的浏览器中。这也需要服务器端支持,我已经看到将深层链接重写为指向 SPA 访问 URL 的链接的解决方案。
我想知道人们实际在做什么,以及人们是否发现自己在实践中限制了 SPA 的使用。感谢您的帮助!
【问题讨论】:
此页面询问 AngularJS 是否仅适用于 SPA 提供了丰富的信息。它提到为不同的站点资源提供不同的 AngularJS 客户端。 ***.com/questions/15231251/… 这里有一个有用的讨论,关于 SPA 什么时候有帮助,什么时候没有。 news.ycombinator.com/item?id=9879685 【参考方案1】:这是所有 SPA 的一个很好理解但严重缺乏沟通的弱点。为了在我们的 Vue 应用程序中支持永久链接(和动态 URL),我们使用 Web 服务器 URL 重写。我们创建了一个 Apache 重写规则,用于侦听特定的已知/保留的永久链接或动态 URL 模式,并使用引用所需资源的自定义查询字符串参数将请求重写到 SPA 的唯一可行端点(即/index.hml
)。
例如:
RewriteEngine On
RewriteRule ^somemodule/(.*?)$ /?somemodule=$1 [R=301,L]
上面的规则监听mywebsite.com/somemodule/32
之类的请求URL,并将其重写为mywebsite.com/index.html?somemodule=32
我们的 Vue 应用程序使用“中间件”组件检查所有请求,寻找匹配 ?somemodule=x
的保留查询字符串参数。当它遇到这种情况时,它会在内部将请求路由到正确的组件/模块。
在 SPA 中处理永久链接和动态 URL 非常麻烦。希望上面的方法可以提供一些额外的思考。
【讨论】:
哎呀。我可以看到这会做到。我可能在 5.5 年前发布了这个问题,但我很快就会再次面临这个问题,所以您的回复很及时。非常感谢!【参考方案2】:在我们的办公室,我们同时使用resourceIds
和slugs
。任何可共享资源都将具有由资源模型的属性生成的slug
属性。例如,为我们的 SPA 撰写文章的任何人都必须为文章命名。该标题在保存时由服务器验证,以确保没有其他文章包含相同的标题。如果标题是唯一的,则会为该资源生成一个slug
并保存到我们的数据库中,否则服务器会响应一条错误消息,指出标题不是唯一的。
然后在我们的状态声明中,当用户访问 http://example/articles/article-slug
时,我们会查询我们的 API 以查找与 article-slug
匹配的文章,如果没有找到文章,则返回 404。
.state('app.articles.article',
url: '/:slug',
views:
articles:
templateUrl: tpl + 'views/frontend/articles.article.html',
controller: 'ArticleCtrl',
resolve:
article: ['$stateParams', function ($stateParams)
var slug = $stateParams.slug;
// query API for slug
]
)
【讨论】:
有趣。因此,当您的 SPA 生成新资源时,它会基于未针对资源类型的路径组件寻址的 slug 创建永久链接?这是否意味着每个资源都有两个访问点?两者都可以公开分享吗? 你给了我一个想法,虽然这个想法可能是你的意图。我可能能够通过仅使用 slug 而从不使用特定于资源类型的 ID 来缓解变化的永久链接问题。一个基本 URL 将是所有对象的单一访问点,并且导航到一个对象的用户甚至会从 SPA 到达这个永久链接 URL。 (除了这似乎是我的选项 1,SPA 在域根目录中,并且在 URL 中没有指示 API 版本。)以上是关于单页应用程序应该如何提供永久链接?的主要内容,如果未能解决你的问题,请参考以下文章