JSS: Resolve site

The bootstrapped JSS app is focused on supporting a single site per app (and localizations of this site). However, let's say we have several markets that want to use our JSS app, but they don't want the exact same routes, content and presentation. Let's see if we can achieve similar site handling as in traditional Sitecore.

I'll start this post out by stating that (as always) there are multiple ways of solving this, the more obvious one being to just have separate JSS apps for each market. However, let's say the markets want to use the exact same components between each other, they just want to define their own routes, content and presentation. In my experience, this is a common scenario for Sitecore customers, who tend to be big enterprises with market divisions that has a lot of say on the look and behavior of their section of the website. In this case, I would personally rather work with a single app that can handle multiple sites.

Resolve site

There is one important factor that makes this relatively easy to achieve, which is that the Layout Service is site aware if you tell it to be. I.e. we can adjust the default RouteHandler.js to pass along sc_site=X in the layout request. All we have to solve is the issue of making the client know what site to pass along.

In my example, we resolve site by hostname, however if you also want to be able to resolve it by "virtual folder", I think it is pretty easy to modify.

We'll start by adding a new site to our config under sitecore/config. My site definitions:

sites

And my app definition look like this:

app
 

Now deploy these config changes with jss deploy config. Next step is to create a new file, which I called siteResolver.js.

siteResolver
 

And we'll just have to add each site here as we create new ones. An alternative to this would be to use some javascript XML parser to read the actual sites config, and process each site. That way, you wouldn't have to add new sites in two places.

Our final stop is RouteHandler.js. On line 96 (in the updateRouteData function), you can see that language is resolved by the first part of the URL (e.g. example.com/sv-SE). If however there is no language prefix in the URL path, it defaults to an app wide default language (defined in package.json). We don't want this, so we remove the second part of this conditional assignment, making the variable become undefined if no language prefix is present in the path.

lang-snippet
 

Instead, we want to handle both site and language in the getRouteData function (line 200). We do this by first resolving the site, and including that plus the api key parameters in the querystring object. Then we check if the the language was resolved by path prefix. If it was, we include it in the querystring, and if it wasn't we simply omit it. The Layout Service will use the default language specified in the site definition of the config.

getroutedata-snippet
 

And that is it. Your app is now able to resolve site as well as language based on hostname and your site definitions.

13 Feb 2019, by Bonny Nilsson | 

JSS, Sites, RouteHandler