Post_GWTSEO_Howto1_v2-01

Better SEO with GWT

When we started working on our new website, we quickly faced challenges often encountered with single-page application frameworks: enabling search engine optimization (SEO) and crawlability. The problem with these kinds of applications is that you only have one .html host file, which has two important consequences:

  1. Having only one title tag makes it hard for people to use the browser history for navigation
  2. It becomes impossible to define meta properties with relevant data for different site sections

Thankfully, each of these problems can be solved.¨

Changing the title

This is actually a simple fix. We can use GWT’s Document class to change the title when our section is attached to the DOM:

Adding and updating meta properties

Crawler

The hard way

We could create MetaElements and inject them into the head section manually when our section is attached to the DOM :

Using GWT-SEO

This seems a bit cumbersome and isn’t quite what webmasters are used to, so perhaps we can do better. This is where GWT-SEO comes into play. It allows us to define meta properties in the UiBinder’s ui.xml file as a Widget, almost like we would define them in an html file. The library will then create and inject the defined meta elements in the head section when your View is attached to the DOM, removing the need to register your own AttachHandler.

Now that’s better! Notice that the title is also handled, which means no more document.setTitle() is needed either!

Internationalization (i18n)

Moreover, since we’re within a UiBinder, we can therefore take advantage of the power of ui:msg to internationalize our properties (more details on using GWT i18n with UiBinder in an upcoming post!). In the meantime, you can take a look at our website for a live example of GWT-SEO using i18n, and especially at the sources of the website to see more in details how it was done, or at the source of my bee page for a specific example.

Dynamic data

More often than not, when implementing a single-page application, the content of the section will depend on some data fetched from an AJAX request (e.g. : a product page in an online store). GWT-SEO can also help you with that, although it requires some Java code in your request’s callback. Let’s say we have a Presenter that retrieves a Product when the product’s dynamic page is loaded, and passes it to its View through the setProduct method.

The advantage of using GWT-SEO, versus manually creating MetaElements to inject dynamic properties, is that it prevents duplicates by replacing existing properties with new ones, by leveraging the injection of derived tags (title and og:title, description and og:description, etc.).

But what good would all that do if crawlers like Google or Facebook can’t retrieve the fully rendered version of the page?

Making the application crawlable

Making your application crawlable could be the topic of a whole other blogpost, but I will discuss it briefly here.

Most crawlers nowadays implement a simple directive that allows us to serve different content when a hashbang (#!) is encountered in an URL. So the first step is to make sure your section URLs contain hashbangs. For example, a crawler fetching http://www.arcbees.com/#!/support would replace the hashbang with the escaped_fragment query parameter, in this case : http://www.arcbees.com/?_escaped_fragment_=/support (take a look at the rendered DOM).

Rendering for crawlers

Now that we have a way to identify crawlers’ requests, we need to serve a rendered version when we detect the _escaped_fragment_ query parameter to ensure the crawler doesn’t need to run any JavaScript code to access the content. To achieve this, we need something like HtmlUnit or PhantomJS to retrieve our webpage and process the JavaScript until we have a fully rendered page. Or better yet, use GWTP Crawler Service, which handles everything for us, from detecting crawlers’ requests to generating a fully rendered page!

Conclusion

Writing the meta properties for all the sections of your single-page application will allow you to be better ranked on search engines, and give you a chance to stand out against your competitors. It will also make your pages easier to share across social medias, which is, in this 2.0 era, mandatory for any web page. SEO and crawlability are easy things to overlook when developing your application, but to ignore them is to miss out on a substantial number of potential visitors!

Maxime Mériouma-Caron

We’re going to use Maven

Well, we’re going to take a little longer to set up the project since we decided to use Maven !

Here are some words that Richard Allen posted on the Gwt-Platform group. This convinced us.

We have a large codebase with many projects that share a large amount of code housed in other projects. I used Ant for several years, but became frustrated with how much effort was required to maintain the whole build environment, and how I was regularly having to create custom solutions for things, like dependency management, that I felt should be the tool’s responsibility. I migrated all of our projects to Maven2 several years ago and have been very pleased. Maven is by no means perfect, so it will frustrate you at times. Maven lets you work at a higher level than Ant. Maven provides a lifecycle with phases such as compile, package, and integration-test, where as Ant provides low level tasks that you have to compose into the “phases” that Maven provides. Working at a higher level reduces your workload most of the time, but is a source of frustration when you need to work at a lower level. However, you can simply use the maven-antrun-plugin to run a set of Ant tasks when you want to work at a low level. And you can always write your own plugins to do anything you want. You can also write plugins in Groovy, which we have found to be easier. BTW, Maven3 is adding some nice scripting capabilities.

Maven has greatly reduced the overall maintenance of our build environment, as well as provided many features we didn’t have with Ant. Maven draws a lot of information from your POM files, and there’s much more to Maven than simply a build tool. Here are some of the benefits I believe you would derive from using Maven.

  • Very powerful dependency management. Maven makes it easy to handle your dependencies on third-party libraries, as well as dependencies on other projects that you maintain. Tools like m2eclipse and the maven-dependency-plugin, as well as the dependency reports generated by the maven-project-info-reports-plugin are invaluable when you want to see all your projects’ dependencies, their versions, and the licenses for your third-party dependencies. The dependency reports are great for open source projects because they provide your users (or potential users) an easy way to see what your project depends on while being very simple for you to produce and maintain.
  • Consistent project structure. Sure, you could devise your own project structure that you consistently used among all of your projects, but Maven already provides one that works well, and anyone that has used Maven before will immediately understand your project layout. Like I said, we have many projects, and it’s great that our developers can switch between projects without having to learn something new about the build environment. I love it when open source projects that I use also use Maven, because I can immediately build their project or import it into Eclipse. If they use Ant, it’s a toss up. Some are easy to build and import, others aren’t. There is no consistency.
  • Simple release management. I haven’t used Maven with Mercurial, but I see it supports it. Having used Maven with Subversion, I know Maven makes it very simple to make a release of your project and publish it to a Maven repository for public access, making your release process consistent and easy, as apposed to the error-prone process that many projects use. Maven’s release tools will ensure your code is committed to your source control and that your code passes all of its tests before making a release, and will automatically update the version numbers in the POM files for you. Additionally, you can create a report of changes from your source control system and/or a report of the fixed issues from your issue management system, like JIRA, that went into the release. This is where you start to see that Maven is a whole lot more than just a build tool.
  • Simple integration with unit testing tools and static analysis tools. Maven makes it easy to run your unit tests and integration tests, generate test coverage reports, run static analysis tools such as Checkstyle, PMD, FindBugs, JavaNCSS, and JDepend, and publish those reports to a website. These tools can be helpful to gage the overall quality of your code.
  • Simple reporting and website generation. I’ve already mentioned some Maven reporting capabilities, but Maven also has a general website generation tool. You can write a website in a wiki-like language and pull in all the reports that you generated. Some other reports that are important for projects to publish, which Maven makes easy, are Javadocs, browsable source code, and information on the project’s license, mailing list, source code repository, issue tracking system, the Maven plugins used for building the project, and the list developers.
  • Repository manager. The concept that Maven uses of storing dependencies and associated metadata in a repository instead of a source control system is a huge benefit. You can use a repository manager to cache all third-party dependencies that you get from the Internet to provide your group a stable repository, deploy your own projects (and custom
    Maven plugins) for other developers in your company to use, and even restrict what versions and libraries developers can pull into projects by making the build only get its dependencies from the repository manager.
  • Now, as for using Maven with Eclipse, you have three options. You can use one of two Eclipse plugins, m2eclipse or Eclipse IAM, or you can use the maven-eclipse-plugin to generate Eclipse projects. I have never used Eclipse IAM. My experience with m2eclipse is that it is nice for a small set of projects, but if you have a large multi-project structure like we do, then m2elipse consumes too much resources. So, I install m2eclipse for some of its tools, like seeing a hierarchy of the Maven dependencies for a project, and autocomplete while editing a POM file, but I do not import our projects as Maven projects into Eclipse. Instead, I use the maven-eclipse-plugin to generate all the Eclipse projects, and then I import them as existing Eclipse projects. We use a hierarchical structure for multiple projects, which is what Maven suggests, and so all I have to do is point Eclipse at the top directory and it will find all of the generated projects. The only primary drawback to this approach, as apposed to using m2eclipse, is that you have to re-generate your Eclipse projects if you add or remove a dependency. However, the process is very fast, and you simply have to refresh a project that you have already imported. Some day, I expect m2eclipse or Eclipse IAM to be efficient enough to just use them.

    Hope that helps.

    -Richard

That was a great and complete answer to our question and thanks to him, we finally made our mind !

Thanks Richard and everyone else that took the time to answer either here or on Gwt-Platform group.