There were a few posts on the internet on how to integrate front-end code into a Sitecore solution. It all started with a post from Alex Shyba. Back in February, he describes the general concept of an integration. Then Richard Seal created a module for Sitecore that allow you to use jsx renderings in Sitecore.
I was trying to solve a problem of an HTML handover between front-end and Sitecore developers for a while. Finally, I was able to play with ReactJS and Sitecore by myself, and here is what I end up doing.
HTML Handover
Quite often we have an HTML created by some team and another team looking at this HTML creates ASP.MVC view. If a project is longer than 2 months, you will need to support both HTML and MVC views and it is a double effort.
If we can use some HTML templates generated by the first team in Sitecore it would be ideal. If you take Angular 1.x, for example, you were able to create directives and pass data into them, which solves the problem to some degree. Yet your SEO wasn’t the best as search engines do not know how to process complex JS. There is no SEO in such a case. This might be acceptable only for portals that need a login and won’t allow bots to see pages anyway but only in this case.
Angular 2.0 and ReactJS are a bit different, they are not working with DOM directly. They creating lighter page component models in JavaScript and convert this structure into DOM or string if you working on a server. This allows us to prerender JS components on the NodeJS server and speed up the initial load of the application as well as improve SEO.
How NodeJS server-side rendering could help us in a .NET application
The ability to render on a server is cool but how could it help in Sitecore, which is the ASP.net site? NodeJS is a web-server, which has Google’s V8 JavaScript engine in its heart. It adds to it various modules to work with the network, I/O, yadda, yadda. If this was done in NodeJS, you could that it could be done on other platforms including .NET.
ClearScript.V8 is one of such libraries for .NET. It wraps V8 and provides a simple C# interface to interact with the JS engine (pass a string with JS code into an Execute command).
ReactJS.NET
ClearScript.V8 is used by ReactJS.NET to execute React methods and render JSX and other controls into a string. Like you would do in a standard Node.JS app. the best thing is that all plumbing is done in this library and it is supported by Facebook itself. It allows you to render JSX files from the server, which was described in details by Alex and Richard, and precompile jsx via webpack e.g.
Angular 2.0 was released just a few weeks ago and might not have too many modules or similar commands (that is why I’m not going to talk about it any mode).
APPROACH
The idea is that you as a front-end developer uses NodeJS and creates your sandbox in it. In this sandbox, you might have sample pages, components, widgets, various tests for them, and so on. Then you pack your app with a webpack and make sure that you separate code. Your components should be in one package, vendor scripts, and scripts that provide governance in separate as well.
The components package should contain only components. It must not use any code that directly accessing DOM, otherwise, it is not isomorphic or universal and couldn’t be used on a server.
Then you reference the webpack package from Sitecore and use controls exposed via name in controller renderings. This would give you full control in model preparation and error handling.
I disagree with the direct usage of JSX as it is not a full replacement for Razor views. It requires the processing of JSX in the .NET app and your Sitecore site needs to know about many different view files. Reference of a pre-processed package allows you to define a clear contract (set of components to be used) via one reference of a JS file.
On a Sitecore side, you could use standard controller renderings and it won’t even recognize that React is used somewhere.
NodeJS and Webpack config
The simplest way to configure a client-side solution is to use yeoman template, what I did with pretty much default configurations. Mian difference was the creation of the second package for components (lines 13-16).
The package for components references a file that should gather all required references, in my case it is server.js. It uses node module exposes to define a variable in a global scope. Using this variable you would be able to access your components from .NET.
A “Common” folder referenced in a server.js is a folder with components that I want to use on a server-side.
ReactJS Components Implementation
You could create standard components as you would usually do for ReactJS. I’ve ended up using an old syntax (var xxx = React.createClass({…}) as there were some problems with the server using newer syntax. I think that I did something wrong with the Babel configuration and my webpack packages were not automatically converted to ES5 standard (I saved it for later).
There is one not standard function for a React component - getPlaceholders. Using this function I’ll let Sitecore know what placeholders exist in my component.
Sitecore Side of the Universe
First of all, you would need to install ReactJS.NET packages. Configure them by adding JS file generated by webpack via “AddScriptWithoutTransform()”. ![2016-10-09_1010.png/images/m/2016/10/2016-10-09_1010.png)
Sitecore itself doesn’t need anything more than a React controller that inherits a standard SitecoreController and adds a few useful features. The first is a method that calls mvc.placeholder pipeline, which helps me to render the content of placeholders. The second is a method that returns ActionResult for React. It uses a JS engine to get the placeholders to list defined in a ReactJS component, process its content and compose props for the component.
When you combine this all together, as you might expect EE is fully functional.
Summary
- Using webpack we could achieve a clean separation between HTML/CSS/JS and Sitecore/.NET.
- Sitecore doesn’t need to know the location of views files, as he is not using MVC view renderings in this case.
- Views themselves could be pre-processed and outside of Sitecore.
- Placeholders could be retrieved using JS call from the ReactJS component itself, which simplifies configuration.
What’s Next?
As you might expect this is a POC, but I still need to add Redux to the page. Also, make sure that it will work with components added dynamically to the page. Redux should not resend placeholders HTML and all localization data but only values needed for the logic.
Another question, which should be checked, is performance.
Follow me on twitter @true_shoorik. Would be glad to discuss ideas above in comments.