Forest header image

Symfony Finland
Random things on PHP, Symfony and web development

Universal Rendering in PHP/Twig could be done with the Angular 2 Template Compiler

At the ng-conf event in May 2016 there were sessions discussing how Angular 2 can support server side rendering in various platforms. If you're working on a project running on Node.js, then Angular 2 is a native citizen. For other options like ASP, Java and PHP there are a few options on the table.

The Angular 2 development team has already collaborated with Mediacurrent on select Drupal projects using Angular 2, but they seemed to have been limited to more generic issues of integrating a server side rendering CMS and a front end framework such as Angular 2. All of this is valuable and not Drupal specific.

Later during the ng-conf more details on the Server Side Rendering (Universal Rendering in Angular lingo) can be implemented in different environments to improve first page load experience. A few options were brought up, some of them have been discussed in this blog before:

The downside of these approaches is that you need to add additional complexity either by adding a dependency to an external service or require a rather exotic PHP extension at this point.

Running JavaScript on the is an easy way to gain full support and there is a similar low-latency Node.js bridge built for Angular Universal rendering in ASP.NET or you can target an embedded JavaScript engine like Nashorn on the JVM.

Targeting PHP/Twig with the Angular 2 template compiler

The more interesting tidbits of information focused around the template compiler in Angular 2. By default it emits JavaScript or TypeScript templates, but it is not limited to doing so. They are considering building extensions that would compile Angular 2 into Twig templating format or possibly raw PHP.

This is a more challenging option for the development team as they need to maintain another component and developers might need to write their business logic twice. The advantage would be that the underlying PHP architecture could stay as simple as possible.

Angular 2 itself will handle catching up to the client state preboot.js, a lightweight JavaScript library that records user events and plays them back once Angular 2 has loaded - giving an acceptable illusion that the application was up and running immediately from a static server side rendered starting state.

For widespread adoption the template compiling option would likely be better. It would allow simple server architecture and a compilation step to Twig/PHP would not add much to the workflow of developers as they'll likely anyhow have a build process in place for their front end JavaScript.

Back end templates can be just another produce of your front end build process

Emitting back templates as a part of this would not have significant overhead as you are likely already creating and managing assets at development and deployment time. So in addition to JS and CSS, you would also get Twig templates from your build process.

I would personally prefer Twig over raw PHP as you get readable code that is easier to debug. Performance wise there is little overhead as Twig itself will compile down to PHP on the first run. In addition the Angular team would get access to the features of Twig. The additional safety net is that if there is an error in the JavaScript generated Twig templates would not crash the whole PHP application.

Using Twig itself obviously couples this approach to applications that are using it, but once the groundwork is done it should be easier to port this to other templating systems like Blade for Laravel or Volt for Phalcon.

In each case you would use the robust templating engine of your choice on the server. The template engine itself does not case if the template is written by hand or generated by the Angular 2 Template Compiler.

Come to think of it, targeting template languages would allow potential portability to a lot of different platforms. Take Mustache as an example, it is available for use in Ruby, JavaScript, Python, Erlang, node.js, PHP, Perl, Perl6, Objective-C, Java, C#/.NET, Android, C++, Go, Lua, ooc, ActionScript, ColdFusion, Scala, Clojure, Fantom, CoffeeScript, D, Haskell, XQuery, ASP, Io, Dart, Haxe, Delphi, Racket, Rust, OCaml, Swift, Bash, Julia, R, Crystal and Common Lisp.

Even a partial server rendered view is enough

Server side rendering of JavaScript applications remains important for user experience and SEO. Even if you would not get a fully server side rendered JavaScript app in PHP at the snap of your fingers this could be useful. As always there can be a middle ground and you don't necessarily need to go all in.

Loading up just the essential bits of your application (content view, navigation, etc.) on the server is an improvement over fully client generated code. You probably don't need even a server rendered view of each and every widget in your client side application. For this your Angular 2 application would need to be able to boot up from bootstrapping partial templates.

Duplicating business logic is a valid concern. If you're using the same server application for generating the back end views using and your front end data feeds using a contemporary PHP framework in a smart way - it is not probably that big of a thing. You're likely already sharing code between CLI script commands and your controllers.

Modern PHP frameworks like Symfony allow you to share code using services between different areas of your application. In this case you would simply call the same service for both the server generated view and the REST API that your Angular 2 API consumes.

Google and the development team are interested in moving this approach forward, but would like to join forces with developers from the PHP realm. You can reach out to Bradley Green from the Angular 2 team in these matters.

Below is the video discussing options for Angular 2 Universal Rendering in various technical environments:


Written by Jani Tarvainen on Saturday May 7, 2016
Permalink - Tags: symfony, php, twig, javascript, angular

« Using Symfony Finder and YAML components to transform Drupal 8 configurations to eZ Platform - Learn Symfony and modern PHP with Bolt 3.0 - a Silex powered CMS »