withastro / astro

The web framework for content-driven websites. ⭐️ Star to support our work!
https://astro.build
Other
46.44k stars 2.46k forks source link

`__dirname is not defined in ES module scope` because of mdx integration #11463

Closed openscript closed 3 months ago

openscript commented 3 months ago

Astro Info

Astro                    v4.11.5
Node                     v22.4.0
System                   Linux (x64)
Package Manager          pnpm
Output                   static
Adapter                  none
Integrations             @astrojs/mdx

If this issue only occurs in one browser, which browser is a problem?

Describe the Bug

When I run astro build the following error is thrown:

12:53:40 [vite] ✓ built in 16ms

 generating static routes 
__dirname is not defined in ES module scope
  Stack trace:
    at file:///workspaces/astro-theme-international/dist/chunks/DefaultLayout_DkOkmtnl.mjs:65111:25
    at async onImport.tracePromise.__proto__ (node:internal/modules/esm/loader:485:26)
    at async generatePages (file:///workspaces/astro-theme-international/node_modules/.pnpm/astro@4.11.5_typescript@5.5.3/node_modules/astro/dist/core/build/generate.js:119:7)
    at async AstroBuilder.build (file:///workspaces/astro-theme-international/node_modules/.pnpm/astro@4.11.5_typescript@5.5.3/node_modules/astro/dist/core/build/index.js:133:5)
    at async build (file:///workspaces/astro-theme-international/node_modules/.pnpm/astro@4.11.5_typescript@5.5.3/node_modules/astro/dist/core/build/index.js:45:3)
 ELIFECYCLE  Command failed with exit code 1.

This only happens after I added the mdx integration. If I remove the integration from astro.config.ts the error disappears. Running astro dev always works.

What's the expected result?

The build should be successful.

Link to Minimal Reproducible Example

https://github.com/openscript/astro-theme-international/tree/repro/mdx-integration-dirname

Participation

openscript commented 3 months ago

I've enabled sourcemaps in my astro.config.ts:

import { defineConfig } from 'astro/config';
import mdx from "@astrojs/mdx";

// https://astro.build/config
export default defineConfig({
  vite: {
    build: {
      sourcemap: true
    }
  },
  prefetch: true,
  i18n: {
    defaultLocale: "en",
    locales: ["de", "en"]
  },
  integrations: [mdx()]
});

Now the error looks like this:


 generating static routes 
__dirname is not defined in ES module scope
  Stack trace:
    at <anonymous> (/workspaces/astro-theme-international/node_modules/.pnpm/rollup@4.18.1/node_modules/rollup/dist/native.js:69:23)
    at async onImport.tracePromise.__proto__ (node:internal/modules/esm/loader:485:26)
    at async generatePages (file:///workspaces/astro-theme-international/node_modules/.pnpm/astro@4.11.5_typescript@5.5.3/node_modules/astro/dist/core/build/generate.js:119:7)
    at async AstroBuilder.build (file:///workspaces/astro-theme-international/node_modules/.pnpm/astro@4.11.5_typescript@5.5.3/node_modules/astro/dist/core/build/index.js:133:5)
    at async build (file:///workspaces/astro-theme-international/node_modules/.pnpm/astro@4.11.5_typescript@5.5.3/node_modules/astro/dist/core/build/index.js:45:3)
 ELIFECYCLE  Command failed with exit code 1.
 ```
Fryuni commented 3 months ago

For future debugging reference, since sourcemap information is lost for module loading errors, this is one way to debug where the offending reference is being imported from:

function testDirname(): Plugin {
  const broken: string[] = [];

  return {
    name: 'test-dirname',
    config(config) {
      config.define ??= {};
      // Make the build not break
      config.define['__dirname'] = 'BROKEN_REFERENCE_FIND_ME';
    },
    transform(code, id) {
      if (!code.includes('BROKEN_REFERENCE_FIND_ME') && !code.includes('__dirname')) return;

      console.log('Found broken reference:', id);
      broken.push(id);
    },
    generateBundle() {
      for (const id of broken) {
        console.log('Broken reference on module:', id);
        let importer: string | undefined = id;
        while (true) {
          const moduleInfo = this.getModuleInfo(importer);
          if (!moduleInfo) {
            console.log('   Module has no info!');
            break;
          }
          importer = moduleInfo.importers?.[0];
          if (!importer) {
            break;
          }
          console.log('  Imported by:', importer);
        }
      }
    }
  }
}

In the case of the project references in the issue it shows the following logs:

Broken reference on module: /proj/node_modules/.pnpm/source-map@0.7.4/node_modules/source-map/lib/read-wasm.js
  Imported by: /proj/node_modules/.pnpm/source-map@0.7.4/node_modules/source-map/lib/read-wasm.js?commonjs-proxy
  Imported by: /proj/node_modules/.pnpm/source-map@0.7.4/node_modules/source-map/lib/source-map-consumer.js
  Imported by: /proj/node_modules/.pnpm/source-map@0.7.4/node_modules/source-map/lib/source-map-consumer.js?commonjs-proxy
  Imported by: /proj/node_modules/.pnpm/source-map@0.7.4/node_modules/source-map/source-map.js
  Imported by: /proj/node_modules/.pnpm/@astrojs+mdx@3.1.2_astro@4.11.5_typescript@5.5.3_/node_modules/@astrojs/mdx/dist/plugins.js
  Imported by: /proj/node_modules/.pnpm/@astrojs+mdx@3.1.2_astro@4.11.5_typescript@5.5.3_/node_modules/@astrojs/mdx/dist/vite-plugin-mdx.js
  Imported by: /proj/node_modules/.pnpm/@astrojs+mdx@3.1.2_astro@4.11.5_typescript@5.5.3_/node_modules/@astrojs/mdx/dist/index.js
  Imported by: /proj/astro.config.ts
  Imported by: /proj/src/pages/[...locale]/[blog]/[...slug].astro

@astrojs/mdx is being imported at runtime due to the pages importing astro.config.ts. The integration is a build-time integration, so failing to bundle it in the runtime of an Astro project is expected to break.