Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create an ESM build of this module #126

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

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"

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
2 participants