Skip to content

Lỗi MDX Custom Components - Nguyên nhân và cách khắc phục

Lỗi MDX Custom Components - Phân tích chi tiết

Section titled “Lỗi MDX Custom Components - Phân tích chi tiết”
[@mdx-js/rollup] Could not parse import/exports with acorn
Identifier 'defineConfig' has already been declared
file: /opt/buildhome/repo/src/content/docs/markdown/components-terminal-code.mdx:232:10

1. Custom Components không được định nghĩa

Section titled “1. Custom Components không được định nghĩa”

Trong project có sử dụng các custom MDX components như:

:::code{language="javascript" filename="astro.config.mjs"}
import { defineConfig } from 'astro/config';
export default defineConfig({...});
:::
:::terminal{title="Deploy"}
$ npm run build
:::
:::alert{type="success"}
Thành công!
:::

Vấn đề: Các components này (:::code, :::terminal, :::alert, v.v.) không được định nghĩa trong:

  • astro.config.mjs
  • Không có file component riêng
  • Không có custom remark/rehype plugin

2. Tại sao lỗi “defineConfig has already been declared”?

Section titled “2. Tại sao lỗi “defineConfig has already been declared”?”

Khi MDX parser gặp custom component syntax mà không được handle, nó cố parse nội dung bên trong như JavaScript thực sự.

Ví dụ:

// Cái này MDX hiểu như import thật
import { defineConfig } from 'astro/config';
import mdx from '@astrojs/mdx';
// => LỖI: defineConfig đã được khai báo 2 lần!
FileSố lượng custom components
components-terminal-code.mdx~15
components-alert-boxes.mdx~20
components-lists-tables.mdx~25
components-navigation-structure.mdx~70

Tổng cộng: ~131 custom components không hoạt động

Cách 1: Thay bằng Markdown chuẩn (Khuyên dùng)

Section titled “Cách 1: Thay bằng Markdown chuẩn (Khuyên dùng)”
<!-- Thay vì -->
:::code{language="javascript"}
export default defineConfig({...});
:::
<!-- Dùng -->
```javascript
export default defineConfig({...});
```markdown
<!-- Thay vì -->
:::terminal{title="Deploy"}
$ npm run build
:::
<!-- Dùng -->
```bash
npm run build
```markdown
<!-- Thay vì -->
:::alert{type="success"}
Thành công!
:::
<!-- Dùng -->
> ✅ Thành công!

Cách 2: Tạo custom components (Nâng cao)

Section titled “Cách 2: Tạo custom components (Nâng cao)”

Tạo các Svelte components:

src/components/mdx/Code.astro
---
const { language, filename } = Astro.props;
---
<pre class="code-block" data-language={language}>
<code>{filename && <span class="filename">{filename}</span>}</code>
<slot />
</pre>

Đăng ký trong Astro config:

astro.config.mjs
import starlight from '@astrojs/starlight';
export default defineConfig({
integrations: [
starlight({
components: {
// Đăng ký custom components
'code': './src/components/mdx/Code.astro',
'terminal': './src/components/mdx/Terminal.astro',
}
})
]
});

Có các remark/rehype plugins hỗ trợ:

  • remark-directive - Hỗ trợ custom directives
  • rehype-pretty-code - Syntax highlighting đẹp
  1. Luôn test build trước khi deploy - Chạy npm run build local trước
  2. Không dùng custom components nếu không định nghĩa - Hoặc là phải tạo components, hoặc dùng markdown chuẩn
  3. Kiểm tra Astro config - Xem có các plugins cần thiết không
  4. Custom components ≠ Markdown extensions - Cần cài đặt riêng, không tự động hoạt động

Chạy build để phát hiện lỗi:

Terminal window
npm run build

Nếu thành công sẽ hiện:

✓ Completed in Xms
✓ Generated X pages

Nếu lỗi sẽ hiện chi tiết vị trí file và dòng bị lỗi.