# Integration of ServiceWorker

# Purpose

This section aims to provide developers a comprehensive guide for integrating and consolidating the built-in ServiceWorker functionality in the SDK at the application layer. It addresses the ServiceWorker conflict issues and common problems.

Although the browser allows multiple Service Workers to be registered in the same domain, these Service Workers must have different scopes. In this way, each Service Worker can independently control the resources under different scopes. However, MessageWorker.js occupies a scope (default is '/'), which will cause the application layer's Service Worker to fail to register successfully in the same scope. Therefore, when the Service Worker at the application layer needs to share the same scope with the SDK's built-in MessageWorker.js, they need to be merged into a single file.

This section will introduce how to merge and customize parameters related to Service Worker configuration.

# Introduction to ServiceWorker

Service Worker is a script that runs in the background of a browser, which can be used to implement offline capabilities, push notifications, background synchronization, and other features. After the webpage is fully loaded, it operates in the background and can intercept network requests, cache resources, and provide other functions.

Key features of ServiceWorker:

  • Offline Capabilities: ServiceWorker can cache resources, allowing users to access websites even when the network is disconnected.
  • Push Notifications: ServiceWorker can receive push notifications from the server and display messages to the user.
  • Background Synchronization: ServiceWorker can perform tasks in the background, such as uploading data or updating data.
  • Network Interception: ServiceWorker can intercept network requests and process them as needed, such as caching data or modifying request headers.

# Overview of MessageWorker.js

MessageWorker.js is a Service Worker script provided by the SDK to implement synchronous communication in the Web Worker layer. Since MessageWorker.js occupies an independent scope, when the application layer's Service Worker needs to use the same scope, the two need to be merged into a single file.

# Environment Setup

Before starting to integrate Service Worker, please ensure your development environment meets the following requirements:

  • Browser supporting Service Worker: Ensure your target browser supports Service Worker, such as Chrome, Firefox, and Edge. For more specific information, you can refer to Can I use (opens new window).

  • @foxitsoftware/foxit-pdf-sdk-for-web-library: The version must be 10.0.0 or higher, and the lib directory should contain the MessageWorker.js file.

  • HTTPS support: Your website must be accessed via HTTPS to use Service Worker. However, there are exceptions for the development environment. localhost and 127.0.0.1 can use Service Worker without enabling HTTPS access.

# Registration and Configuration of Service Worker

Starting from 10.0.0, a new messageSyncServiceWorker (opens new window) parameter has been added to the PDFViewer constructor arguments, used for specifying the registration method of the Service Worker.

There are two ways to use messageSyncServiceWorker:

  1. Method 1: Specify url and options:

    • url is the registration path for the Service Worker;
    • options are the registration options for the Service Worker, you can refer to the specific description in MDN (opens new window).
    const viewer = new PDFViewer({
        messageSyncServiceWorker: {
            url: '/your-service-worker.js',
            options: { // Optional
                scope: '/foxit-lib/'
            }
        }
        // ... Other parameters
    })
    
  2. Method 2: Specify registration:

    • registration is the Promise<ServiceWorkerRegistration> object returned by the navigator.serviceWorker.register() method.
    const viewer = new PDFViewer({
        messageSyncServiceWorker: {
            registration: navigator.serviceWorker.register('/your-service-worker.js', {
                scope: '/foxit-lib/'
            })
        }
        // ... Other parameters
    })
    

Method 1 will be determined by the SDK internally as to when to register the ServiceWorker. If you need to manually control the registration of the ServiceWorker, you must use method 2.

In the SDK release package, we have provided a complete example (/examples/PDFViewCtrl/integrate-service-worker). You can directly refer to its implementation and run and view the effects according to the README.md document.

# Service-Worker-Allowed Response Header

By default, the max scope allowed by a Service Worker is determined by its script location. Specifically, the scope of the Service Worker can only cover the directory where its script is located and its subdirectories. For example, if the Service Worker script is located at https://example.com/sub/worker.js, it can only control resources under https://example.com/sub/ and its subpaths by default. If you forcibly specify the scope parameter to a larger scope, it will lead to the failure of the Service Worker registration, and the error message will be: The path of the provided scope ('/') is not under the max scope allowed ('/sub/').

