In Experience Editor, your browser would read your <link>
tag and attempt to fetch https://cm.sc101.com/styles/main.css
which won’t not exist. What you want is https://app.sc101.com/styles/main.css
.
Well, it did! In Sitecore Headless Services 14.0, this remapping was on the endpoint that Experience Editor used (the /jss-render
one from earlier) before the HTML was rendered in the Experience Editor. Therefore, you had to configure the URL of the rendering host in your rendering host application configuration.
If you looked at Part 2 of my Sitecore Headless Development series, there were a few lines of code in Startup.cs
to enable Experience Editor support that looked something like this:
services.AddSitecoreRenderingEngine(options =>
{
...
})
.ForwardHeaders()
.WithTracking()
.WithExperienceEditor(options =>
{
if (Configuration.RenderingHostUri != null)
{
options.ApplicationUrl = Configuration.RenderingHostUri;
}
});
Here, in the options of .WithExperienceEditor()
, you’d set the URL of your rendering host so that the Experience Editor could rewrite any relative URLs in your rendering host with an absolute URL with the correct hostname. It’s doubly important if your rendering host application is in a separate network than your Sitecore instance or has some special DNS resolution with a reverse proxy or something. The headless endpoint then uses this to rewrite your relative URLs with absolute URLs for Experience Editor.
This is where things changed in Sitecore Headless Services 16.0. As Sitecore Headless Services starts supporting more and more languages and SDKs (ASP.NET Core, React, Next.js, etc) it made more sense for this logic to happen on the CM server instead of being implemented in every flavor of headless SDK. You’ll notice now that Sitecore.AspNet.ExperienceEditor.ExperienceEditorOptions
no longer contains a property called ApplicationUrl
- so compiling your rendering host against 16.0 will throw a compilation error. Since you don’t have to set any options in that extension method, you can now call .WithExperienceEditor()
with no parameters.
services.AddSitecoreRenderingEngine(options =>
{
...
})
.ForwardHeaders()
.WithTracking()
.WithExperienceEditor();
So where does that property get set now? Thanks to the insight provided by Nick Wesselman, there is a new attribute in your headless app Sitecore configuration called serverSideRenderingEngineApplicationUrl
which is where you would set the URL for your rendering host. This attribute is in the configuration/sitecore/javaScriptServices/apps/app
config node that you created for your headless application initially. For those of you using SXA, this is a new field on the Settings
item on your site.
So, your config should look something like this:
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/" xmlns:set="http://www.sitecore.net/xmlconfig/set/">
<sitecore>
<javaScriptServices>
<apps>
<app name="renderingHost"
sitecorePath="/sitecore/content/SC101"
serverSideRenderingEngine="http"
serverSideRenderingEngineEndpointUrl="http://app/jss-render"
serverSideRenderingEngineApplicationUrl="https://app.sc101.com"
inherits="defaults" />
</apps>
</javaScriptServices>
</sitecore>
</configuration>
You’ll notice that the hostname for the endpoint URL and the application URL could be different here - the endpoint URL can be the internal DNS for your rendering host. If your CM server can communication with your rendering host with a private DNS resolution (e.g., Kubernetes), this would be the place to put your private domain name. The application URL has to be publicly (or at least as public as your CM hostname is) resolvable as that’s the URL that your browser will use.