我正在我的本地机器上创建一个单页应用程序 (SPA),但在文档根目录下几个级别。因此,例如,我的索引页将位于http://localhost/projects/foo/index.html
.
我正在使用Davis.js通过历史 API 进行客户端路由,它建议对其路由使用绝对 URL。例如<a href="/hello/world">
触发/hello/world
路由。
这是一个问题,因为当您单击位于 上的链接时http://localhost/projects/foo/index.html
,它会将 URL 更改为http://localhost/hello/world
,这显然是不正确的,即使应用程序继续正常运行(因为您实际上从未离开过该页面)。但是,刷新页面,您将收到 404 错误,因为该文件http://localhost/hello/world
不存在。
使用相对链接,like<a href="hello/world">
更接近标记。单击该链接会将 URL 更改为http://localhost/projects/foo/hello/world
,但不会触发路由/hello/world
。再次单击相同的链接,您会发现自己位于http://localhost/projects/foo/hello/hello/world
(double hello)。同样,不是理想的行为。
现在,Davis 正在匹配来自域根的路由,所以/hello/world
只会在 url 为http://somewhere.tld/hello/world
. 但即使我直接从文档根目录中提供服务,仍然/hello/world
存在实际不存在的问题。
目前,我当前的解决方案是强制 Davis 使用基于哈希的路由而不是基于路径:http://localhost/projects/foo/index.html#/hello/world
. 这可以 100% 正常工作,因为浏览器将始终加载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-hash 解决方案甚至不需要服务器,只需要一个浏览器)和(b) SPA 跟踪它的“位置”是相对于文档根目录的(这对我来说是一件非常糟糕的事情)。
所以我的问题是,做客户端路由的正确方法是什么,与应用程序在服务器上的位置无关,最好不需要静态托管以外的服务器端技术。