However, in some cases, you may want to expand the scope of the Service Worker so that it can control resources within a larger range. At this point, the Service-Worker-Allowed response header becomes particularly important. By configuring this response header, you can specify a broader path, allowing the Service Worker to be effective within a larger scope.

# Configuring Service-Worker-Allowed Response Header

To use the Service-Worker-Allowed response header, you need to include the following field in the HTTP response header of the Service Worker script. Its value is the max scope path allowed:

Service-Worker-Allowed /;

# Nginx Configuration Example

If you are using Nginx as your server, you can include the Service-Worker-Allowed response header by modifying the Nginx configuration file. Below is a configuration example:

server {
    location /sw.js {
        add_header Service-Worker-Allowed /;
    }
}

# Webpack Dev Server Configuration Example

If you are using Webpack Dev Server for local development, you can include the Service-Worker-Allowed response header by configuring devServer. Below is a configuration example:

// webpack.config.js
module.exports = {
    //  Other configurations
    devServer: {
        headers: {
            'Service-Worker-Allowed': '/'
        }
    }
};

# vue.config.js Configuration Example

If you are using Vue CLI, you can adjust the Webpack Dev Server by modifying vue.config.js. Below is a configuration example:

// vue.config.js
module.exports = {
    devServer: {
        headers: {
            'Service-Worker-Allowed': '/'
        }
    }
};

# Special Request Address

In the fetch event listened by the Service Worker in the application layer, if the request address matches __foxitwebsdk-syncmsg__, please ignore this request directly. This is also mentioned in our example code (examples/PDFViewCtrl/integrate-service-worker/src/service-worker.js).

# Common Questions and Troubleshooting

  1. ServiceWorker Not Registered

    • Issue description: Unable to find the ServiceWorker registration results in the developer tools.

    • Possible reasons:

      1. The path is set incorrectly, and the Service Worker js request returns 404 or other errors;
      2. The browser does not support ServiceWorker;
      3. The HTTPS protocol is not enabled. For security reasons, ServiceWorker can only be used under the HTTPS protocol. An exception to this is localhost and 127.0.0.1, which do not require HTTPS.
    • Solutions:

      1. Check the Service Worker's registration code and path configurations.
      2. Check browser compatibility. For Service Worker compatibility, please refer to Can I use (opens new window).
      3. Enable HTTPS protocol.
  2. ServiceWorker Registration Failed

    • Issue description:A prompt during registration indicates that the scope exceeds the max scope allowed. Example of error message:
        register a ServiceWorker for scope ('http://localhost:9899/') with script ('http://localhost:9899/lib/MessageWorker.js?b=http://localhost:9899/__foxitwebsdk-syncmsg__'): The path of the provided scope ('/') is not under the max scope allowed ('/lib/'). Adjust the scope, move the Service Worker script, or use the Service-Worker-Allowed HTTP header to allow the scope.
    
    • Possible reasons: The registration path or scope of the Service Worker is not set correctly. It should be noted that the max scope allowed by the Service Worker depends on the location of the Service Worker script itself (refer to: MDN (opens new window)).

    • Solutions:

      1. Understand the scope rules of Service Worker;
      2. Check the registration code and scope settings of Service Worker;
      3. Adjust the scope of Service Worker, that is, modify the scope (opens new window) parameter;
      4. Adjust the Service-Worker-Allowed HTTP response header to allow a larger scope;
      5. Check the path of Service Worker script and server configuration.
  3. ServiceWorker Registration Indicates Unsupported MIME Type

    • Issue description: A prompt during registration indicates an unsupported MIME type ('***/***'). Example of error message:
    Failed to register a ServiceWorker for scope ('http://localhost:5173/assets/') with script ('http://localhost:5173/assets/service-worker.js'): The script has an unsupported MIME type ('text/html').
    
    • Possible reasons: The registration path of the ServiceWorker is incorrect or the target file does not exist.
    • Solutions:
      1. Check the registration path of the ServiceWorker;
      2. Check if the target file exists;
      3. Check the server configuration.