Article
0 comment

Make Livereload on SharePoint Online possible

While working on a small side project on a Sunday, I asked myself the question. Is it possible to use live-reload when I developed a web part on SharePoint Online? I had to search for an answer for that and guess what? I found a solution.

This solution is not only for development but also for a production compilation of a SharePoint web part or extension.

Live-reload aka reload website once the code compilation finishes

Live-reload is one of the essential tools in the quiver of any web front end developers. There are professional tools like my favourite – Browsersync and other countless community-driven.

All these solutions use the WebSocket API.

The WebSocket API is an advanced technology that makes it possible to open a two-way interactive communication session between the user’s browser and a server. With this API, you can send messages to a server and receive event-driven responses without having to poll the server for a reply. – Source: MDN

So one or multiple web sites and browser register to a web socket backend server. This server that passes information around. Similar to a chat server does, but in this case, it can also send around more advance commands and action.

For example, please re-register a new version of CSS on a page (works without browser refresh) or refresh the whole browser window after the code got re-compiled.

How it works in local workbench

Livereload is part of the local build rig. When the build rig starts it registers itself as an HTTP service on the port 35729.
The local workbench opens a connection to this HTTP Service through a script that registered on the local workbench page.

//localhost:35729/livereload.js?snipver=1

This script automatically sends a hello to the service backend and waiting for new messages from the backend.

Once gulp has completed its job a gulp task to reload the page sends a request to this web socket service. That then forces all connected clients (local workbench) to refresh.

How to get this script running on SharePoint Online

As security and performance pre-caution this script does not exist on SharePoint pages. It lives on the SharePoint Online workbench (/_layouts/15/workbench.aspx) and reloads the page in case a code change happen.

Both local and remote workbench are great tools and support dynamic reloading. They are, in many ways, less optimal if you like to test and develop a web part under real-life conditions.

To make Livereload working, we can use a simple trick and add some code to or web part or extension, and this is the complete magic.

// create a new <script> element
let script = document.createElement('script');
// assign the src attribute to the livereload serve
script.src = "//localhost:35729/livereload.js?snipver=1";
// add script to the head section of the page
document.head.appendChild(script);

Technical it is DOM manipulation, and I wouldn’t recommend deploying a web part that contains this code, but it helps you to improve your workflow during development.

Once the Live-reload script reference is on the page, the script registers itself as a client to the server running on ‘localhost:35729’. That is the whole of magic. The rest is that your local code rebuild, fire the reload message against the server and force all user interfaces connected to reload.

Advanced usage

To make sure live-reload not in effect when the code ended up in a production build, we can enhance the registration a bit.

if (this.context.manifest["loaderConfig"]["internalModuleBaseUrls"][0]
                     .indexOf("https://localhost:4321") !== -1) {

  // create a new <script> element
  let script = document.createElement('script');
  // assign the src attribute to the livereload serve
  script.src = "//localhost:35729/livereload.js?snipver=1";
  // add script to the head section of the page
  document.head.appendChild(script);

}

The SPFx context object contains the manifest of the web part or extension. The manifest contains ‘loaderConfig’ and in there an array of ‘internalModuleBaseUrl’. Lastly, this property contains the URL where the webpart got served. For development, it provides ‘https://localhost:4321’.

If it is not a development build, then the URL get substituted at runtime to the real URL the web part served. You might like to wrap it in a function like this.

private registerLiveReload() {
  if (this.context.manifest["loaderConfig"]["internalModuleBaseUrls"][0]
                       .indexOf("https://localhost:4321") !== -1) {

    // create a new <script> element
    let script = document.createElement('script');
    // assign the src attribute to the livereload serve
    script.src = "//localhost:35729/livereload.js?snipver=1";
    // add script to the head section of the page
    document.head.appendChild(script);

  }
}

public render(): void {
  // register live reload
  this.registerLiveReload();

Livereload as Application Customizer

If you don’t like to add this code to all your custom web part, here is a smarter idea. Create an Application Customizer that uses the code from before and deploy it to your development tenant or development site collection.

This way you have live-reload already in place and don’t have to worry in your web part or extensions code. At some point, it will be nice to see that the assembly loader, which is the component that runs the web part on the page, would detect from where the manifest is loaded.

If served from localhost, the Live-reload get added to the page automatically.

Have fun using it for now!

Leave a Reply

Required fields are marked *.


This site uses Akismet to reduce spam. Learn how your comment data is processed.