angularjs - nginx、预渲染和 Angular 路由问题

标签 angularjs nginx seo prerender

我正在开发一个动态的angular 网站(使用html5mode 删除#)。它使用 Elasticsearch 获取一些数据并呈现内容。 nginx 负责映射到 Elasticsearch 和我的网站根目录。

为了让整个网站具备 SEO 功能,我正在尝试整合 prerender ,使用本地实例 (http://localhost:3000)。

我拼命尝试将预渲染魔法与 nginx location/angular_test 结合使用。默认的 nginx prerender 中间件配置不适用于 location。在下面找到我的 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/(.*) /$1 break;
        proxy_pass http://elasticsearch;
        proxy_redirect http://elasticsearch /es/;
    }

}

当我访问 http://localhost/angular_test/search?_escaped_fragment_= 时我得到一个 404,因为 nginx 试图加载文件 /var/html/www/angular_test/search。这应该由 angulars 路由涵盖(请参阅 try_files 对 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/(.*) /$1 break;
        proxy_pass http://elasticsearch;
        proxy_redirect http://elasticsearch /es/;
    }

}

关于angularjs - nginx、预渲染和 Angular 路由问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36916682/

相关文章:

linux - 配置 NGINX 时如何使用环境变量作为前缀路径?

seo - 共享主机上的 SPDY 和 SEO 语义

module - 如何实现 Prestashop 前端 Controller

asp.net-mvc - SEO:索引链接到页面但不索引 URL

javascript - RxJS - 为什么我要使用 throwError 而不是简单地抛出错误?

ruby-on-rails - 在 Rails Assets 管道 (application.js) 中排除 *.spec.js 文件

javascript - 4 个复选框,如果选中 2 个或更多复选框,我想随机触发与其中一个复选框关联的 1 个函数

javascript - AngularJs $routeProvider 不支持 MVC

PHP5-FPM 静态、动态还是按需?

nginx - 在生产环境中提供 Go Webapps