Use Case
In one of the projects which use Sitecore JSS with Next.js, due to business needs, we needed to replace certain links starting with a particular path or rather in other words needed a patch for the Link fields. In this post, I am gonna explain how traditionally we do this and the next post explains how and why we did it another way.
Traditional way
Replacing links is not a new thing and there are many articles out there that explain how it can be done in 2 step process.
Anyways to explain it, We need a new custom renderField pipeline processor and then patch it either after Sitecore.Pipelines.RenderField.GetInternalLinkFieldValue' or after all processors under <renderField>
in show config.
Below is an example stub of patching.
using System.Collections.Generic;
using Sitecore.Pipelines.RenderField;
using Sitecore.Xml.Xsl;
public class CuratedGetFieldContent : Sitecore.Pipelines.RenderField.GetFieldValue
{
public string Site { get; set; }
public List<string> Fields { get; set; } = new List<string>();
public void Process(RenderFieldArgs args)
{
// Do the null checks
// Check for Site in case of multisite
// Perform check for field type key that would be passed from config
args.Result = this.ReplaceLinks(args.Result);
}
private RenderFieldResult ReplaceLinks(RenderFieldResult argsResult)
{
this.ReplacePart(argsResult.FirstPart);
this.ReplacePart(argsResult.LastPart);
return argsResult;
}
private void ReplacePart(string argsResultString)
{
// do the business logic to compare specific path and replace with new API route
argsResultString.Replace("sourcePath", "targetApiPath");
}
}
Configuration File
<renderField>
<processor patch:after="*[@type='Sitecore.Pipelines.RenderField.SetAnchorsPositionInLinks, Sitecore.Kernel']"
type="[Redacted].Project.[Redacted].CuratedGetFieldContent, [Redacted Asssembly Name]">
<site>SiteName</site>
<fields hint="list">
<field>rich text</field>
<field>general link</field>
</fields>
</processor>
</renderField>
Another way was to patch layout service Field serializers but for that, we would have to do it on the shared repository which again goes against the purpose of patching to a specific site and not all sites.
Patch for Field Serializer (Stub) goes something like below
namespace [Redacted].Foundation.SitecoreExtensions.Pipelines.GetFieldSerializer
{
using FieldSerializers;
using Sitecore.Diagnostics;
using Sitecore.LayoutService.Serialization;
using Sitecore.LayoutService.Serialization.Pipelines.GetFieldSerializer;
public class GetCuratedLinksFieldSerializer : BaseGetFieldSerializer
{
/// <summary>
/// Initializes a new instance of the <see cref="GetCuratedLinksFieldSerializer"/> class.
/// </summary>
/// <param name="fieldRenderer">The field renderer.</param>
public GetCuratedLinksFieldSerializer(IFieldRenderer fieldRenderer) : base(fieldRenderer)
{
}
/// <inheritdoc/>
protected override void SetResult(GetFieldSerializerPipelineArgs args)
{
Assert.ArgumentNotNull(args, nameof(args));
args.Result = new CuratedLinksFieldSerializer(this.FieldRenderer);
}
}
}
Configuration file
<pipelines>
<group groupName="layoutService">
<pipelines>
<getFieldSerializer>
<processor type="[Redacted].Foundation.SitecoreExtensions.Pipelines.GetFieldSerializer.GetGeneralLinkFieldSerializer, [Redacted Assembly Name]" resolve="true" patch:before="*[@type='Sitecore.LayoutService.Serialization.Pipelines.GetFieldSerializer.GetDefaultFieldSerializer, Sitecore.LayoutService']">
<FieldTypes hint="list">
<fieldType id="1">general link</fieldType>
</FieldTypes>
</processor>
</getFieldSerializer>
</pipelines>
</group>
</pipelines>
Because these two ways didn’t fit our criteria we would have to now look into fixing this from the Next.js app. We will look into it in the next part.