Skip to content

Conversation

@aloisklink
Copy link

@aloisklink aloisklink commented Feb 11, 2024

Create an ESM build of this module, so that it works with modern bundlers, such as Vite.

The node buildpackage.js script now creates a ./bin/esm folder, which contains an ESM version of this package.

I've disabled minification for this folder, since I don't think it's very useful, and it just makes the package larger.

The ESM version will work with most bundlers. However, since it's missing file-extensions (e.g. it uses export * from "./Client"; instead of export * from "./Client.js";), some stricter ESM programs will not yet work with it.

Fixes: #109
Fixes: #29

Other changes in this PR

  • bfd05f7: There was one import that still used the old import Boards = require("../Boards/Boards"); syntax, so I updated that to import * as Boards from "../Boards/Boards";.
  • f858462: I renamed src/Common/Context.d.ts to src/Common/Context.ts, since that allows us to skip the # Copy declare files to bin step, as tsc will automatically make a .d.ts file for us.
  • e87e0da: The buildpackage.js script currently uses node_modules\.bin\tsc to call TypeScript, which doesn't work on my Unix machine. Instead, I've changed it to use path.join("node_modules", ".bin", "tsc"), so that it should automatically use \ on Windows, and / on Unix.

package.json#exports

I've used https://nodejs.org/api/packages.html#conditional-exports in our package.json file to automatically map files to the ESM version when appropriate.

It's pretty verbose, for backwards compatibility to support:

  • import {getClient} from 'azure-devops-extension-api/Common';
  • import {getClient} from 'azure-devops-extension-api/Common/index';
  • import {getClient} from 'azure-devops-extension-api/Common/index.js';

A future breaking change can simplify this, if you're okay with dropping support for all of these imports.

Script I used to generate these
const fs = require("fs");

const dirs = fs.readdirSync("./bin", {
  withFileTypes: true,
});

let myExports = {
  ".": {
    "import": "./esm/index.js",
    "default": "./index.js"
  },
  "./*": {
    "import": "./esm/*/index.js",
    "default": "./*/index.js"
  },
  "./package.json": "./package.json"
};
for (const dir of dirs) {
  if (dir.isDirectory() && !["node_modules", "esm"].includes(dir.name)) {
    myExports = {
      ...myExports,
      [`./${dir.name}/*`]: {
        "import": `./esm/${dir.name}/*.js`,
        "default": `./${dir.name}/*.js`
      },
      [`./${dir.name}/*.js`]: {
        "import": `./esm/${dir.name}/*.js`,
        "default": `./${dir.name}/*.js`,
      },
    }
  }
}
console.log(JSON.stringify(myExports, undefined, 2));

Testing

I've tested the npm run build script on Linux only, I'd appreciate it if somebody would be able to test it on Windows to make sure it works there too!

I've tested the ESM output of this on Vite.

aloisklink and others added 3 commits February 10, 2024 16:42
The old syntax is designed for CommonJS only.

on-behalf-of: @Mermaid-Chart <[email protected]>
This allows us to avoid having a `cp ./src/**/*.d.ts` step, since
TypeScript will now automatically create them for us.
Use `./node_modules/.bin/tsc` on Unix OSes that use `/` instead of `\`.
This allows building the package on Linux/MacOS, as well as Windows.
The `node buildpackage.js` script now creates a `./bin/esm` folder,
which contains an ESM version of this package.

I've disabled minification for this folder, since I don't think it's
very useful, and it just makes the package larger.

We use https://nodejs.org/api/packages.html#conditional-exports
to automatically map files to the ESM version when appropriate.

The ESM version will work with most bundlers. However, since it's
missing file-extensions (e.g. it uses `export * from "./Client";`
instead of `export * from "./Client.js";`), some stricter ESM programs
will not yet work with it.

Fixes: microsoft#109
@knsv
Copy link

knsv commented Feb 12, 2024

@microsoft-github-policy-service agree [company="Mermaid Chart"]

@aloisklink
Copy link
Author

@microsoft-github-policy-service agree company="Mermaid Chart"

@matttabor
Copy link

any updates here? Still waiting for ESM support for Vite. for now referencing github:aloisklink/azure-devops-extension-api#2635bb031bb1870bf5de2c2ba31e858139543117 but I don't really want to keep doing that.

@akshaybheda
Copy link

Checking if any updates for this one.

@ps-from-md
Copy link

need this to work here too

@broten15
Copy link

I also need this to work

@Hevia
Copy link

Hevia commented Jul 18, 2025

We are blocked on internal extension work because of lack of ESM support as well

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Provide ESM modules ERROR: Failed to build TypeScript. Module type

7 participants