AngularJS vs SEO

Sudah lama sebenarnya menyelesaikan masalah  ini baru sempat untuk menulis hari ini. Intinya adalah ketika robot index berkunjung ke website kita,  nginx meredirect ke server Panthomjs. Panthomjs akan me-render secara sempurna html dan memberikan ke robot index.

Configuration di nginx  nginx.conf:

location / {
  try_files $uri @prerender;
}

location @prerender {
 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) {
  set $prerender "127.0.0.1:8888";
  proxy_pass http://$prerender$request_uri;
 }
 if ($prerender = 0) {
  rewrite .* /index.html break;
 }
}

 

Script phantomjs render.js :

var system = require('system');

if (system.args.length < 3) {
    console.log("Missing arguments.");
    phantom.exit();
}

var server = require('webserver').create();
var port = parseInt(system.args[1]);
var urlPrefix = system.args[2];

var parse_qs = function(s) {
    var queryString = {};
    var a = document.createElement("a");
    a.href = s;
    a.search.replace(
        new RegExp("([^?=&]+)(=([^&]*))?", "g"),
        function($0, $1, $2, $3) { queryString[$1] = $3; }
    );
    return queryString;
};

var renderHtml = function(url, cb) {
    var page = require('webpage').create();
    page.settings.loadImages = false;
    page.settings.localToRemoteUrlAccessEnabled = true;
    page.onCallback = function() {
        cb(page.content);
        page.close();
    };
//    page.onConsoleMessage = function(msg, lineNum, sourceId) {
//        console.log('CONSOLE: ' + msg + ' (from line #' + lineNum + ' in "' + sourceId + '")');
//    };
    page.onInitialized = function() {
       page.evaluate(function() {
            setTimeout(function() {
                window.callPhantom();
            }, 10000);
        });
    };
    page.open(url);
};

server.listen(port, function (request, response) {
    var route = parse_qs(request.url)._escaped_fragment_;
    var url = urlPrefix
      + request.url.slice(1, request.url.indexOf('?'))
      + '#!' + decodeURIComponent(route);
    renderHtml(url, function(html) {
        response.statusCode = 200;
        response.write(html);
        response.close();
    });
});

console.log('Listening on ' + port + '...');
console.log('Press Ctrl+C to stop.');