单页应用程序应该如何提供永久链接?

How should single page applications provide permalinks?

为通过单页应用程序管理的资源提供public可访问URL的约定是什么?我认为这是一个架构设计问题,但我预计会在 AngularJS 中开发一个 SPA,以防万一。我是 SPA 新手。

用户将通过 SPA 创建、查看和修改各种资源(例如基于服务器的对象)。一般 public 也可以通过 permalink URL 访问这些相同的资源。我同意 SPA 在访问资源的 permalink URL.

时为访问者显示资源

我只能想到这两种方法:

  1. 将所有资源放在 http://example.com/resourcetype/resourceID,在此处实现 RESTful API(改变 HTTP 方法)。
  2. 将所有 permalink 置于 http://example.com/resourcetype/resourceID 并使 SPA 命中 http://example.com/api/resourcetype/resourceID

(在/api下设置permalink似乎不​​合理。"permalink",我只是指public未登录URL 资源。)

我更希望通过 SPA 导航到资源的用户到达可共享的 URL,因为想要共享该页面的用户将首先考虑共享其 URL ,不要先找个link到permalink页面。这建议采用第一种方法,但第二种方法更适合通过 URL 对 API 进行版本控制,例如 /api/v1/api/v2

最好避免在 URL 中使用散列。我知道我可以在 AngularJS 中使用 HTML5 模式来在支持该模式的浏览器中隐藏它们。这也需要服务器端支持,我已经看到将深度 links 重写为 links 到 SPA 访问 URLs.

的解决方案

我想知道人们实际上在做什么,以及人们是否发现自己在实践中限制了 SPA 的使用。感谢您的帮助!

在我们的办公室,我们同时使用 resourceIdsslugs。任何可共享资源都将具有由资源模型的 属性 生成的 slug 属性。例如,任何为我们的 SPA 撰写文章的人都必须为文章命名。服务器在保存时验证该标题,以确保没有其他文章包含相同的标题。如果标题是唯一的,则为该资源生成一个 slug 并保存到我们的数据库中,否则服务器将响应一条错误消息,指出标题不是唯一的。

然后在我们的状态声明中,当用户访问 http://example/articles/article-slug 时,我们查询我们的 API 以查找匹配 article-slug 和 return 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 的一个众所周知但未充分传达的弱点。为了在我们的 Vue 应用程序中支持永久链接(和动态 URLs),我们使用 Web 服务器 URL 重写。我们创建了一个 Apache 重写规则,用于侦听特定 known/reserved 永久链接或动态 URL 模式,并使用自定义查询字符串参数将请求重写到 SPA 的唯一可行端点(即 /index.hml)引用所需的资源。

例如:

RewriteEngine On
RewriteRule ^somemodule/(.*?)$ /?somemodule= [R=301,L]

上面的规则侦听一个请求 URL 比如 mywebsite.com/somemodule/32 并将其重写为 mywebsite.com/{index.html}?somemodule=32

我们的 Vue 应用程序使用“中间件”组件检查所有请求,寻找我们保留的查询字符串参数匹配 ?somemodule=x。遇到这种情况时,它会将请求内部路由到正确的 component/module.

在 SPA 中处理永久链接和动态 URL 是一件非常麻烦的事情。希望上面的方法能提供一些额外的思考。