MarkLogic World 2020 Live Keynote – Register Now

JavaScript Modules in MarkLogic 10

In this 3-part blog series, we’ll be reviewing over some of the new features of MarkLogic 10, such as:

  1. The addition of JavaScript Modules, also known as MJS.
  2. V8 Engine upgrade from version 5.3 to version 6.7. This is the actual motor that ‘powers’ JavaScript in MarkLogic.
  3. Additional features from the ECMAScript 2015 JavaScript standard have been added. Go to http://www.ecma-international.org/ecma-262/6.0/ to find out what you can do with ECMAScript 2015.

In this first blog of the series, we’ll discuss destructuring assignment and compare the differences between JavaScript Modules (MJS) and Server-side JavaScript (SJS) by working through some examples. We’ll also discuss some of the advantages of upgrading to MarkLogic 10.

In the next blog, we’ll discuss in detail about the new API’s the V8 Engine upgrade comes with. And after that, we will discuss another piece of functionality that was included in the upgrade, Object Rest and Spread Properties, and how they can be used in your Data Hub code. So if you’d like to see all the new things you can do with JavaScript in MarkLogic 10, stick around!

Now let’s get started with an introduction to JavaScript Modules.


Destructuring Assignment

Let’s jump in with some typical MarkLogic 9 code:

const validator =
require("/lib/validator.sjs")

validator.isValidZipCode("10001")
validator.isValidPostCode("6025")

In this example, you require the "/lib/validator.sjs" SJS script and assign that to the validator variable. Then, you can use the functions from the "/lib/validator.sjs" SJS script in your code by referencing the validator variable. Although this seems simple enough, with destructuring assignment, the syntax becomes even more concise:

const { isValidZipCode, isValidPostCode } = require("/lib/validator.sjs")

isValidZipCode("10001")
isValidPostCode("6025")

Now, you can use the functions without having to specify the validator prefix. And this gets even more concise again when you use MJS modules:

import { isValidZipCode, isValidPostCode } from "/lib/validator.mjs";

isValidZipCode("10001")
isValidPostCode("6025")

Using the new syntax, you simply import the functions you want to use. In this case, we want the functions isValidZipCode and isValidPostCode, imported from the file "/lib/validator.mjs". Now, you can use the functions without having to specify the validator prefix.

SJS vs MJS

Now let’s take a look at what the differences are in the actual script. For example, your typical SJS script might look something like this:

function isValidZipCode(code) {/*...*/}
function isValidPostCode(code) {/*...*/}

module.exports = {
  isValidZipCode: isValidZipCode,
  isValidPostCode: isValidPostCode
};

So we have functions, isValidZipCode(code) and isValidPostCode(code), and a module.exports declaration where you declare what you actually want to export for use by the client.

If we look at MJS, the code is actually quite similar, but much more concise for declaring the exports:

function isValidZipCode(code) {/*...*/}

function isValidPostCode(code) {/*...*/}

export { isValidZipCode, isValidPostCode };

Advantages of MJS

One of the main advantages of going from using SJS to MJS is that your code executes faster. This is because SJS scripts are loaded for every single request, whereas MJS modules are loaded once into a global module cache and shared between requests, thus improving performance.

In other words, SJS scripts cannot be shared across multiple MarkLogic requests. Once you load an SJS script, it’s unique to that request, and you can’t actually share it with multiple requests. If a request includes a require in the script, it has to be loaded every time.

However, with MJS, scripts can be shared by multiple MarkLogic requests. So if you have code that’s executed repeatedly, it should execute faster as you don’t have to load the code with each request.

How to Upgrade from SJS to MJS

Firstly, you need to rename the extension from .sjs to .mjs. Then, you need to change your module exports from the SJS syntax from:

module.exports = {
  isValidZipCode: isValidZipCode,
};

to the more concise MJS code here:

export { isValidZipCode }

Then, convert the SJS require step from:

const validator =
require("/lib/validator.sjs")

to use the import declaration in your MJS:

import * as validator =
from "/lib/validator.sjs";

Alternatively, you can specify exactly which functions you want imported, e.g.:

import { isValidZipCode, isValidPostCode } from "/lib/validator.mjs";

Data Services Changes Required

If you’re using Data Services, note that it generates the code for you and you may need to do some tweaking. For instance, if you had the following in your data service .sjs file for an input parameter param1:

var param1;

You would need to change it to the following in your .mjs file:

const param1 = external.param1

Also if you have already generated the Java client code, you will need to change it. For example, if you had a search function (search.sjs) in SJS, you’ll need to point it to the new MJS file (search.mjs).

@Override
public reader search(String q, ...) {
    return BaseProxy.JsonDocumentType.ToReader(baseProxy.request("search.sjs, ...)
@Override
public reader search(String q, ...) {
    return BaseProxy.JsonDocumentType.ToReader(baseProxy.request("search.mjs, ...)

Dynamic Module Loading Impact

One thing to be aware of is that you cannot load JavaScript modules dynamically in MarkLogic. For example, you can do the following in SJS:

let lib = someCondition() ?
       require("/lib/foo.sjs") :
       require("/lib/bar.sjs")

But you cannot do the equivalent using MJS in MarkLogic.

V8 JavaScript Engine Performance Improvement

All-in-all, one of the best reasons to move to MarkLogic 10 as soon as you can is that the actual engine itself (V8) has seen an improvement in performance, particularly for the most commonly used functionality (e.g. String and Array operations). With this increased engine performance, codebases that make heavy use of JavaScript should experience a performance gain.

Next Steps

We just walked through destructuring assignment, the differences between SJS and MJS, and found out why upgrading to MarkLogic 10 and using MJS can speed up the execution of your code. You can read up more about Server-Side JavaScript in MarkLogic in our JavaScript Reference Guide.

In the next blog in our series, we will go over the details behind the V8 Engine Upgrade with MarkLogic 10 and some of the new functionality that comes with the new APIs. After that, we’ll walk through the new Rest and Spread Properties functionality.

This website uses cookies.

By continuing to use this website you are giving consent to cookies being used in accordance with the MarkLogic Privacy Statement.