现代的浏览器已经支持HTML5的history.pushState,一种支持改变浏览器地址栏和历史而不发送实际服务器请求的技术。
记得以前的SPA(Single Page Application)应用是怎么做的么?在angular1里面,你会看到类似下面的地址:
http://localhost:8000/home/#/login
这里用了标记#来告诉浏览器,我这个不是真实的地址,不要试图去服务器上查这个请求。
现在我们不需要这么做了,使用HTML5支持的浏览器,直接地址栏里面看到的结果就是:
http://localhost:8000/home/login
是不是很赞?so far so good,直到你在你的nodejs服务器前面加了nginx。。。
一开始,看起来所有的东西都work,你的nginx配置可能如下:
server {
listen 80 default_server;
server_name your.server.com;
root /root/www;
error_page 404 /404.html;
error_page 500 502 503 504 /500.html;
location / {
index index.html;
}
}
然而,当你打开页面并f5刷新的时候,你会得到一个大大的404错误。
为什么?因为nginx根据你的请求地址去找相应的页面了!!!结果当然是没找到!!!
通过一番google,你可能找到下面的解决方案,把所有未找到的页面重定向到index.html
server {
listen 80 default_server;
server_name your.server.com;
root /root/www;
error_page 404 /404.html;
error_page 500 502 503 504 /500.html;
location / {
index index.html;
try_files $uri$args $uri$args/ $uri/ index.html =404;
}
}
中间多出来的那段try-files
告诉nginx,把所有找不到的请求都重定向发到index.html上去。
恩,你又试了试,看起来f5没有问题了。
但是,当你尝试输入一个不存在的地址http://localhost:8000/notexist
的时候,你发现404页面没有出现,index.html还是被load了!!!(当然路由不存在,你会看到一个白的页面,但是所有index页面的代码还是被load了)
这是你要的结果么?可能有些网站希望这样,永远不会有40x和50x错误。但是如果我需要有404呢?看看刚才的配置,和404页面是有冲突的,你不能一边告诉nginx把所有找不到的页面重定向到index,又希望把不存在的页面跳转到404页面!
刚才配置里面最后的=404其实是永远到不了的,因为你的index.html页面一直存在!!!
怎么办?想了很久,我只能用一个workaround来部分解决这个,nignix的配置文件如下:
server {
listen 80 default_server;
server_name your.server.com;
root /root/www;
error_page 404 /404.html;
error_page 500 502 503 504 /500.html;
location / {
index app/index.html;
}
location /app {
try_files $uri$args $uri$args/ $uri/ /app/index.html =404;
}
}
然后移动并修改index.html,把里面的<base href="/">
改成<base href="/app">
。
简单解释下,通过把index.html移动到app目录下,我给所有的虚拟请求建立了一个壳/app/**
,所有app开头的请求,我都认为是angular2的虚拟请求,重定向到index去处理。其他的所有请求,如果不是一个真实存在的文件,都会跳到404页面。