nginx、prerender 和 angular 路由问题
nginx, prerender and angular routing issue
我正在开发动态 angular
网站(使用 html5mode
删除 #
)。它使用 Elasticsearch
获取一些数据并呈现内容。 nginx
负责映射到 Elasticsearch
和我的网站根目录。
为了让整个网站都具备 SEO 功能,我正在尝试使用本地实例 (http://localhost:3000
) 集成 prerender。
我拼命尝试将预渲染魔法与 nginx location /angular_test
结合使用。默认的 nginx prerender 中间件配置不适用于 location
s。在下面找到我的 nginx 配置:
upstream elasticsearch {
zone elasticsearch 64K;
server localhost:9200;
}
server {
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
server_name angular_test_server;
location /angular_test {
rewrite_log on;
error_log /var/log/nginx/localhost.error_log notice;
set $prerender 0;
if ($http_user_agent ~* "baiduspider|twitterbot|facebookexternalhit|rogerbot|linkedinbot|embedly|quora link preview|showyoubot|outbrain|pinterest|slackbot|vkShare|W3C_Validator") {
set $prerender 1;
}
if ($args ~ "_escaped_fragment_") {
set $prerender 1;
}
if ($http_user_agent ~ "Prerender") {
set $prerender 0;
}
if ($uri ~ "\.(js|css|xml|less|png|jpg|jpeg|gif|pdf|doc|txt|ico|rss|zip|mp3|rar|exe|wmv|doc|avi|ppt|mpg|mpeg|tif|wav|mov|psd|ai|xls|mp4|m4a|swf|dat|dmg|iso|flv|m4v|torrent|ttf|woff)") {
set $prerender 0;
}
if ($prerender = 1) {
rewrite .* /$scheme://$host$request_uri?;
proxy_pass http://localhost:3000;
break;
}
# support html5mode of angular (fallback to index.html and let angular do the routing)
try_files $uri $uri/ /angular_test/index.html;
}
location /es/ {
rewrite /es/(.*) / break;
proxy_pass http://elasticsearch;
proxy_redirect http://elasticsearch /es/;
}
}
当我访问 http://localhost/angular_test/search?_escaped_fragment_= I get a 404 because nginx tries to load the file /var/html/www/angular_test/search
. This should be covered by angulars routing (see try_files doing a try on the index.html). http://localhost/angular_test?_escaped_fragment_= 时工作正常
当我使用类似下面的东西时(如这里https://gist.github.com/thoop/8165802所提议的),它甚至没有进入 @prerender
位置部分。
location /angular_test {
# support html5mode of angular (fallback to index.html and let angular do the routing)
try_files $uri $uri/ /angular_test/index.html @prerender;
}
有什么方法可以得到这个设置 运行 prerender
?感觉这里nginx的使用方式不对...
我想出了解决办法。 If is really evil 在 nginx 位置!
当 if(...)
逻辑移出 location
并移至 server
时它起作用。这是我的最终配置:
upstream elasticsearch {
zone elasticsearch 64K;
server localhost:9200;
}
server {
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
server_name angular_test_server;
set $prerender 0;
if ($http_user_agent ~* "baiduspider|twitterbot|facebookexternalhit|rogerbot|linkedinbot|embedly|quora link preview|showyoubot|outbrain|pinterest|slackbot|vkShare|W3C_Validator") {
set $prerender 1;
}
if ($args ~ "_escaped_fragment_") {
set $prerender 1;
}
if ($http_user_agent ~ "Prerender") {
set $prerender 0;
}
if ($uri ~ "\.(js|css|xml|less|png|jpg|jpeg|gif|pdf|doc|txt|ico|rss|zip|mp3|rar|exe|wmv|doc|avi|ppt|mpg|mpeg|tif|wav|mov|psd|ai|xls|mp4|m4a|swf|dat|dmg|iso|flv|m4v|torrent|ttf|woff)") {
set $prerender 0;
}
location /angular_test {
rewrite_log on;
error_log /var/log/nginx/localhost.error_log notice;
#resolve using Google's DNS server to force DNS resolution and prevent caching of IPs
resolver 8.8.8.8;
if ($prerender = 1) {
#setting prerender as a variable forces DNS resolution since nginx caches IPs and doesnt play well with load balancing
#set $prerender "$host:3000";
rewrite .* /$scheme://$host$request_uri? break;
proxy_pass http://localhost:3000;
}
# support html5mode of angular (fallback to index.html and let angular do the routing)
try_files $uri $uri/ /angular_test/index.html;
}
location /es/ {
rewrite /es/(.*) / break;
proxy_pass http://elasticsearch;
proxy_redirect http://elasticsearch /es/;
}
}
我正在开发动态 angular
网站(使用 html5mode
删除 #
)。它使用 Elasticsearch
获取一些数据并呈现内容。 nginx
负责映射到 Elasticsearch
和我的网站根目录。
为了让整个网站都具备 SEO 功能,我正在尝试使用本地实例 (http://localhost:3000
) 集成 prerender。
我拼命尝试将预渲染魔法与 nginx location /angular_test
结合使用。默认的 nginx prerender 中间件配置不适用于 location
s。在下面找到我的 nginx 配置:
upstream elasticsearch {
zone elasticsearch 64K;
server localhost:9200;
}
server {
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
server_name angular_test_server;
location /angular_test {
rewrite_log on;
error_log /var/log/nginx/localhost.error_log notice;
set $prerender 0;
if ($http_user_agent ~* "baiduspider|twitterbot|facebookexternalhit|rogerbot|linkedinbot|embedly|quora link preview|showyoubot|outbrain|pinterest|slackbot|vkShare|W3C_Validator") {
set $prerender 1;
}
if ($args ~ "_escaped_fragment_") {
set $prerender 1;
}
if ($http_user_agent ~ "Prerender") {
set $prerender 0;
}
if ($uri ~ "\.(js|css|xml|less|png|jpg|jpeg|gif|pdf|doc|txt|ico|rss|zip|mp3|rar|exe|wmv|doc|avi|ppt|mpg|mpeg|tif|wav|mov|psd|ai|xls|mp4|m4a|swf|dat|dmg|iso|flv|m4v|torrent|ttf|woff)") {
set $prerender 0;
}
if ($prerender = 1) {
rewrite .* /$scheme://$host$request_uri?;
proxy_pass http://localhost:3000;
break;
}
# support html5mode of angular (fallback to index.html and let angular do the routing)
try_files $uri $uri/ /angular_test/index.html;
}
location /es/ {
rewrite /es/(.*) / break;
proxy_pass http://elasticsearch;
proxy_redirect http://elasticsearch /es/;
}
}
当我访问 http://localhost/angular_test/search?_escaped_fragment_= I get a 404 because nginx tries to load the file /var/html/www/angular_test/search
. This should be covered by angulars routing (see try_files doing a try on the index.html). http://localhost/angular_test?_escaped_fragment_= 时工作正常
当我使用类似下面的东西时(如这里https://gist.github.com/thoop/8165802所提议的),它甚至没有进入 @prerender
位置部分。
location /angular_test {
# support html5mode of angular (fallback to index.html and let angular do the routing)
try_files $uri $uri/ /angular_test/index.html @prerender;
}
有什么方法可以得到这个设置 运行 prerender
?感觉这里nginx的使用方式不对...
我想出了解决办法。 If is really evil 在 nginx 位置!
当 if(...)
逻辑移出 location
并移至 server
时它起作用。这是我的最终配置:
upstream elasticsearch {
zone elasticsearch 64K;
server localhost:9200;
}
server {
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
server_name angular_test_server;
set $prerender 0;
if ($http_user_agent ~* "baiduspider|twitterbot|facebookexternalhit|rogerbot|linkedinbot|embedly|quora link preview|showyoubot|outbrain|pinterest|slackbot|vkShare|W3C_Validator") {
set $prerender 1;
}
if ($args ~ "_escaped_fragment_") {
set $prerender 1;
}
if ($http_user_agent ~ "Prerender") {
set $prerender 0;
}
if ($uri ~ "\.(js|css|xml|less|png|jpg|jpeg|gif|pdf|doc|txt|ico|rss|zip|mp3|rar|exe|wmv|doc|avi|ppt|mpg|mpeg|tif|wav|mov|psd|ai|xls|mp4|m4a|swf|dat|dmg|iso|flv|m4v|torrent|ttf|woff)") {
set $prerender 0;
}
location /angular_test {
rewrite_log on;
error_log /var/log/nginx/localhost.error_log notice;
#resolve using Google's DNS server to force DNS resolution and prevent caching of IPs
resolver 8.8.8.8;
if ($prerender = 1) {
#setting prerender as a variable forces DNS resolution since nginx caches IPs and doesnt play well with load balancing
#set $prerender "$host:3000";
rewrite .* /$scheme://$host$request_uri? break;
proxy_pass http://localhost:3000;
}
# support html5mode of angular (fallback to index.html and let angular do the routing)
try_files $uri $uri/ /angular_test/index.html;
}
location /es/ {
rewrite /es/(.*) / break;
proxy_pass http://elasticsearch;
proxy_redirect http://elasticsearch /es/;
}
}