Skip to content

Add API for dumping or inspecting the consolidated CJS and EJS module graph #52180

Closed as not planned
@ggoodman

Description

@ggoodman

What is the problem this feature will solve?

With the #51977 having landed, we're moving to a world where the logical graph will cross freely to and from CJS and ESM. I anticipate that this will break some stuff in unpredictable and hard-to-debug ways given the long tail of wacky stuff that has made its way into NPM.

These hard-to-debug and hard-to-anticipate situations will be difficult to detect and inspect from user-land code. The module graph is private state held by the runtime and V8. Having a way to extract a read-only view of this will allow tools and users to inspect, share and fix these situations.

What is the feature you are proposing to solve the problem?

I propose an API that would allow the caller to obtain a read-only representation of the module graph across both CJS and ESM nodes.

As a straw man, let's imagine require('node:module').getModuleGraph(). It could provide data with providing the following:

  1. The fully-qualified module ID (maybe it's URL).
  2. The type of that module (ESM vs CommonJS).
  3. That module's loaded dependencies, where we see the following for each:
    • The reference type require, import_dynamic, import, .. anything else?
    • The module specifier for that dependency.
    • The fully-qualified module ID of the resolved dependency.

It might look like this:

const graph = [
  {
    id: 'file:///path/to/a.cjs',
    module_type: `CommonJS',
    dependencies: [
      {
        specifier: './b',
        reference_type: 'require',
        id: 'file:///path/to/b.cjs',
      },
    ],
  },
  {
    id: 'file:///path/to/b.cjs',
    module_type: `CommonJS',
    dependencies: [
      {
        specifier: './c',
        reference_type: 'require',
        id: 'file:///path/to/c.esm',
      },
    ],
  },
  {
    id: 'file:///path/to/c.esm',
    module_type: `ESM',
    dependencies: [
      {
        specifier: './c',
        reference_type: 'import',
        id: 'file:///path/to/d.esm',
      },
    ],
  },
  {
    id: 'file:///path/to/d.esm',
    module_type: `ESM',
    dependencies: [],
  },
];

Side-note questions:

  • Is it possible through some convoluted means for the same on-disk module to have both a CJS and ESM in-memory representation? If so, that probably changes the way modules need to be identified in the proposed schema above.

What alternatives have you considered?

N/A. This is uncharted territory! 🚀

Metadata

Metadata

Assignees

No one assigned

    Labels

    feature requestIssues that request new features to be added to Node.js.loadersIssues and PRs related to ES module loadersstale

    Type

    No type

    Projects

    Status

    Awaiting Triage

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions