4

We would like to improve the frontend development experience in our Sitecore 9.2 solution and provide something like "hot reload", i.e. the frontend is built auto-magically and published to wwwroot, such that our frontend developers does not have to wait for the website to startup after each change to the frontend assets.

Background

We use webpack for our sass + javascript + react components.

We do not use Sitecore JSS.

Our Visual Studio solution is following Helix conventions (multiple small projects!).

Currently, our backend and frontend development process is following these steps:

  1. Manually compile code (backend + frontend)

  2. Manually publish to wwwroot

  3. Wait for app pool recycle

  4. Site startup

Question Does anyone have experience configuring "hot reload" for frontend development in a Sitecore solution, that they want to share?

5

For local testing of frontend code there is usually no need for building/publishing the visual studio solution. For your local dev environment, you have several options that will be a lot faster:

A) Symlink from Frontend build-dir to webroot

Set up a symbolic link in the local webroot and point that directory to the output of the frontend build. With webpack this would typically be a bundle in the /dist dir.

Example:

mklink /D "C:\inetpub\wwwroot\my-project.local\assets\mybundle" "c:\dev\myproject\dist\mybundle"

Make sure your assets are not cached by IIS throuhg web.config (only locally):

<configuration>
<location path="assets/mybundle">
    <system.webServer>
      <staticContent>
        <clientCache cacheControlMode="DisableCache" />
      </staticContent>
    </system.webServer>
  </location>
</configuration>

B) Use Nginx as local proxy

If your frontend project supports self-hosting, you can bypass requests to http://my-project.local/assets/mybundle to your self-hosted webserver i.E. http://localhost:1234

nginx.conf:

server {
   listen       88;
   server_name  my-project.local;

   location /assets/mybundle/ {
        proxy_pass  http://localhost:1234/dist/mybundle;
   }        
}

Now you can access the local site using:

http://my-project.local:88

Requests to frontend resources will be redirected to the self-hosted webserver.

C) xCopy command in conjunction with file watcher

First, set up a batch file for copying your frontend bundle to the IIS webroot i.E.

xcopy "c:\dev\myproject\dist\mybundle\*.*" "C:\inetpub\wwwroot\my-project.local\assets\mybundle"  /sy

Then set up a file watcher in the frontend build folder i.E. with this powershell script: https://superuser.com/questions/226828/how-to-monitor-a-folder-and-trigger-a-command-line-action-when-a-file-is-created

General: Referencing frontend assets

A general challenge with all of these options is referencing the generated .js and .css files in razor layouts. Webpack typically generates hash codes in the file names like

main.8cd6d964582176f0ac47.js 

A possible solution is to update hashes at runtime based on the files in the bundle directory:

public static IHtmlString Asset(this HtmlHelper helper, string content)
{
    var fileName = Path.GetFileName(content);
    var fileParts = fileName?.Split('.');

    if (fileName == null || fileParts.Length != 2)
    {
        return new HtmlString(content);
    }

    var extension = Path.GetExtension(content);
    var firstPart = fileParts.FirstOrDefault();

    var actualFileName = Directory.GetFiles(Server.MapPath("~/assets/mybundle/"), $"*{extension}").FirstOrDefault(f => Path.GetFileName(f).Split('.').FirstOrDefault() == firstPart);
    return new HtmlString(actualFileName);
}

In Razor views:

<script src="@Html().Asset('main.js')"></script>

I would only do this locally for performance reasons.

Summary:

These are just a few of many options. Personally, I have found option A (Symlink) to be the best if the frontend framework supports live building. Otherwise option B (Local Proxy) works best.

In any case, Frontend changes are immediately visible on the local site and no AppPool recycle is required. This greatly speeds up the frontend development process.

  • Wow! I only tested the first solution (A), since I dont have Nginx available, but that worked just perfect.Thank you! – Hos Dec 2 at 19:03
0

On top of the answer from Mark Lowe, also ensure that View Precompilation is done, and ensure the front end build / watch task copies the CSHTML file across to the web site.

This is the setting I have. Take a look at the environment that I have introduced which I labelled as LocalDeveloper.

<?xml version="1.0"?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/" xmlns:localenv="http://www.sitecore.net/xmlconfig/localenv/" xmlns:role="http://www.sitecore.net/xmlconfig/role/">
<sitecore role:require="Standalone or ContentDelivery or ContentManagement">
    <mvc>
        <precompilation>
            <assemblies>
                <assemblyIdentity name="ACME.Website" />
            </assemblies>
        </precompilation>
    </mvc>
    <settings localenv:require="LocalDeveloper">
        <setting name="Mvc.UsePhysicalViewsIfNewer" value="true" />
    </settings>
</sitecore>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.