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”Lỗi xảy ra
Section titled “Lỗi xảy ra”[@mdx-js/rollup] Could not parse import/exports with acornIdentifier 'defineConfig' has already been declaredfile: /opt/buildhome/repo/src/content/docs/markdown/components-terminal-code.mdx:232:10Nguyên nhân
Section titled “Nguyên nhân”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ậtimport { defineConfig } from 'astro/config';import mdx from '@astrojs/mdx';// => LỖI: defineConfig đã được khai báo 2 lần!Các files bị ảnh hưởng
Section titled “Các files bị ảnh hưởng”| File | Số 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 khắc phục
Section titled “Cách khắc phục”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 -->```javascriptexport default defineConfig({...});```markdown<!-- Thay vì -->:::terminal{title="Deploy"}$ npm run build:::
<!-- Dùng -->```bashnpm 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:
---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:
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ách 3: Dùng remark plugin có sẵn
Section titled “Cách 3: Dùng remark plugin có sẵn”Có các remark/rehype plugins hỗ trợ:
remark-directive- Hỗ trợ custom directivesrehype-pretty-code- Syntax highlighting đẹp
Bài học rút ra
Section titled “Bài học rút ra”- Luôn test build trước khi deploy - Chạy
npm run buildlocal trước - 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
- Kiểm tra Astro config - Xem có các plugins cần thiết không
- Custom components ≠ Markdown extensions - Cần cài đặt riêng, không tự động hoạt động
Kiểm tra lỗi
Section titled “Kiểm tra lỗi”Chạy build để phát hiện lỗi:
npm run buildNếu thành công sẽ hiện:
✓ Completed in Xms✓ Generated X pagesNếu lỗi sẽ hiện chi tiết vị trí file và dòng bị lỗi.