Calling PnP JS from a TypeScript Azure Function: or a tale of two standards

Sebastian Rogers
3 min readMar 17, 2022

TL;DR If you want to use the PnP JS Core library from an Azure Function you need to use TypeScript 4.5 or higher; write .mts TypeScript files and set your script file to be index.mjs.

This is a good example of why its impossible to predict how long a programming task will take.

We wanted to call the PnP JS Core Library from TypeScript Azure Function.

We have written many TypeScript Azure Functions.

We have used V2 of the PnP JS Core library many times.

However we needed V3 of the PnP JS Core library.

We created the Azure Function — set up a very simple PnP JS Core call:

Ran the function and got:

Uncaught SyntaxError: Cannot use import statement outside a module

So I flipped the “module” setting in the tsconfig.json file to “ESNext” to tell it to use ESM modules then I got:

Worker was unable to load function GetWeb: ‘ReferenceError: require is not defined in ES module scope, you can use import instead’

That was yesterday, a full day later we know how to fix it, but nowhere in the time planning for the project did we have “work out why TypeScript Azure Functions does not support ESM modules”. So we are in effect a day late.

The reason is that in the JavaScript / Node world there are two competing standards for modules:

The reasons are historical but the key things is that ‘ESM’ has won and its becoming the standard, many projects have moved to using it, including PnP JS Core, TypeScript provided experimental support for it in version 4.5 and Node have implemented full support for it.

TypeScript Azure Functions use Node but when created via the func or VS Code default method use TypeScript 3.3 and assume that all modules are CommonJS. This is very reasonable as the TypeScript support is experimental. So out of the box you can only use CommonJS modules.

However if you want to use PnP JS Core you now have an issue as they have dropped support for CommonJS.

So you’ll need to modify your configuration, a fully worked example is available here, which is a GitHub template so you can use it to start your own projects: Simple-Innovation/simple-azure-function-pnp-template (github.com)

In essence though you need to:

  • Upgrade TypeScript to version 4.5 or higher.
  • In tsconfig.json set “module”: “ESNext”
  • In each Function rename index.ts to index.mts
  • In each function.json change the “scriptFile to reference “index.mjs” rather than “index.js”
  • Write all TypeScript files as .mts rather than .ts files
  • Reference all .mts files in import statements explicitly as .mjs files

See the README.md file for more details.

TL;CR If you want to use the PnP JS Core library from an Azure Function you need to use TypeScript 4.5 or higher; write .mts TypeScript files and set your script file to be index.mjs.

--

--

Sebastian Rogers

Technical Director for Simple Innovations Ltd. First paid for code in 1980, but still has all his own hair.