Javascript 在单页应用程序上执行客户端路由的正确方法是什么?

Javascript 在单页应用程序上执行客户端路由的正确方法是什么?,javascript,html,url-routing,single-page-application,Javascript,Html,Url Routing,Single Page Application,我正在本地机器上创建一个单页应用程序(SPA),但要比文档根低几层。例如,我的索引页位于http://localhost/projects/foo/index.html 我使用history API进行客户端路由,它建议对路由使用绝对URL。例如,触发/hello/world路线 这是一个问题,因为当您单击http://localhost/projects/foo/index.html,它将URL更改为http://localhost/hello/world,这显然是不对的,即使应用程序继续正常

我正在本地机器上创建一个单页应用程序(SPA),但要比文档根低几层。例如,我的索引页位于
http://localhost/projects/foo/index.html

我使用history API进行客户端路由,它建议对路由使用绝对URL。例如,
触发
/hello/world
路线

这是一个问题,因为当您单击
http://localhost/projects/foo/index.html
,它将URL更改为
http://localhost/hello/world
,这显然是不对的,即使应用程序继续正常运行(因为你从未真正离开过页面)。不过,如果刷新页面,就会出现404错误,因为文件
http://localhost/hello/world
不存在

使用相对链接,如
更接近标记。单击该链接将URL更改为
http://localhost/projects/foo/hello/world
,但不会触发
/hello/world
路由。再次单击同一链接,您将在
http://localhost/projects/foo/hello/hello/world
(双重问候)。同样,这不是我们想要的行为

现在,Davis正在匹配来自域根目录的路由,因此只有当url为
时才会触发
/hello/world
http://somewhere.tld/hello/world
。但是,即使我直接从文档根目录中提供服务,仍然存在一个问题,
/hello/world
实际上并不存在

目前,我目前的解决方案是迫使Davis使用基于散列的路由而不是基于路径的路由:
http://localhost/projects/foo/index.html#/hello/world
。这与预期的效果完全一样,因为浏览器将始终加载
index.html
,Davis将始终看到
/hello/world
。此外,如果用户已打开Javascript,包含该哈希片段的链接将始终有效。(我不担心那件事)

我可以看到的一个解决方案是将基本URL设置为
http://localhost/projects/foo/
,让服务器将该目录中的所有请求重写为
index.html
,并让所有链接和路由指向并匹配基本url+片段(如
http://localhost/projects/foo/hello/world
)。所以从技术上讲,所有这些URL都存在,它们都指向同一个文件。然而,这需要(a)一个能够重写URL的服务器为SPA服务(URL哈希解决方案甚至不需要服务器,只需要一个浏览器)和(b)SPA跟踪它相对于文档根的“位置”(这对我来说是一件非常糟糕的事情)


因此,我的问题是,客户端路由的正确方法是什么,与应用程序在服务器上的位置无关,最好不需要服务器端技术(静态托管除外)。

我对单页应用程序和客户端路由也有类似的经验

在考虑了一下这个问题之后,我最终意识到,为了SEO的利益,您需要让您的服务器按照Davis建议的绝对URL呈现内容。这样,谷歌爬虫就可以继续在你的网站上爬行,就像它不是一个单页应用一样

如果你说你不能做任何服务器端技术,那么这个问题将更加困难。你提出的解决方案似乎都是合理的


您可能还希望在这个链接上阅读有关的内容。

我认为最好的方法是在服务器上提供您与Davis定义的任何客户端路由。因此,如果您的客户端路由是
/foo/bar
,那么服务器最好能够对相同的路由做出明智的响应

这通常比听起来更简单,如果您使用的是语言不可知的模板语言(如mustache),则不必涉及大量重复

如果这是不可能的,那么有一些变通方法,以便服务器返回404以外的内容,而不是仅用于客户端的路由。然而,对我来说,这些总是感觉像是解决办法,而不是解决办法。显然,答案取决于您正在构建的应用程序的类型

至于使用Davis与相对路线,我承认这是我从未使用过的,因此不能说它会得到多好的支持。戴维斯的设计中没有任何特别的东西会阻止它工作


不过,我只是在这里玩浏览器中的pushState api,它在相对路径方面似乎有些奇怪。

我不清楚您是在为您的开发环境寻找解决方案,还是应用程序真的会部署到具有这些路径的服务器上。@steveax-我正在寻找最佳的解决方法在SPA上执行客户端路由,不知道它在服务器上的位置,最好不需要服务器端的任何东西,除了静态托管。这似乎是所使用的库的特定特性。我对Davis.js不太熟悉,但快速看一下文档,您似乎可以使用它为您的应用程序预先设置一个全局路径。@steveax-这不是库的问题。追加全局/基本路径的问题是,现在应用程序需要知道它相对于文档根的位置。如果我移动应用程序,我需要更改代码。是的。应用程序!=一组链接的网页,它们通常位于文档根。