Node: esm: Modify ESM Experimental Loader Hooks

Created on 12 Aug 2020  路  4Comments  路  Source: nodejs/node


This issue is regarding #34144 . The original proposal on that PR was to modify the getSource loader hook to be able to optionally return a format in its return object that overrides the format returned by getFormat.

This method was eventually discussed at a team meeting: nodejs/modules#536 and a new proposal was eventually brought up: remove the getFormat hook entirely.

I plan to explore this option and submit a PR in the coming 2 weeks.

cc: @jkrems @nodejs/modules-active-members

ES Modules discuss

Most helpful comment

cc @nodejs/modules-active-members with my special ping powers.

All 4 comments

cc @nodejs/modules-active-members with my special ping powers.

Removing agenda label. Please re-add if there is more for us to discuss in the meeting

Just thought I'd drop by to say I've run into a bit of a wall today, which I think these coming changes would have been very helpful for:

// Typescript files
const extensionsRegex = /\.ts$|\.tsx$/;

export function transformSource(source, context, defaultTransformSource) {
  const { url } = context;

  if (extensionsRegex.test(url)) {
    return {
      source: babel.transform(source, {
        rootMode: "upward",
        cwd: process.cwd(),
        filename: url,
        sourceType: "unambiguous",
        ast: false
      }).code,
      format: "commonjs"
    };
  }

  // Let Node.js handle all other sources.
  return defaultTransformSource(source, context, defaultTransformSource);
}

I actually tried returning format: "commonjs" without knowing that it doesn't actually work- just assumed it might. So it does feel like a natural API to me.

I also ran into some issues with Node not being able to recognize relative TypeScript imports without an extension, for example:

import "./ServerConfig";

I tried to intercept the imports with the resolve hook, and rewrite them. But didn't seem to get it right. Would be nice if this was made a little easier too- perhaps with a recognizedModuleExtensions: [] option or something. But that's probably not completely relevant to this issue.

I actually tried returning format: "commonjs" without knowing that it doesn't actually work- just assumed it might.

I think at the least we should issue a warning when a source is provided with format=commonjs, with or without this PR. Because of the async nature of the ESM system, we'd likely be unable to use the result in a "real" require (from CJS) and we wouldn't want to risk a race condition between require and import of the same file.

But you bring up a good general point - we should document how to write a transform that can handle both CJS and ESM.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

mikeal picture mikeal  路  197Comments

mikeal picture mikeal  路  90Comments

egoroof picture egoroof  路  90Comments

speakeasypuncture picture speakeasypuncture  路  152Comments

TazmanianDI picture TazmanianDI  路  127Comments