diff --git a/.changeset/smart-clouds-applaud.md b/.changeset/smart-clouds-applaud.md new file mode 100644 index 000000000..0fffa2103 --- /dev/null +++ b/.changeset/smart-clouds-applaud.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Add helpful error message when the MDX integration is missing. diff --git a/packages/astro/src/core/errors/dev/vite.ts b/packages/astro/src/core/errors/dev/vite.ts index ffe3979c3..9dad775bf 100644 --- a/packages/astro/src/core/errors/dev/vite.ts +++ b/packages/astro/src/core/errors/dev/vite.ts @@ -1,18 +1,29 @@ +import type { SSRLoadedRenderer } from './../../../@types/astro.js'; import * as fs from 'fs'; import { getHighlighter } from 'shiki'; import { fileURLToPath } from 'url'; import type { ErrorPayload } from 'vite'; import type { ModuleLoader } from '../../module-loader/index.js'; import { AstroErrorData } from '../errors-data.js'; -import type { ErrorWithMetadata } from '../errors.js'; +import { AstroError, ErrorWithMetadata } from '../errors.js'; import { createSafeError } from '../utils.js'; import { renderErrorMarkdown } from './utils.js'; -export function enhanceViteSSRError(error: unknown, filePath?: URL, loader?: ModuleLoader): Error { +export function enhanceViteSSRError({ + error, + filePath, + loader, + renderers, +}: { + error: unknown; + filePath?: URL; + loader?: ModuleLoader; + renderers?: SSRLoadedRenderer[]; +}): Error { // NOTE: We don't know where the error that's coming here comes from, so we need to be defensive regarding what we do // to it to make sure we keep as much information as possible. It's very possible that we receive an error that does not // follow any kind of standard formats (ex: a number, a string etc) - const safeError = createSafeError(error) as ErrorWithMetadata; + let safeError = createSafeError(error) as ErrorWithMetadata; // Vite will give you better stacktraces, using sourcemaps. if (loader) { @@ -48,6 +59,23 @@ export function enhanceViteSSRError(error: unknown, filePath?: URL, loader?: Mod } } + const fileId = safeError.id ?? safeError.loc?.file; + + // Vite throws a syntax error trying to parse MDX without a plugin. + // Suggest installing the MDX integration if none is found. + if ( + !renderers?.find((r) => r.name === '@astrojs/mdx') && + safeError.message.match(/Syntax error/) && + fileId?.match(/\.mdx$/) + ) { + safeError = new AstroError({ + ...AstroErrorData.MdxIntegrationMissingError, + message: AstroErrorData.MdxIntegrationMissingError.message(fileId), + location: safeError.loc, + stack: safeError.stack, + }) as ErrorWithMetadata; + } + // Since Astro.glob is a wrapper around Vite's import.meta.glob, errors don't show accurate information, let's fix that if (/Invalid glob/.test(safeError.message)) { const globPattern = safeError.message.match(/glob: "(.+)" \(/)?.[1]; diff --git a/packages/astro/src/core/errors/errors-data.ts b/packages/astro/src/core/errors/errors-data.ts index 669c5054f..333134c2d 100644 --- a/packages/astro/src/core/errors/errors-data.ts +++ b/packages/astro/src/core/errors/errors-data.ts @@ -534,6 +534,23 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati 'A remark or rehype plugin attempted to inject invalid frontmatter. Ensure "astro.frontmatter" is set to a valid JSON object that is not `null` or `undefined`.', hint: 'See the frontmatter injection docs https://docs.astro.build/en/guides/markdown-content/#modifying-frontmatter-programmatically for more information.', }, + /** + * @docs + * @see + * - [MDX installation and usage](https://docs.astro.build/en/guides/integrations-guide/mdx/) + * @description + * Unable to find the official `@astrojs/mdx` integration. This error is raised when using MDX files without an MDX integration installed. + */ + MdxIntegrationMissingError: { + title: 'MDX integration missing.', + code: 6004, + message: (id: string) => { + return `Unable to render ${JSON.stringify( + id + )}. Ensure that the \`@astrojs/mdx\` integration is installed.`; + }, + hint: 'See the MDX integration docs for installation and usage instructions: https://docs.astro.build/en/guides/integrations-guide/mdx/', + }, // Config Errors - 7xxx UnknownConfigError: { title: 'Unknown configuration error.', diff --git a/packages/astro/src/core/render/dev/index.ts b/packages/astro/src/core/render/dev/index.ts index 16fb13fd3..7b5df9482 100644 --- a/packages/astro/src/core/render/dev/index.ts +++ b/packages/astro/src/core/render/dev/index.ts @@ -59,13 +59,13 @@ export async function preload({ // Load the module from the Vite SSR Runtime. const mod = (await env.loader.import(fileURLToPath(filePath))) as ComponentInstance; return [renderers, mod]; - } catch (err) { + } catch (error) { // If the error came from Markdown or CSS, we already handled it and there's no need to enhance it - if (MarkdownError.is(err) || CSSError.is(err) || AggregateError.is(err)) { - throw err; + if (MarkdownError.is(error) || CSSError.is(error) || AggregateError.is(error)) { + throw error; } - throw enhanceViteSSRError(err as Error, filePath, env.loader); + throw enhanceViteSSRError({ error, filePath, loader: env.loader, renderers }); } }