我正在本地计算机上创建一个单页面应用程序(SPA),但距文档根目录有几个级别。因此,例如,我的索引页面位于http://localhost/projects/foo/index.html
。
我使用Davis.js使用历史记录API进行客户端路由,并建议为其路由使用绝对URL。例如。 <a href="/hello/world">
会触发/hello/world
路线。
这是一个问题,因为当您点击http://localhost/projects/foo/index.html
上的该链接时,它会将网址更改为http://localhost/hello/world
,这显然不对,即使该应用继续正常进行(因为您从来没有真正离开过页面)。不过刷新页面,您会收到404错误,因为文件http://localhost/hello/world
不存在。
使用相对链接,如<a href="hello/world">
更接近标记。点击该链接会将网址更改为http://localhost/projects/foo/hello/world
,但不会触发/hello/world
路由。再次点击相同的链接,您将发现自己处于http://localhost/projects/foo/hello/hello/world
(双打招呼)。再次,不是理想的行为。
现在,正在进行的是戴维斯正在匹配来自域根的路由,因此/hello/world
只会在网址为http://somewhere.tld/hello/world
时触发。但即使我直接从文档根目录服务,仍然存在/hello/world
实际上不存在的问题。
目前,我目前的解决方案是强迫戴维斯使用基于散列的路由而不是基于路径的http://localhost/projects/foo/index.html#/hello/world
。这按预期工作100%,因为浏览器将始终加载index.html
,戴维斯将始终看到/hello/world
。此外,只要用户启用了Javascript,包含该哈希片段的链接将始终有效。 (我并不担心那种情况)
我可以看到的一个解决方案是使基本URL为http://localhost/projects/foo/
,让服务器将该目录中的所有请求重写为index.html
,并使所有链接和路由指向并匹配基本URL +片段(如http://localhost/projects/foo/hello/world
)。从技术上讲,所有这些网址做都存在,它们只是指向同一个文件。但是,这需要(a)能够进行URL重写的服务器为SPA服务(url-hash解决方案甚至不需要服务器,只需要浏览器)和 (b) SPA跟踪&#34;其中&#34;它是相对于文档根目录(对我来说是非常坏事)。
所以我的问题是,什么是正确方式进行客户端路由,与应用程序在服务器上的位置无关,最好不需要服务器端技术。静态托管。
答案 0 :(得分:1)
我在单页应用和客户端路由方面有过类似的经历。
在稍微考虑这个问题之后,我终于意识到,为了SEO的利益,你会想要让你的服务器在Davis建议的绝对网址上呈现内容。这样,Google抓取工具实际上可以继续抓取您的网站,就像它不是单页应用一样。
如果你说你不能做任何服务器端技术,那么问题就会困难得多。你提出的解决方案似乎都是合理的。
您可能还希望阅读此链接中的Google's specification for its crawler。
答案 1 :(得分:1)
我认为最好的方法是让您使用Davis定义的任何客户端路由也可以在服务器上使用。因此,如果您有/foo/bar
的客户端路由,那么理想情况下服务器应该能够明智地响应相同的路由。
这通常比听起来更简单,如果您使用的是语言无关的模板语言,例如小胡子,则不必涉及大量重复。
如果无法做到这一点,那么有一些解决方法,以便服务器为客户端路由返回404以外的其他内容。然而,这些总是感觉像是解决方法而不是我的解决方案。显然,答案取决于您正在构建的应用程序类型。
至于使用相对路线的戴维斯,我承认这是我从未使用过的东西,所以不能说它会得到多么好的支持。戴维斯的设计中没有任何特别的东西会妨碍它的运作。
然而,我刚刚在浏览器中使用了pushState api,它似乎与相对路径有些奇怪。