JSS (React) Dynamic Layouts - Part 3: Layout items on import, and extending Layout Service
All preparations done, let's make sure layout items are created when we deploy our JSS app. And while we're tinkering around in Sitecore, let's also see to it that the Layout Service gives us the name of the layout. That way we don't need to keep a layout map with IDs in JSS.
Quick recap of the last part: We modified a frontend JSS pipeline to make sure our layouts are included in the import manifest (a JSON file describing what should be created/updated in Sitecore). Now let's complete this functionality by creating a backend processor to read the layouts-manifest and handle the item creation.
Keep calm and install this package: jss_process_layouts. It will make sure your layouts are imported into Sitecore when deploying your app, and it will include layout info (name and ID) in the responses from Layout Service (which we will need for the next part).
Step 1: ProcessLayouts
JSS introduces a heap of new processors, some patched into existing pipelines, some (a lot) that make up new pipelines. In fact, there is an entire pipeline-group for just JSS. One particular pipeline included in this group is the import-pipeline, and this is the one we want to patch. Now, we could do this in multiple patches if we wanted. If you look at the existing processors in the pipelines, you'll see that for each type of item the pipeline expects from the JSS manifest, there is a pipeline for resolving a container (for example, a rendering container) and another processor further down the chain that processes the actual items (again, like for example renderings). However, I decided to keep it simple for the sake of this post and just create a single processor.
The processor reads the layouts-section of the manifest (the one we created in the last part) and based on this it creates new layout if they are not pre-existing, or update existing ones (however the only field that is updated if the layout already exists is the Placeholders field, since it's the only one we care about right now. If you want to, it's very easy to extend the logic to also be able to set the Model and Area field of the new layouts). It also reads all the placeholders that are included for each layout, and does the same for these.
Step 2: ResolveLayout
With the above done, we've almost gotten all the way to the finish line:
- We can resolve layouts in JSS
- We include layouts in the import-manifest in JSS
- We generate (or update) layouts and placeholders based on the import manifest in Sitecore
We have one step left:
- Discarding the manual ID -> Layout file handling we created in part 1 in favor of a fully automatic workflow.
To get started with this, we need to make the Layout Service tell us the name of the layout. By default, it includes the layout ID, but we don't decide the ID in JSS and our layout components have no idea what their ID is, we can't create a connection based on it. There are two different properties by default in the Layout service response: Context and Route. To be quite honest, I would prefer to have the layout info in the Route object. However, the context object is much easier to extend since it's managed in full by a pipeline. The Route object is not. So I simply followed the official JSS docs on extending the getLayoutServiceContext pipeline, and created below processor that includes the layout data in the context object instead. If you're looking to one-up me and create a better solution to this, I recommend you take a look at Corey Smith's post about extending the Layout service rendering data.
Anyways, my solution will take us part of the way. We still need to adjust this on the client side in JSS (which is what we will do in the next part).
And to get both of these processors running, we create a good old fashioned config patch:
This is all available on my github aswell.
I'll look at how to utilize the layout name we are now getting from the Layout Service to auto-generate the layout-map of the layout factory we previously created in JSS, and I'll also make sure that this works in disconnected mode (were we have no contact with the actual Layout Service). Check it out!
18 Jan 2019, by Bonny Nilsson |
Sitecore 9.1, JSS, Deployment, Layouts, Pipeline, Import, Code-first