Creating A SPA Aware Link Within The Quick Navigator When Building A Hybrid Episerver React Application
In this tutorial, you will learn how to create a link within the quick navigator that redirects a content editor to the pages of the current edit mode within Episerver. This article is assuming that you are using .NET to load the page layout and have the server-side quick navigator rendering on the page:
The interesting part of this tutorial is not creating a custom the link within the navigation bar. How to do this has been documented numerous time. The interesting part is hooking a single-page application up with some backend C# code. To combine state-managed within a React.js application - using the Episerver content API - with some backend C#.
When you create a React.js application as the headless solution for Episerver it is likely that you will use React router to manage the routing within the SPA. This makes creating a link in the quick navigator complicated. You can not tell from the current HTTP context what page the user might be viewing.
Having a headless React application that talks to the Episerver context API will require the state to be managed somewhere within the browser. It is likely you would use Redux or potentially React context with a hook. This poses a problem. The code to create a quick navigation link will need to be C# code. The C# code will not be able to access the internal React state.
- A variable on the global window
- Within local storage
Assuming you wanted to use the global window, you could use this:
Granted the code above is slightly hacky. This is the only way to solve this problem if you want to integrate within the Episerver quick navigator. A clean approach might be to create a completely new navigator yourself, however, this will involve more effort. In the code above, first, the editor URL is retrieved using the PageEditing helper. I'm using the RootPage as a placeholder. The page will never link here. you could change this to be anything you want. The actual current page ID will be read in using JS.
In this tutorial, you will learn how to create a higher-order component using React.js that will enable inline editing mode to work within preview mode. This tutorial is part of a series of posts about using Episerver as a headless CMS with React.js. In traditional Episerver MVC rending, using the Propertyfor() helper would traditionally handle wrapping any Episerver component with all the correct attributes to allow the inline editing function to work.
When you use Episerver within a headless context all of the responsibility for making things like getting inline-editing to work is up-to-you. This means it up-to-you to write the frontend to intergrate with Episerver correctly. You will need to apply the the correct attributes on all components.
In order to make inline editing work you will need to decorate every Episerver property with the 'data-epi-edit' attribute when in edit mode. Addding this code onto every compoent would violate the DRY prinicple. When working with React.js the best way to apply this functionailry is with a high-order-component. Explaing what a HOC is and how you can implment it within React is outside the scope of this tutorial, to find more information read this:
The first task to get inline editing to work is to determine if edit-mode is currently enabled for the current request. Let's begin...
How To Get Edit Mode
Within C# you can determine if a request is in edit mode in a few different ways. There are some useful helpers like, 'PageEdititng'. In the music festival site, you can find this code:
The Higher-Order Function
To create a higher-order component code that can be wrapped around a component is fairly simple. The purpose of the HOC is to apply the correct attribute if 'editMode' is enabled. The end HTML that you want to render will need to look something like this - where 'mainContent' is the main of a property of type rich-text:
The code to accomplish this could look like this:
Pass in 'editmode'. Pass in the components name 'mainContent'. The component will be the react component/. For this example, the component would render the rich-text property on a page.
Tips In case Inline Editing Does Not Work
If you want the block preview mode to work you will need to implement a special block preview controller. If you do not know how to do this, then you can find out more in this tutorial, 'How To Preview A Block In Episerver'.
Within the block preview if the attribute is being rendered but inline editing does not work. Using inspector, check the containing element. If the containing element also has the data-epi-edit attribute then this may break inline editing.
In this tutorial, you will learn about some of the APIs that are available when using Episerver as a headless CMS via the content delivery API. Traditionally, when working with Episerver you to render pages and blocks on a website you would use out-of-the-box C# razor helpers to render. In the new world, all pages and blocks are rendered by reading data returned from a JSON API.
To enabled content API, install the Nuget package 'Episerver.ContentDeliveryApi'.
After installing the plug-in, you will need to givethe ContentApiRead role read-access to the homepage and all of its children (assuming the whole site is avaliable to the API). Within the Episerver admin area, under 'Set Access Rights', nsure the ContentApiRead role has 'read' and 'Apply settings for all subitems' are both enabled.
Next, you will either need to create or modify the WebAPi config, like so:
Which will need to be registered within global.ascx:
Next, you will need to configure the API. This can be done within a C# initlisatoin module, like so:
The code above makes the API public so anyone can query it. It also enables a special site definition API. This is useful for debugging at the start. Enabling it will allow you to test that the content API is working. To check the site definition API you can access it like this:
This will return a bunch of data, including siteSettings, language selectors, currencies etc.. If you want to query the API for a specific page or block, you can query it using the content API:
If the content exists, the API will return some corresponding JSON, like so:
In this tutorial, you will learn some performance tips that you can apply to the content API to help improve your website's performance. Recently, I have been working on a React SPA that is powered by the Episerver Content API. As more content was added into the CMS the performance of the content API ground to a halt. Some requests would take over 10 seconds to return. If you looked at the API's response header you will notice the cache-control header is not set by default, as you can see:
One way to fix that is to set the cache headers in the response. Within C# you create an attribute similar to this:
You can register the attribute within a WebApiConfig like this:
Just in case you did not know, you register the WebApiConfig within the 'global.ascx' like so:
Adding this will add the cache headers. this is will help the client, however, you will notice this strange header called 'cf-cache-status: DYNAMIC'.
If you look at the Cloudflare website, here, you can see that dynamic means the resource was not cached by default and your current caching configuration doesn't instruct Cloudflare to cache the resource. How come?
By default, Cloudflare/DXP is configured to only cache content that has a file extension. Assets like images that obviously have file extensions, like a png or a jpg ca be cached easily. If you want Cloudflare to respect the responses cache headers on a page or API request then you will need to Episerver support to create a 'Page Rule' rule for you. The page rule can pattern match on URL so you can rules that specifically target the content API. I suggest you add rules for:
https://www.website.com/api/episerver/v2.0/site?language=en https://www.website.com/?expand=*If the page rule has been set-up correctly you should see a HIT on the cf-cache-status, like so:
Armed with some caching will mean the number of requests that get sent to the origin will be dramatically reduced. You will need to figure out what cache durations you will need to add to the site.