The Main Module: Always-Included Extension Functionality

First, a refresher. Adobe Experience Platform Launch allows users to quickly and easily implement marketing technologies on their websites and apps. It is also a platform. Marketing technology vendors can build extensions on the platform that make it easier for businesses to install and configure the vendor’s technology on their websites.

This post is intended for extension developers who already have at least a basic understanding of what a Launch extension can do and how it is composed. If you’re unfamiliar with extension development, I recommend starting out by reading our extension development documentation or watching this video on extension development.

The case for always-included extension functionality

In our previous article, Build Optimization Through Minimal Inclusion — particularly the “Behind the Curtain” section — we discussed how the Launch build system determines what should be included in the build output. If you haven’t read it yet, go read it and come back when you’re done. I’ll wait.

Done? Okay, great. It’s very important to understand that even if your extension is installed on a Launch property, only a portion of your extension’s library code may end up being shipped to the Launch user’s website.

As you may have reasoned from the article, it would seem that if the Launch user installs your extension on a property but never uses an event type, condition type, action type, or data element type provided by your extension, then zero code from your extension would be included in any build output. But what if your extension needs to provide functionality on a Launch user’s website even when no event type, condition type, action type, or data element type from your extension is used? You may even wonder when this case would occur.

Let’s assume you and I sell a technology that captures how website visitors move their mouse around or scroll up and down while browsing content on websites. We track this type of data on our customers’ websites and then provide our customers heatmaps showing where visitors spend their time and focus.

Let’s also assume we’re building a Launch extension that allows Launch users to quickly and easily install our interaction-tracking technology on their websites. It’s reasonable to consider that our extension might provide two action types that allow the user to control when recording should start and stop: Start Recording and Stop Recording. The library module for our Start Recording action type might look like this (review action type documentation if needed):

var recorder = require('./recorder.js');
module.exports = function(settings) {
recorder.startRecording();
};

The library module for our Stop Recording action type might look like this:

var recorder = require('./recorder.js');
module.exports = function(settings) {
recorder.stopRecording();
};

Both of these action types leverage a module called recorder.js that contains our logic that records user interaction.

Using what we learned in Build Optimization Through Minimal Inclusion, we can conclude that if the Launch user uses either the Start Recording or Stop Recording action types, our recorder logic will be included in the build output. If the user does not use the Start Recording or Stop Recording action types, our recorder logic will not be included in the build output. This should seem fairly reasonable: If a recording is never going to happen, then there’s no reason to bloat build output with recording logic that will never provide value.

But what if our technology doesn’t provide customers the ability to control when to start or stop recording? Perhaps we’ve received customer feedback that they don’t want to deal with that kind of control or perhaps we’re a startup in the early stages and we just haven’t had the resources to implement this kind of control within our recorder logic yet.

Whatever the reason to not provide control to start and stop recording, let’s assume our recorder code is designed in such a way that it always just starts recording as soon as it’s loaded on the page and then stops recording as soon as the user navigates away from the page. If this were the case, our extension wouldn’t provide Start Recording or Stop Recording action types. But if our extension doesn’t provide these action types, the code inside ofrecorder.js would never be included in the Launch build output!

For this reason, we provide the ability to define a “main module”.

Defining a main module

Hopefully, I’ve clearly demonstrated a case where we may want a piece of code to always be included in Launch build output even when the property doesn’t use an event type, condition type, action type, or data element type from our extension. For these cases, we reference the module we always want to be included from our extension.json using the main attribute:

{
...
"main": "src/lib/recorder.js"
}

With this in place, the code inside ofsrc/lib/recorder.js will always be included in a property’s build output (assuming the extension is installed and added to the library) and executed when the Launch library is loaded on the website.

With great power comes great responsibility

The benefit of a main module is that it’s always included within a property’s build output. The drawback of a main module is that it’s always included within a property’s build output. See what I did there? Don’t use a main module just because you can; use a main module only when you absolutely need to in order to provide the functionality the Launch user is expecting when your extension is installed. We try hard to keep build output slim and trim for our users. Please support us in these efforts.

If you have related questions, feel free to ask in the comments below. Now go build something great!