JSS (React) Dynamic Layouts - Part 2: Include layouts in the import manifest

We've enabled dynamic layouts, and we've seen how to patch JSS pipelines. Now we want to include layouts in the app deployment in order to enable code-first workflow.

EDIT: This was originally part 3, but what was previously part 2 is really more of a general how-to on patching frontend pipelines in JSS and not about this particular implementation. However, I do recommend you to check it (what is now part 1.5) out here.

Let's recap. In part 1 of this series we looked at how to resolve layouts from Sitecore, instead of using a hardcoded global one. In part 1.5 we took a look at how to extend a JSS pipeline. In this part we will look at how to apply a pipeline extension to include layouts in the import manifest (sitecore/manifest/sitecore-import.json). This file is generated by JSS via a generateManifest-pipeline that is invoked when you run jss manifest (which is part of the script when you execute any deploy-related commands). 

Restructuring for metadata

We need to start by exposing some metadata for every layout we create, which we can include in the manifest. My first thought was just to export this alongside the layout react-component, so as to keep the module cohesive. However, I ran into some trouble with this approach. The jss commands are being run with a babel interpreter, they do not however include the babel react interpreter. This means that if there is any JSX (react-markup) code exported anywhere down the import-chain (even if you never actually do anything with the exported component) it will result in a crash when you try and run any jss scripts, in our case jss manifest. Like below:

jsxparseerrorlog

Long story short, we can't export the layout metadata from the same module that we export our component from.

So, I restructured a bit. Instead of putting the layout-files directly under src/layouts, I put them in separate folders. For example, src/layouts/TestLayout.js would now be in src/Layouts/TestLayout/TestLayout.js. Then I create a Metadata.js file beside each layout file in their respective folder (If you're feeling lost at this point, revisit part 1). From there, I export the layout metadata as below.

testlayout-metadata

I have two layouts at this point, each with their own metadata file. To finish this step up I create sort of an index file, but for the metadata file. Remember, I cannot include the metadata exports in the actual index.js file, since that would mean that there is one link in our import chain (starting from our custom pipeline patch, that we will create in the next section) that imports a react-component. So alongside the index.js in the src/layouts folder, I create metadata.js

metadata-index

My file structure for layouts now look like this:

Layouts file structure

Now we have what we need to get to pipeline patchin'.

Pipeline patch: generateLayouts

In this section we'll modify the example patch we created in part 1.5. If you haven't gone through that part already, now is a good time. Or, you can simply copy the below code and put it in a new file under sitecore/pipelines, just make sure your filename adheres to *.patch.js.

I'm not going to go through this in detail. Essentially, we import the metadata from the metadata file we just created, and then we iterate over this adding each one to the pipelineResult that we export. This will include it in the manifest JSON. Simply make sure your generateLayouts.patch.js file looks something like this:

generateLayoutspatch

And you're done! To verify that everything is working as expected, run jss manifest from the root of your app, make sure it doesn't crash, then verify that your sitecore/manifest/sitecore-import.json file contains a layouts section, containing the metadata for your layouts (In my case, the DefaultLayout and the TestLayout).

Next up, extending the import pipeline in Sitecore to create layout items based on the manifest.

16 Jan 2019, by Bonny Nilsson | 

Sitecore 9.1, JSS, Layouts, Deploy, Import, Pipelines, Code-first