I am writing html snapshot support for a website for SEO. We have an AngularJS site running on nodejs and express. I am installing everything via npm.
I am seeing an error when I snap-shoot pages that have an escaped character (e.g. %20 in my case).
I have tried running with grunt and grunt-html-snapshot. In this example, both URLs work in a browser. The URL without the escape also snapshots ok. But the url with the %20 causes a loop error (a digest loop error?) in phantom/angular.
Here is the gruntfile:
module.exports = function(grunt) {
grunt.loadNpmTasks('grunt-html-snapshot');
grunt.initConfig({
htmlSnapshot: {
all: {
options: {
snapshotPath: 'snapshots/',
sitePath: 'http://localhost/',
// urls: ['courses/BiologicalAnthropology/']
urls: ['courses/Biological%20Anthropology/']
}
}
}
});
grunt.registerTask('default', ['htmlSnapshot']);
};
Here is the console output for the error:
Running "htmlSnapshot:all" (htmlSnapshot) tas k
running html-snapshot task...hold your horses
Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!
Watchers fired in the last 5 iterations: [["fn: $locationWatch; newVal: 7; ol d Val: 6"],["fn: $locationWatch; newVal: 8; oldVal: 7"],["fn: $locationWatch; newVal: 9; oldVal: 8"],["fn: $locationWatch; newVal: 10; oldVal: 9"],["fn: $l o cationWatch; newVal: 11; oldVal: 10"]]
http://errors.angularjs.org/1.2.15/$rootScope/infdig?p0=10&p1=%5B%5B%22fn% 3A% 2 0%24locationWatch%3B%20newVal%3A%207%3B%20oldVal%3A%206%22%5D%2C%5B%22fn%3A% 20%24locationWatch%3B%20newVal%3A%208%3B%20oldVal%3A%207%22%5D%2C%5B%22fn% 3A% 2 0%24locationWatch%3B%20newVal%3A%209%3B%20oldVal%3A%208%22%5D%2C%5B%22fn%3A% 20%24locationWatch%3B%20newVal%3A%2010%3B%20oldVal%3A%209%22%5D%2C%5B%22fn %3A % 20%24locationWatch%3B%20newVal%3A%2011%3B%20oldVal%3A%2010%22%5D%5D
at https://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.js:1 207 3
at https://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.js:1 227 9
at https://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.js:1 385
at invoke (https://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angu lar .js:3805)
at https://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.js:1 386
at bootstrap (https://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/a ngular.js:1394)
at angularInit (https://ajax.googleapis.com/ajax/libs/angularjs/1.2.15 /angular.js:1307)
at https://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.js:2 1163
at https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js:2
at https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js:2
at https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js:2
at K (https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js: 2)
error: Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!
Watchers fired in the last 5 iterations: [["fn: $locationWatch; newVal: 7; oldVal: 6"],["fn: $locationWatch; newVal: 8; oldVal: 7"],["fn: $locationWatch; newVal: 9; oldVal: 8"],["fn: $locationWatch; newVal: 10; oldVal: 9"],["fn: $locationWatch; newVal: 11; oldVal: 10"]]
http://errors.angularjs.org/1.2.15/$rootScope/infdig?p0=10&p1=%5B%5B%22fn%3A%20%24locationWatch%3B%20newVal%3A%207%3B%20oldVal%3A%206%22%5D%2C%5B%22fn%3A% 20%24locationWatch%3B%20newVal%3A%208%3B%20oldVal%3A%207%22%5D%2C%5B%22fn%3A%20%24locationWatch%3B%20newVal%3A%209%3B%20oldVal%3A%208%22%5D%2C%5B%22fn%3A% 20%24locationWatch%3B%20newVal%3A%2010%3B%20oldVal%3A%209%22%5D%2C%5B%22fn%3A%20%24locationWatch%3B%20newVal%3A%2011%3B%20oldVal%3A%2010%22%5D%5D
I have also tried running a plain vanilla phantomjs script to snapshot the page, but get similar errors with that approach.
Server Script (PhantomJS):
var path = require('path')
var childProcess = require('child_process')
var phantomjs = require('phantomjs')
var binPath = phantomjs.path
var childArgs = [
path.join(__dirname, '../phantom/test.js'),
'http://localhost/courses/Biological%20Anthropology'
]
console.log(childArgs);
childProcess.execFile(binPath, childArgs, function(err, stdout, stderr) {
console.log(err, stdout, stderr);
// handle results
})
Phantom script:
var system = require( "system" );
var page = require( "webpage" ).create();
var url = system.args[1];
var t = Date.now();
console.log(url);
page.open( url, function( status ) {
console.log( 'Load time: ' + (Date.now() - t) + 'ms' );
} );
page.onLoadFinished = function(status) {
console.log('On load finished Status: ' + status);
var pageContent = page.evaluate( function() {
return document.getElementsByTagName( "html" )[0].innerHTML;
} );
console.log(pageContent);
phantom.exit();
};
Here's the first line of the console error (after that it repeats angular includes and code indefinitely):
[Error: stdout maxBuffer exceeded.] 'http://localhost/courses/Biological%20Anthropology/\r\nError: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!\r\nWatchers fired in the last 5 iterations: [["fn: $locationWatch; newVal: 7; oldVal: 6"],["fn: $locationWatch; newVal: 8; oldVal: 7"],["fn: $locationWatch; newVal: 9; oldVal: 8"],["fn: $locationWatch; newVal: 10; oldVal: 9"],["fn: $locationWatch; newVal: 11; oldVal: 10"]]\r\nhttp://errors.angularjs.org/1.2.15/$rootScope/infdig?p0=10&p1=%5B%5B%22fn%3A%20%24locationWatch%3B%20newVal%3A%207%3B%20oldVal%3A%206%22%5D%2C%5B%22fn%3A%20%24locationWatch%3B%20newVal%3A%208%3B%20oldVal%3A%207%22%5D%2C%5B%22fn%3A%20%24locationWatch%3B%20newVal%3A%209%3B%20oldVal%3A%208%22%5D%2C%5B%22fn%3A%20%24locationWatch%3B%20newVal%3A%2010%3B%20oldVal%3A%209%22%5D%2C%5B%22fn%3A%20%24locationWatch%3B%20newVal%3A%2011%3B%20oldVal%3A%2010%22%5D%5D\r\n\r\n
The only thing I found on stack overflow related was this discussion on client side angular implementation and browser compatibility. They were seeing a similar error message:
Angular JS: IE Error: 10 $digest() iterations reached. Aborting
And I found a brief google group discussion with an unsatisfactory answer (disable html5mode):
https://groups.google.com/forum/#!msg/angular/Gna-zWBJhIE/CBYhCJ_1lXIJ