Working disconnected in JSS

Abstract

Defining route data and customizing data in JSS code-first, disconnected development

To support working disconnected and deploy the data to Sitecore later, you must define your app data without Sitecore, by generating a manifest with the Manifest API.

The manifest is a JSON file representing your data in a format that can be imported into Sitecore using the App Import API or used to host the app in disconnected mode.

When working disconnected you use the code-first development workflow.

Tip

Your app can utilize a Sitecore-first development approach, in which case you do not need to generate an app manifest. Developing Sitecore-first requires a Sitecore instance to run the app.

We recommend using code-first for the initial deployment of a JSS app to Sitecore, even if not using the pattern after that, to save time setting up items for your JSS application.

Defining route data

Route data is used to represent the routes served by your app when running in disconnected mode. The Placeholder component, and any components that it renders, expect route data to adhere to a specific schema.

For disconnected development, route data is typically retrieved from static YAML or JSON files, or simple JavaScript files. For connected development or production, the route data is retrieved using calls to the Sitecore Layout Service (through HTTP requests, or in-process for integrated mode SSR).

The sample apps define route data in /data/routes by using YAML files. You can choose to use JSON files instead if you prefer that format (just rename the file to .json and run the content through a YAML-to-JSON converter). YAML supports comments, multiline values, and other features that improve the content authoring experience.

You can create a route type with fields or add additional root placeholders in a code-first JSS sample app when working.

Customizing data in disconnected mode

When disconnected mode starts up, it creates a mock version of the JSS services that can run in connected mode on Sitecore.

These mock services might need to be customized to account for server-side customizations to Layout Service, so that disconnected mode receives the same customizations.

The disconnected mode proxy

The disconnected mode starts up a local HTTP server to run the mock APIs. This is defined in the sample apps in scripts/disconnected-mode-proxy, and this is what is customized when you want to alter the disconnected mode data.

The default disconnected mode proxy comes with a number of options to customize its data. The sitecore-jss-dev-tools package exports the DisconnectedLayoutServiceOptions TypeScript typing that documents the full array of options and their signatures. TypeScript-aware editors, like VS Code, enable reading this metadata even if the file is not TypeScript.

const proxyOptions = {
  appRoot: __dirname,
  appName: config.appName,
  watchPaths: ['../data'],
  language: config.language,
  port: 3042,
  compilers: ['@babel/register'],
  ...
};

Customizing the context

When customizing the Layout Service context on the Sitecore side, you might want to apply similar customizations when disconnected. The customizeContext hook allows you to do that:

const proxyOptions = {
  appRoot: __dirname,
  customizeContext: (context, route, currentManifest, request, response) => {
    return { myCustomContextProperty: 'helloworld', ...context };
  },
  ...
};

Customizing component data

When customizing component data using Rendering Contents Resolvers or Integrated GraphQL in Sitecore, you might want to apply similar customizations when disconnected. The customizeRendering hook allows you to do that:

const proxyOptions = {
  appRoot: __dirname,
  customizeRendering: (rendering, rawManifestRendering) => {
    // mock integrated GraphQL results for a specific component name
    if (rendering.componentName === 'ContentBlock' && rendering.fields) {
      rendering.fields = {
        data: {
          item: {
            id: 'mock-graphql-result-id',
            heading: {
              jss: rendering.fields.heading,
            }
          }
        }
      };

      return rendering;
    }

    // customize data based on a flag value added to the component definition on the route
    // i.e. in YAML, 
    // - componentName: Whatever
    //   addCoolStuff: true
    if (rawManifestRendering.dataSource.addCoolStuff) {
      return {
        coolStuff: [
          'React',
          'Vue',
        ],
        ...transformed,
      };
    }

    // returning falsy will cause JSS to use the default value
    return undefined; // is a function
  },
  ...
};

Advanced customizations

The disconnected server in sample apps defaults to using the createDefaultDisconnectedServer() helper function. This function provides basic customization APIs and encapsulates the registrations of several middlewares that make the disconnected server work. You can also unpack the function and register the middleware yourself if you want to do advanced customizations that are not supported by the default DisconnectedServerOptions.