~ 4 min read

Component auto import in Astro framework

share this story on
Can Astro automatically import components in markdown files? Yes, it can! Here's how to do it thanks to Chris Swithinbank and his Astro Auto Import package.

The Astro frontend framework is such a delight to work with but I was missing a feature with regards to islands and framework components that allowed the page data, such as blog posts, to automatically import the components that are used in the markdown file. This is how I solved it.

About MDX and Astro

Astro is a frontend framework that allows you to build websites, like a personal blog, using a mix of static and dynamic content. It’s a great way to build websites that are fast, optimized for SEO due to the server-side rendering and server-generated pages support, and easy to maintain.

One of the features of Astro is that it allows you to use MDX files to create pages. MDX is a way to write JSX in markdown files. This allows you to extend the Markdown syntax and use framework components in your markdown files to create rich content. MDX is well-supported in Astro using the @astro/mdx package and the MDX syntax is built on-top of Markdown so you don’t really need to learn a new syntax and can maintain the frontmatter and markdown syntax that you are already familiar with.

Her’es an example of MDX files:

---
title: "Hello, world!"
date: "2024-06-06"
---

import SomeComponent from './SomeComponent.jsx';

# Hello, world!

<SomeComponent prop="propValue" />

This is a blog post written in MDX, <Button name="Click me" />.

The rendered page will have the SomeComponent and Button components rendered in the page content but will not show the import SomeComponent ... statement. This is because the @astro/mdx package processes the MDX file and injects the component imports into the page. Of course, don’t forget saving this file with an .mdx extension: blog-hello-world.mdx.

Auto import components in Astro

If you search “astro framework component auto import” long enough you’ll land on the community contributed Astro package called astro-auto-import by the splendid Chris Swithinbank.

In essence, the astro-auto-import package reads the component file from the path that you specify in the Astro integration configuration file and then generates the appropriate ESM module tree for it that gets injected into the markdown imports and looks something like this:

return {
        type: 'mdxjsEsm',
        value: '',
        data: {
            estree: {
                body: [],
                ...parseJs(js, { ecmaVersion: 'latest', sourceType: 'module' }),
                type: 'Program',
                sourceType: 'module',
            },
        },
    };

Benefits of using astro-auto-import:

  • You can import React, Vue, and other framework components.
  • You don’t need to explicitly and manually import the components in the markdown file.
  • You can maintain both .md and .mdx files side by side in your Astro blog.

Configure the Astro Auto Import integration by adding the following to your astro.config.mjs file:

// .. other imports
import AutoImport from 'astro-auto-import';

export default defineConfig({

    // ... other config options
    integrations: [
        // The Auto Import configuration here:
		AutoImport({
			imports: ['./src/components/widgets/BlogCallToAction.vue'],
		}),
        // Make sure that the mdx() integration is *after* the Auto Import integration
        // *AND IMPORTANT* to make sure that the mdx integration doesn't repeat any prior markdown configured
        // plugins like remarkToc or remarkReadingTime
		mdx(),
	],
	
	markdown: {
		remarkPlugins: [remarkToc, remarkReadingTime],
		extendDefaultPlugins: true,
	},
});

The following are especially important to note:

  • The imports array in the AutoImport configuration should contain the path to the components that you want to auto-import in the markdown files.
  • The mdx() integration should be placed after the AutoImport integration in the integrations array.
  • The mdx() integration should not repeat any prior markdown configured plugins like remarkToc or remarkReadingTime.

If you skip the last one and you have some markdown plugins stated in the mdx() integration, you will get an error like this:

[Vue warn]: Component <Anonymous> is missing template or render function.
[Vue warn]: Component <Anonymous> is missing template or render function.
 error   Could not render `[object Module]`. No matching import has been found for `[object Module]`.
  Hint:
    Please make sure the component is properly imported.
  Error reference:

or some other Vite error similar to the above which states that it can’t find the component that you are trying to render in the MDX file and the whole page won’t load. Astro will crash.

Once everything is installed and setup, just use the component in your MDX files without having to declare the import statement:


# Hello, world!

<SomeComponent prop="propValue" />

This is a blog post written in MDX, <Button name="Click me" />.

No more manual imports, kind of like using globals in Markdown files 😅 but hey, at least those Markdown files are portable and consistent and won’t have a weird import looking statement in the beginning of the file when you migrate or import them to a new system next time!