Skip to content

Instantly share code, notes, and snippets.

@tstirrat15
Created November 2, 2016 16:57
Show Gist options
  • Save tstirrat15/67937ee35ef47897eea1aee3fcf0fa5f to your computer and use it in GitHub Desktop.
Save tstirrat15/67937ee35ef47897eea1aee3fcf0fa5f to your computer and use it in GitHub Desktop.
<!doctype html>
<html class="no-js" lang="en-GB">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Does GoogleBot render Angular 2 without Angular Universal? | React, etc. Tech Stack</title>
<link rel="stylesheet" href="/theme/react_etc2/css/foundation.css">
<link rel="stylesheet" href="/theme/react_etc2/css/theme.css?x=x">
<link href='https://fonts.googleapis.com/css?family=Noto+Sans:700,700italic' rel='stylesheet' type='text/css'>
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-61267-27', 'auto');
ga('send', 'pageview');
</script>
<!-- Begin Cookie Consent plugin by Silktide - http://silktide.com/cookieconsent -->
<script type="text/javascript">
window.cookieconsent_options = {"message":"This website uses cookies to ensure you get the best experience on our website","dismiss":"Ok!","learnMore":"More info","link":null,"theme":"light-top"};
</script>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/cookieconsent2/1.0.9/cookieconsent.min.js"></script>
<!-- End Cookie Consent plugin -->
<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<script>
(adsbygoogle = window.adsbygoogle || []).push({
google_ad_client: "ca-pub-9905412022020408",
enable_page_level_ads: true
});
</script>
<link rel="sitemap" type="application/xml" title="Sitemap" href="/sitemap.xml">
<meta name="generator" content="Bolt">
<link rel="canonical" href="http://react-etc.net/entry/does-googlebot-render-angular-2-without-angular-universal">
<link rel="sitemap" type="application/xml" title="Sitemap" href="/sitemap.xml">
<meta name="generator" content="Bolt">
<link rel="canonical" href="http://react-etc.net/entry/does-googlebot-render-angular-2-without-angular-universal">
<link rel="sitemap" type="application/xml" title="Sitemap" href="/sitemap.xml">
<meta name="generator" content="Bolt">
<link rel="canonical" href="http://react-etc.net/entry/does-googlebot-render-angular-2-without-angular-universal">
</head>
<body>
<div class="row">
<div class="title-bar" data-responsive-toggle="example-menu" data-hide-for="medium">
<button class="menu-icon" type="button" data-toggle></button>
<div class="title-bar-title">Menu</div>
</div>
<div class="top-bar" id="example-menu">
<div class="top-bar-left">
<ul class="menu vertical medium-horizontal " data-responsive-menu="accordion medium-dropdown">
<li class="index-1 menu-text first"><a href="/" title='This is the first menu item.' class='first'>Home</a></li>
<li class="index-2"><a href="/entries" title='' class=''>All entries</a></li>
<li class="index-3 is-dropdown-submenu-parent"><a href="/pages/about" title='' class='last'>Extras</a><ul class="menu submenu vertical" data-submenu><li class="index-1 first"><a href="https://www.symfony.fi/entry/versioning-an-api-in-graphql-vs-rest" title='' class=''>Versioning an API in GraphQL vs. REST</a></li><li class="index-2"><a href="http://symfony-cms.net/decoupling-headless-cms" title='' class=''>Decoupling with a Headless CMS</a></li><li class="index-3"><a href="https://janit.wordpress.com/2015/07/30/learning-symfony-right-with-the-demo-application-and-best-practises/" title='' class=''>Learning Symfony right with the Demo Application and Best Practises</a></li><li class="index-4"><a href="https://janit.wordpress.com/2015/07/29/bolt-is-a-viable-wordpress-alternative-built-with-silex-and-symfony-components/" title='' class=''>Bolt is a viable WordPress alternative built with Silex and Symfony components</a></li><li class="index-5"><a href="https://janit.wordpress.com/2015/07/18/bugs-in-web-development-improve-quality-with-components/" title='' class=''>Bugs in Web Development; How to improve quality with Software Components</a></li><li class="index-6 last"><a href="http://symfony-cms.net/what-do-serverless-architectures-mean-for-cms" title='' class=''>What do serverless architectures mean for CMS?</a></li></ul></li>
<li class="index-4"><a href="https://www.symfony.fi/entry/what-is-typescript-and-why-should-i-care" title='' class=''>What is TypeScript?</a></li>
<li class="index-5 last is-dropdown-submenu-parent"><a href="https://facebook.github.io" title='' class='last'>Facebook Open Source</a><ul class="menu submenu vertical" data-submenu><li class="index-1 first"><a href="http://hhvm.com" title='' class=''>HHVM</a></li><li class="index-2 last"><a href="https://facebook.github.io/react/" title='' class=''>React</a></li></ul></li>
</ul>
</div>
<div class="top-bar-right">
</div>
</div>
<!-- Header bar -->
<div class="large-12 columns headertitle">
<h2>React, etc. Tech Stack</h2>
<p>React, Flux, GraphQL, Hack, HHVM...? All of this and more!</p>
</div>
<div class="large-12 columns headerphoto" style='background-image: linear-gradient(180deg, rgba(255, 255, 255, 0.2), rgba(255, 255, 255, 0.2) 60%, rgba(255, 255, 255, 0.5)), url(/theme/react_etc2/images/02.jpg)'>
</div>
</div>
<div class="row">
<div class=" large-8 columns">
<h1>Does GoogleBot render Angular 2 without Angular Universal?</h1>
<div class="large-6 columns imageholder">
<img src="/files/2016-06/google-bot.jpg">
</div>
<p>Google is in a unique position as it is both the market leader in seach engine market. In addition it's providing tools for developers to work work. Google's own JavaScript Framework Angular.js saw great success from 2010, but the first iteration had some technical shortcomings. This is why Google is investing heavily to a major rewrite in Angular2.</p>
<p>For Angular 2 one of the capabilities developers have been coveting from React.js ecosystem&nbsp;which is isomorphic rendering. This means that the first view is rendered on the server to improve initial load performance and enable best possible search engine visibility. In Angular 2 the framework gains this functionality with <a href="https://universal.angular.io">Angular Universal</a>.</p>
<p>While Angular Universal is a great way to ensure SEO visibility, it does add complexity to the server side deployment of Angular 2 applications. There are dependencies on the backend technologies, so it's not a given that developers will be able to enable Angular Universal.</p>
<p>There is discussion for bringing <a href="https://www.symfony.fi/entry/universal-rendering-in-php-twig-with-angular-2-template-compiler">Angular Universal support to PHP and Twig</a>, but details are unknown. This is why many Angular 2 applications will be continue to be deployed without server side rendering of applications.</p>
<p>In an experiment on how well Google's own Search Crawler GoogleBot is able to render Angular 2 applications, we'll take a look at how GoogleBot is able to render the example application from the Angular Team, <a href="https://github.com/johnpapa/angular2-tour-of-heroes">Tour of Heroes</a>.</p>
<p>Using the <a href="https://www.google.com/webmasters/">Google Webmaster tools</a> you can get the GoogleBot to visit your page and render your site. You can also get a rendered view of the page two formats:</p>
<ul>
<li>This is how Googlebot saw the page</li>
<li>This is how a visitor to your website would have seen the page</li>
</ul>
<p>In the case of Angular2 it is clear that the GoogleBot's JavaScript capabilities are good enough to render the rather sophisticated front end framework. The demo application rendering shows that GoogleBot does render everything ok - even without Universal Rendering:</p>
<p><img alt="" src="/files/2016-06/angular2-googlebot.jpg" style="max-width: 640px;" /></p>
<p>So for individual pages it is clear that GoogleBot can execute and index raw Angular2 applications, however when using the "Crawl this URL and its direct links" option on indexing record you can see that there are no entries to other pages of the application.</p>
<p>This means that when you <a href="http://symfony-cms.net/decoupling-headless-cms">decouple from a CMS</a> with Angular&nbsp;2, for example, individual pages will be available - but it will not be able to natively follow all the links in the page. You'll still need to take care of SEO when deploying Angular 2 applications without Angular Universal.</p>
<p>In addition it's worth noting that by default Angular 2 now uses the "HTML 5 pushState" style for <a href="https://angular.io/docs/ts/latest/guide/router.html#!#appendix-locationstrategy-and-browser-url-styles">routing</a>. So the issue when decoupling websites with a REST API and 404 pages continues to remain relevant:</p>
<blockquote>If your custom backend does not handle checking if the content exists or not, then you'll likely get 404s, heading to a broken page. You could fix this by always sending a template with the HTTP 200 (OK) message, but that would be breaking the internet. If a page does not exist, it should return a 404.<br />
- &nbsp;<a href="http://drupal.sh/headless-drupal-angular-html5-history-api-not-found-404">REST, Angular HTML5 History API and not found (404) pages</a></blockquote>
<p>So in the future it looks clearer and clearer that if your application needs to have public links from outside you should use Angular Universal. While GoogleBot is able to load and execute all the CSS and JavaScript from&nbsp;Angular 2 applications, it is unable to follow anchor links.</p>
<p>When Decoupling CMS other applications with a REST, it will be better done in the future with a separate rendering server with Node.js with Angular Universal enabled. This will make hybrid solutions more difficult and add complexity - but is a necessity for best Search Engine visibility.&nbsp;</p>
<a href="https://twitter.com/share" class="twitter-share-button">Tweet</a>
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');</script>
<script src="https://apis.google.com/js/platform.js" async defer></script>
<g:plusone></g:plusone>
<p class="meta">
Written by <em>Jorgé</em> on Friday June 24, 2016
</p>
<p class="meta">
<a href="/entry/does-googlebot-render-angular-2-without-angular-universal">Permalink</a> -
</p>
<p class="meta">
<a href="/entry/keystone-js-is-the-best-node-js-alternative-for-wordpress">&laquo; Keystone.js is the best Node.js alternative to WordPress</a>
-
<a href="/entry/adam-klein-on-javascript-on-v8-es6-features-async-await-and-modules">Adam Klein on JavaScript on V8: ES6 features, Async/Await and Modules &raquo;</a>
</p>
</div>
<!-- Sidebar -->
<aside class="large-4 columns">
<h5>Site search</h5>
<form action="https://www.google.com" id="cse-search-box">
<div class="row collapse">
<input type="hidden" name="cx" value="partner-pub-9905412022020408:5459677776" />
<input type="hidden" name="ie" value="UTF-8" />
<div class="large-8 small-9 columns">
<input type="text" name="q" size="55" />
</div><div class="large-4 small-3 columns">
<input type="submit" name="sa" value="Search" class="button secondary" />
</div>
</div>
</form>
<script type="text/javascript" src="https://www.google.com/coop/cse/brand?form=cse-search-box&amp;lang=en"></script>
<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<!-- Content Sites (Sidebar) -->
<ins class="adsbygoogle"
style="display:block"
data-ad-client="ca-pub-9905412022020408"
data-ad-slot="2193643771"
data-ad-format="auto"></ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>
<div class="panel">
</div>
<h5>Recent Entries</h5>
<ul>
<li><a href="/entry/wordpress-com-stole-ghost-platform-code-now-accuses-wix-for-the-same">WordPress.com stole Ghost platform code, now accuses Wix for the same</a></li>
<li><a href="/entry/youtube-is-being-rebuilt-on-web-components-and-polymer">YouTube is being rebuilt with Web Components & Polymer</a></li>
<li><a href="/entry/choosing-between-angular-react-and-vue-js-you-cant-go-wrong">Choosing between Angular, React and Vue.js? You can't go wrong.</a></li>
<li><a href="/entry/dgraph-has-the-potential-to-become-a-defacto-standard-for-graphql-graph-databases">Dgraph has the potential to become a defacto standard for GraphQL powered DBs</a></li>
<li><a href="/entry/php-8-to-ship-with-a-jit-compiler">PHP 8.0 to ship with a JIT compiler</a></li>
<li><a href="/entry/tom-dale-on-graphql-relay-and-rest">Tom Dale on GraphQL, Relay and REST</a></li>
<li><a href="/entry/angular-2-in-production-on-google-adsense-admin-ui">Angular 2 in production on Google AdSense admin UI</a></li>
<li><a href="/entry/json-api-is-a-simple-alternative-to-graphql-and-rest">JSON API is a simple alternative to GraphQL and REST</a></li>
<li><a href="/entry/facebook-launches-npm-compatible-client-yarn">Facebook launches NPM compatible client Yarn</a></li>
<li><a href="/entry/php-cms-ez-platform-gets-graphql-support">PHP CMS eZ Platform gets GraphQL support</a></li>
</ul>
<p><a href="/entries">Entries overview &raquo;</a></p>
<h5>Recent Pages</h5>
<ul>
<li><a href="/page/rest-vs-graphql">REST vs GraphQL</a></li>
<li><a href="/page/installing-wordpress-on-windows-subsystem-for-linux-wsl-ubuntu">Installing WordPress on Windows Subsystem for Linux (WSL/Ubuntu)</a></li>
<li><a href="/page/dont-use-drupal-or-wordpress-for-iot-internet-of-things">Don't use Drupal or WordPress for IoT, Internet of Things</a></li>
<li><a href="/page/alternatives-to-drupal">Alternatives to Drupal</a></li>
<li><a href="/page/about">About</a></li>
</ul>
<p><a href="/pages">Pages overview &raquo;</a></p>
</aside>
<!-- End Sidebar -->
</div>
<!-- Footer -->
<footer class="row">
<hr />
<div class="large-10 columns">
<ul class="menu vertical medium-horizontal inline-list align-right" data-responsive-menu="accordion medium-dropdown">
<li class="index-1 menu-text first"><a href="/" title='This is the first menu item.' class='first'>Home</a></li>
<li class="index-2"><a href="/entries" title='' class=''>All entries</a></li>
<li class="index-3"><a href="/pages/about" title='' class='last'>Extras</a></li>
<li class="index-4"><a href="https://www.symfony.fi/entry/what-is-typescript-and-why-should-i-care" title='' class=''>What is TypeScript?</a></li>
<li class="index-5 last"><a href="https://facebook.github.io" title='' class='last'>Facebook Open Source</a></li>
</ul>
</div>
</footer>
<script src="/theme/react_etc2/js/jquery.min.js"></script>
<script src="/theme/react_etc2/js/foundation.js"></script>
<script src="/theme/react_etc2/js/app.js"></script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment