Mẫu Trình Chiếu Web Hiện Đại với Next.js: Hướng Dẫn Kỹ Thuật và Thực Chiến Dự Án

1. Tổng quan dự án: Mẫu trình chiếu web hiện đại cho việc chia sẻ kỹ thuật

Nếu bạn thường xuyên cần thực hiện các bài chia sẻ kỹ thuật trong đội nhóm, phát biểu tại cộng đồng công nghệ, hoặc quay các video hướng dẫn, bạn chắc chắn đã từng trải qua sự "đau khổ" khi chuẩn bị slide. Các công cụ trình chiếu truyền thống (như PowerPoint, Keynote) thường trở nên cồng kềnh và kém hiệu quả khi tạo các bài demo code hay sơ đồ kiến trúc. Các vấn đề như định dạng sai lệch, highlight code không đẹp mắt, khó khăn trong việc triển khai chia sẻ... đã làm giảm giá trị của nội dung kỹ thuật.

Gần đây, tôi đã phát hiện một dự án mã nguồn mở có tên tech-presentation-template trên GitHub, dự án này đã giải quyết hoàn hảo các vấn đề trên. Về cơ bản, đây là một ứng dụng trình chiếu web hiện đại được xây dựng bằng Next.js 14 (App Router), Tailwind CSSFramer Motion. Triết lý thiết kế cốt lõi của nó là "tách biệt nội dung và kiểu dáng" - tất cả nội dung slide của bạn được định nghĩa trong một file TypeScript, với cập nhật thời gian thực và cuối cùng có thể triển khai như một trang web thông thường để chia sẻ với bất kỳ ai.

Mẫu này ban đầu được xây dựng cho chủ đề "Triển khai code chất lượng thấp do AI tạo (AI Slop) lên môi trường production", nhưng kiến trúc tổng quát của nó hoàn toàn phù hợp cho bất kỳ chủ đề kỹ thuật nào. Nó tích hợp sẵn nhiều loại slide được tối ưu hóa cho kịch bản nhà phát triển, như toàn màn hình code, sơ đồ kiến trúc, khối trích dẫn, và hỗ trợ Markdown và highlight cú pháp gốc, giúp việc trình bày nội dung kỹ thuật trở nên tinh tế và hiệu quả hơn.

Trong bài viết này, tôi sẽ hướng dẫn bạn từ đầu, phân tích sâu dự án này. Tôi sẽ giải thích chi tiết cách thiết lập môi trường, tùy chỉnh nội dung, hiểu kiến trúc cốt lõi, và chia sẻ các kinh nghiệm thực chiến cũng như hướng dẫn tránh lỗi tôi đã tích lũy. Dù bạn muốn nhanh chóng tạo một bài chia sẻ hay muốn học một cấu trúc dự án Next.js full-stack xuất sắc, bài viết này sẽ mang lại sự trợ giúp trực tiếp.

2. Kiến trúc dự án và tư duy thiết kế cốt lõi

Trước khi bắt đầu viết code, việc hiểu tư duy thiết kế của một dự án là cực kỳ quan trọng. Điều này giúp chúng ta đưa ra quyết định hợp lý hơn khi tùy chỉnh, thay vì sao chép mù quáng. Sự thành công của tech-presentation-template phần lớn bắt nguồn từ kiến trúc thiết kế rõ ràng và tập trung.

2.1 Tại sao chọn Next.js + Tailwind CSS + Framer Motion?

Đây là một tổ hợp công nghệ phát triển web hiện đại kinh điển và hiệu quả, mỗi lựa chọn đều có mục đích rõ ràng.

  1. Next.js 14 (App Router): Đây là nền tảng của dự án. App Router cung cấp định tuyến dựa trên hệ thống tệp, điều này làm cho việc triển khai các tuyến đường slide động như /slides/1, /slides/2 trở nên cực kỳ đơn giản. Khả năng thành phần phía máy chủ (RSC) và khả năng render luồng, mặc dù không được sử dụng sâu trong mẫu này, nhưng đã để lại không gian cho việc mở rộng trong tương lai (như tạo ghi chú trình bày phía máy chủ). Điều quan trọng hơn, đầu ra build của Next.js là một trang web tĩnh (thông qua pnpm build), có thể dễ dàng triển khai đến Vercel, Netlify hoặc bất kỳ nền tảng lưu trữ tĩnh nào, liên kết chia sẻ chính là kết quả cuối cùng, không cần khán giả cài đặt bất kỳ phần mềm nào.
  2. Tailwind CSS: Chịu trách nhiệm về kiểu dáng. Đối với các dự án UI có tính tùy chỉnh cao như trình chiếu, CSS truyền thống hoặc CSS-in-JS có thể khá phức tạp khi duy trì chủ đề toàn cầu và thiết kế đáp ứng. Triết lý lớp tiện ích (Utility-First) của Tailwind cho phép các nhà phát triển xây dựng và điều chỉnh kiểu dáng nhanh chóng trong JSX, chẳng hạn như kiểm tra kích thước font chữ, màu sắc, khoảng cách và hoạt ảnh. Các biến CSS được định nghĩa trong app/globals.css với nền tối và màu cam "Cursor editor" làm chủ đạo, có thể dễ dàng duy trì tính nhất quan về mặt hình ảnh trong toàn bộ ứng dụng thông qua Tailwind.
  3. Framer Motion: Chịu trách nhiệm về hoạt ảnh. Các chuyển động mượt mà là yếu tố then chốt nâng cao trải nghiệm trình bày. Framer Motion là một thư viện hoạt ảnh React mạnh mẽ, được sử dụng để thực hiện các hiệu ứng như mờ dần, trượt khi chuyển slide. Trong components/SlideNav.tsxcomponents/Slide.tsx, bạn có thể thấy việc sử dụng thành phần motion.div, nó định nghĩa cách các phần tử xuất hiện, rời đi và cập nhật thông qua API khai báo, đơn giản hóa đáng kể việc triển khai hoạt ảnh phức tạp.

Kinh nghiệm thực tế: Tổ hợp công nghệ này gần như là một trong những phương pháp tốt nhất hiện tại để xây dựng các ứng dụng web hiệu suất cao, biểu cảm cao. Nếu bạn không quen thuộc với chúng, dự án này là một mẫu học xuất sắc. Tuy nhiên, nếu bạn cần hiệu suất tải lần đầu tiên tối ưu hơn, hãy xem xét sử dụng next export để xuất HTML tĩnh sau khi build (nhưng sẽ mất một số tính năng động của Next.js). Đối với các buổi chia sẻ kỹ thuật nội bộ, giải pháp hiện tại đã hoàn toàn đủ.

2.2 Luồng dữ liệu cốt lõi: Mọi thứ bắt nguồn từ slides.ts

Đây là thiết kế tinh tế nhất của dự án và cũng là nguồn gốc hiệu suất của nó. Trung tâm trạng thái của toàn bộ ứng dụng là một mảng nằm trong lib/slides.ts.

// lib/slides.ts ví dụ đơn giản
export const presentationSlides: PresentationSlide[] = [
  {
    identifier: 1,
    heading: "Chủ đề bài trình bày",
    content: `## Đây là nội dung Markdown\n- Điểm một\n- Điểm hai`,
    category: "cover",
  },
  {
    identifier: 2,
    heading: "Về tôi",
    content: "Tôi là người trình bày...",
    category: "title",
  },
  // ... thêm slide
];

Luồng làm việc của ứng dụng như sau:

  1. Định nghĩa nội dung: Bạn chỉnh sửa mảng này trong slides.ts, định nghĩa identifier, heading, content, category cho mỗi slide.
  2. Ánh định tuyến: App Router của Next.js sẽ tạo trang cho đường dẫn động app/slides/[identifier]/page.tsx. [identifier] tương ứng với ID của slide.
  3. Lấy dữ liệu: Trong page.tsx, lấy identifier slide hiện tại thông qua params.identifier, sau đó tìm dữ liệu slide tương ứng từ mảng slides.ts.
  4. Render thành phần: Truyền dữ liệu slide (bao gồm category) đến thành phần components/Slide.tsx. Thành phần Slide bên trong sẽ chọn bố cục và thành phần con khác nhau (như CodeBlock, MarkdownRenderer) để render dựa trên giá trị của category.
  5. Đồng bộ điều hướng: Thành phần components/SlideNav.tsx cũng đọc mảng slides để tạo thanh tiến trình và nút điều hướng (tiến/lùi). Nó đồng bộ với ID slide hiện tại thông qua trạng thái React hoặc tham số truy vấn URL.

Lợi ích lớn của thiết kế này:

  • Tách biệt mối quan tâm: Bạn chỉ cần quan tâm đến nội dung trong slides.ts, không cần chạm vào các thành phần UI.
  • Xem trước thời gian thực: Máy chủ phát triển của Next.js hỗ trợ tải lại nóng (HMR). Lưu slides.ts xong, slide trong trình duyệt sẽ cập nhật ngay, trải nghiệm viết code không khác gì Notion.
  • An toàn kiểu dữ liệu: Sử dụng TypeScript định nghĩa giao diện Slide, bạn có thể nhận được tự động hoàn thành và thông báo lỗi khi chỉnh sửa nội dung, tránh lỗi chính tả.
  • Dễ quản lý phiên bản: Toàn bộ nội dung bài trình bày của bạn chỉ là một file văn bản, có thể dễ dàng quản lý lịch sử sửa đổi bằng Git, hợp tác cũng rất thuận tiện.

3. Bắt đầu từ đầu: Thiết lập môi trường và khởi tạo dự án

Lý thuyết xong, chúng ta bắt đầu thực hành. Đảm bảo máy tính của bạn đã cài đặt Node.js (18.17 hoặc cao hơn)pnpm (có thể sử dụng npm hoặc yarn, nhưng dự án đề xuất pnpm).

3.1 Lấy mã nguồn dự án

Mở terminal, thực hiện lệnh sau để clone dự án và vào thư mục. Tôi đề nghị bạn clone kho lưu trữ gốc, sau đó sử dụng nó làm mẫu để chỉnh sửa.

# Clone kho lưu trữ gốc
git clone https://github.com/naufaldi/tech-presentation-template.git my-tech-presentation
cd my-tech-presentation

# Cài đặt dependencies
pnpm install

Lưu ý: pnpm install sẽ nhanh hơn npm install và tiết kiệm không gian đĩa hơn vì nó sử dụng liên kết cứng. Nếu chưa cài pnpm, hãy chạy npm install -g pnpm trước.

3.2 Khởi động máy chủ phát triển

Sau khi cài đặt xong dependencies, chạy lệnh phát triển:

pnpm dev

Terminal sẽ xuất thông tin tương tự như sau:

> next dev
▲ Next.js 14.2.5
- Local:        http://localhost:3000
- Network:      http://192.168.1.xxx:3000

Mở http://localhost:3000 trong trình duyệt, bạn sẽ được chuyển hướng đến http://localhost:3000/slides/1, tức slide đầu tiên. Bây giờ bạn nên thấy một giao diện trình chiếu với chủ đề tối hiện đại.

Thử các thao tác này:

  • Nh phím mũi tên phải (→) hoặc phím cách để chuyển đến slide tiếp theo.
  • Nh phím mũi tên trái (←) để quay lại slide trước.
  • Nh vào thanh tiến trình ở dưới màn hình để nhảy nhanh đến bất kỳ slide nào.
  • Thử chỉnh sửa bất kỳ nội dung văn bản nào trong file lib/slides.ts, lưu lại rồi quay lại trình duyệt, không cần làm mới, nội dung đã tự động cập nhật.

3.3 Phân tích cấu trúc dự án sâu

Hãy xem xét kỹ cấu trúc thư mục của dự án, điều này giúp ích cho việc tùy chỉnh và phát triển sau này.

my-tech-presentation/
├── app/                    # Thư mục cốt lõi Next.js 14 App Router
│   ├── globals.css        # Kiể dáng toàn cầu và định nghĩa biến CSS (màu chủ đạo, font chữ...)
│   ├── layout.tsx         # Bố cục gốc, định nghĩa khung HTML và thành phần điều hướng toàn cục
│   ├── page.tsx           # Trang chủ (/), chỉ làm chuyển hướng đến /slides/1
│   └── slides/            # Đường dẫn liên quan đến slide
│       └── [identifier]/  # Đường dẫn động, [identifier] là tham số
│           └── page.tsx   # Trang cốt lõi, render slide tương ứng dựa trên [identifier]
├── components/            # Thành phần React có thể tái sử dụng
│   ├── Slide.tsx          # Thành phần slide chính, render bố cục khác nhau dựa trên category
│   ├── SlideNav.tsx       # Thanh điều hướng dưới (tiến/lùi/thanh tiến trình)
│   ├── CodeBlock.tsx      # Thành phần highlight code (sử dụng `react-syntax-highlighter`)
│   └── MarkdownRenderer.tsx # Chuyển đổi chuỗi Markdown thành phần tử React
├── lib/                   # Hàm tiện ích và dữ liệu cốt lõi
│   ├── slides.ts          # **Cốt lõi**: định nghĩa tất cả nội dung slide
│   └── types.ts           # Định nghĩa kiểu TypeScript (như giao diện Slide)
├── public/                # Tài nguyên tĩnh
│   ├── logo.svg           # Logo trang web
│   ├── fonts/             # Font chữ tùy chỉnh "CursorGothic"
│   └── *.webp             # Tài nguyên ảnh dùng trong slide
├── next.config.js         # Tệp cấu hình Next.js
└── package.json           # Dependencies và script của dự án

Cấu trúc này rất rõ ràng, tuân thủ các phương pháp hay nhất của Next.js App Router. Vùng làm việc chính của bạn sẽ là lib/slides.ts (nội dung) và app/globals.css (kiểu dáng).

4. Tính năng cốt lõi thực chiến: Tùy chỉnh trình chiếu riêng của bạn

Bây giờ, chúng ta đi sâu vào tính năng cốt lõi, xem cách tận dụng các chức năng mà mẫu cung cấp để tạo ra tài liệu trình bày kỹ thuật chuyên nghiệp.

4.1 Hiểu và sử dụng chín loại slide

lib/types.ts định nghĩa SlideCategory quyết định bố cục hình ảnh của slide. Mỗi loại có kịch bản sử dụng riêng.

Loại (category) Ứng dụng tốt nhất Đặc điểm chính
**cover** Màn hình bìa bài trình bày Tiêu đề cỡ超大, tạo ấn tượng thị giác mạnh mẽ.
**title** Đầu/cuối phần, giới thiệu người trình bày Bố cục căn giữa, thường kết hợp logo và tiêu đề phụ.
**section** Trang phân chia phần Chữ lớn căn giữa, khối nền nổi bật, dùng để chuyển tiếp.
**content** Trang nội dung chính (thường dùng nhất) Văn bản căn trái, hoàn toàn hỗ trợ Markdown danh sách, tiêu đề, bảng.
**image** Hiển thị biểu đồ, ảnh chụp, sơ đồ minh họa Trộn văn bản ảnh, ảnh căn giữa hoặc cạnh, kèm giải thích.
**quote** Nhấn mạnh câu nói nổi tiếng, kết luận quan trọng Kiểu trích dẫn nổi bật, thường có dải trang trí bên cạnh.
**video** Nhúng video trình bày Nhúng iframe, hỗ trợ YouTube, Google Drive và các liên kết video khác.
**code** Hiển thị đoạn code (yêu thích của nhà phát triển) Tập trung vào khu vực code, cung cấp highlight cú pháp tốt và số dòng tùy chọn.
**diagram** Hiển thị nghệ thuật ASCII hoặc biểu đồ văn bản Font chữ đẳng cách, giữ căn chỉnh ký tự, phù hợp vẽ sơ đồ kiến trúc đơn giản.

Ví dụ thực chiến: Tạo một trang "nội dung" phức tạp

Giả sử chúng ta muốn giới thiệu React Hooks, có thể thêm một slide như thế này trong lib/slides.ts:

{
  identifier: 10, // Đảm bảo ID duy nhất và đúng thứ tự
  heading: "Phân tích các React Hooks cốt lõi",
  category: "content",
  content: `## Bốn Hooks thường dùng nhất

### 1. useState - Quản lý trạng thái
Cho phép component hàm có trạng thái nội bộ.
\`\`\`javascript
const [counter, setCounter] = useState(0);
\`\`\`

### 2. useEffect - Xử lý tác phụ
Thay thế hàm vòng đời, xử lý lấy dữ liệu, đăng ký...
\`\`\`javascript
useEffect(() => {
  document.title = \`Bạn đã nhấn \${counter} lần\`;
}, [counter]); // Mảng phụ thuộc
\`\`\`

### 3. useContext - Truyền giá trị chéo component
Tránh việc truyền props qua nhiều tầng.
\`\`\`javascript
const theme = useContext(ThemeContext);
\`\`\`

### 4. useRef - Tham chiếu DOM hoặc giá trị bền vững
Thuộc tính .current giữ nguyên trong vòng đời component.
\`\`\`javascript
const inputRef = useRef(null);
// <input ref={inputRef} />
\`\`\`
`,
  notes: "Khi trình bày: Nhấn mạnh mảng phụ thuộc và hàm dọn dẹp của useEffect.", // Ghi chú người trình bày
}

Slide này tận dụng tối đa sự hỗ trợ Markdown của loại content, kết hợp các yếu tố như tiêu đề cấp 2, tiêu đề cấp 3, khối code, mật độ thông tin cao và cấu trúc rõ ràng.

4.2 Kỹ thuật nâng cao Markdown và nhúng đa phương tiện

Trường content hỗ trợ hoàn chỉnh Markdown theo phong cách GitHub (GFM), mang lại cho chúng tôi tự do sáng tạo lớn.

  1. Bảng: Rất phù hợp để so sánh ưu nhược điểm của các giải pháp kỹ thuật khác nhau.
| Tính năng | Next.js (App Router) | Create React App |
| :--- | :--- | :--- |
| Định tuyến | Dựa trên hệ thống tệp, ưu tiên máy chủ | Định tuyến máy khách (React Router) |
| Lấy dữ liệu | Thành phần máy chủ, Server Actions | Fetch máy khách (useEffect) |
| Tối ưu hiệu suất | Tự động chia mã, render luồng | Cần cấu hình thủ công |
| Đường cong học | Dốc, nhiều khái niệm | Tương đối dễ |

  1. Ảnh và video:
  • Ảnh: Đặt file ảnh (như architecture.png) vào thư mục public/, sau đó sử dụng cú pháp Markdown để tham chiếu. ![Sơ đồ kiến trúc](/architecture.png). Nên định dạng .webp để có tỷ lệ nén tốt hơn.
  • Video: Sử dụng category: "video" và cung cấp thuộc tính video trong đối tượng slide. Đối với liên kết chia sẻ Google Drive, cần chuyển sang chế độ xem trước (/preview). Đối với YouTube, có thể sử dụng liên kết nhúng (https://www.youtube.com/embed/VIDEO_ID).
  1. Ghi chú người trình bày: Đây là một tính năng ẩn rất hữu ích. Thêm một trường notes tùy chọn trong mỗi đối tượng slide. Những nội dung này không hiển thị trên slide mà khán giả thấy, nhưng bạn có thể in ra hoặc đặt trên màn hình khác làm dàn ý trình bày.
{
  identifier: 5,
  heading: "Chiến lược tối ưu hiệu suất",
  category: "content",
  content: `## Chiến lược cốt lõi: Giảm render không cần thiết...`,
  notes: `[Bổ sung giải thích] Có thể đưa ra một case study thực tế: Trang danh sách sản phẩm của chúng tôi do Context không phù hợp dẫn đến render toàn bộ, sau khi dùng Memo hiệu suất tăng 50%. Chuẩn bị mở Chrome DevTools để demo.`,
}

4.3 Tùy chỉnh chủ đề và kiểu dáng sâu

Nếu bạn không hài lòng với kiểu chủ đề "Cursor" mặc định, có thể dễ dàng tùy chỉnh thương hiệu.

  1. Thay đổi màu chủ đạo: Tất cả màu sắc được định nghĩa trong biến :root của tệp app/globals.css.
:root {
  --background: #0f172a;     /* Thay thành nền xanh đậm */
  --foreground: #f8fafc;     /* Thay thành chữ xám nhạt */
  --accent-primary: #3b82f6; /* Thay thành màu xanh làm màu chính */
  --accent-secondary: #10b981; /* Thay thành màu xanh lá làm màu phụ */
}

Sau khi thay đổi, màu chủ đạo, nút, viền highlight của toàn bộ trang web sẽ thay đổi theo. 2. Thay đổi font chữ: Dự án mặc định sử dụng font CursorGothic. Nếu muốn sử dụng font hệ thống hoặc Google Fonts, cần hai bước:

  • Bước A: Trong app/globals.css, bình luận hoặc sửa phần @font-face để giới thiệu font mới.
/* Ví dụ, sử dụng stack font hệ thống */
:root {
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
}
  • Bước B: Cập nhật cấu hình font của Tailwind trong tailwind.config.js (nếu dự án có tệp này). Mẫu này không cấu hình rõ ràng vì font được áp dụng trực tiếp trong CSS.
  1. Tùy chỉnh bố cục: Nếu bạn muốn tạo một loại slide mới (ví dụ, bố cục hai cột so sánh), bạn cần:
  • Thêm loại mới vào kiểu hợp SlideCategory trong lib/types.ts, như 'two-column'.
  • Thêm cấu trúc JSX tương ứng cho loại category mới trong components/Slide.tsx.
  • Viết kiểu dáng cho bố cục mới này trong app/globals.css.

Hướng dẫn tránh lỗi của tôi: Khi chỉnh sửa kiểu dáng, ưu tiên sử dụng hoặc mở rộng tên lớp Tailwind, thay vì viết CSS tùy chỉnh nhiều. Ví dụ, muốn in đậm một tiêu đề nào đó, hãy dùng **tiêu đề** trong Markdown hoặc thêm thẻ HTML <strong>, để plugin Tailwind xử lý. Điều này giúp duy trì tính nhất quán kiểu dáng tốt hơn.

5. Xây dựng, triển khai và kỹ thuật trình bày thực chiến

Sau khi tạo xong nội dung, bước tiếp theo là chia sẻ nó.

5.1 Xây dựng phiên bản sản xuất

Trước khi triển khai, hãy build và kiểm tra phiên bản sản xuất tại địa phương để đảm bảo mọi thứ hoạt động bình thường.

# Build file tĩnh (trong thư mục .next/)
pnpm build

# Khởi động máy chủ chế độ sản xuất để xem trước
pnpm start

Truy cập http://localhost:3000, kiểm tra tất cả slide, ảnh, điều hướng có hoạt động bình thường không. Chế độ sản xuất đã tắt tải nóng và công cụ phát triển, gần với môi trường trực tuyến hơn.

5.2 Triển khai lên Vercel (đề xuất)

Đây là cách triển khai thuận tiện nhất vì dự án được xây dựng bằng Next.js.

  1. Đẩy mã nguồn của bạn lên kho GitHub, GitLab hoặc Bitbucket.
  2. Đăng nhập Vercel.
  3. Nhấp "New Project", nhập kho của bạn.
  4. Vercel sẽ tự động phát hiện đây là dự án Next.js, cấu hình gần như không cần chỉnh sửa.
  5. Nhấp "Deploy". Vài chục giây sau, bạn sẽ nhận được liên kết vĩnh viễn như https://my-tech-presentation.vercel.app.

Bạn có thể chia sẻ trực tiếp liên kết này với khán giả. Họ có thể xem slide trình chiếu của bạn trên trình duyệt bất kỳ thiết bị nào, trải nghiệm giống với môi trường phát triển tại địa phương.

5.3 Kỹ thuật thao tác và phương án dự phòng khi trình bày

  • Chế độ xem người trình bày: Mẫu gốc không có chế độ xem người trình bày (hiện đồng thời slide hiện tại, slide tiếp theo và ghi chú). Một giải pháp thực tế là:
  1. Mở liên kết trình bày của bạn trong trình duyệt (ví dụ your-deck.vercel.app).
  2. Nhấn F12 mở công cụ phát triển.
  3. Nhấp vào biểu tượng cài đặt ở góc trên bên phải, tìm "Dock side" và chọn "Right" hoặc "Left", di chuyển bảng công cụ phát triển sang một bên.
  4. Thêm ?notes=true vào URL slide trong thanh địa chỉ (điều này cần bạn chỉnh sửa đơn giản Slide component để hiển thị nội dung notes dựa trên tham số truy vấn). Như vậy, màn hình chính là toàn màn hình slide, thanh bên là ghi chú của bạn.
  • Điều khiển bằng bàn phím: Thành thạo sử dụng (slide tiếp), (slide trước), Home (đầu tiên), End (cuối) để điều hướng, mượt mà và chuyên nghiệp hơn dùng chuột.
  • Dự phòng ngoại tuyến: Đối với các bài trình bày quan trọng, luôn cần phương án B. Có thể sao chép toàn bộ thư mục .nextpublic sau khi build bằng pnpm build vào USB. Hoặc sử dụng tính năng "In" của trình duyệt, chọn "Lưu dưới dạng PDF" để tạo tài liệu định dạng đẹp.

6. Xử lý vấn đề thường gặp và tối ưu hóa nâng cao

Trong quá trình sử dụng, bạn có thể gặp một số vấn đề. Tôi tổng hợp một số trường hợp phổ biến và giải pháp ở đây.

6.1 Vấn đề nội dung và hiển thị

Hiện tượng Nguyên nhân có thể Giải pháp
Sửa slides.ts nhưng trang không thay đổi 1. Máy chủ phát triển không chạy hoặc bị treo. 2. Bộ đệm trình duyệt. 1. Kiểm tra terminal, đảm bảo pnpm dev đang chạy và không có lỗi. 2. Thử làm mới cứng trình duyệt (Ctrl/Cmd + Shift + R).
Ảnh không tải được 1. Đường dẫn ảnh sai. 2. Ảnh không được đặt vào thư mục public. 1. Đảm bảo đường dẫn trong Markdown bắt đầu bằng /, như /my-image.webp. 2. Sao chép file ảnh vào thư mục public/.
Khối code không có highlight cú pháp 1. Gói react-syntax-highlighter có thể chưa được cài đặt hoặc nhập đúng. 1. Chạy pnpm install react-syntax-highlighter @types/react-syntax-highlighter đảm bảo dependencies đầy đủ. 2. Kiểm tra components/CodeBlock.tsx có tồn tại và nhập đúng không.
Video không phát được 1. Liên kết video không phải là định dạng nhúng. 2. Trang web bị nhà cung cấp video (như Google Drive) chặn. 1. Đối với Google Drive, đảm bảo liên kết kết thúc bằng /preview. 2. Cân nhắc tải video lên nền tảng chuyên dụng (như YouTube/Vimeo) và sử dụng mã nhúng.
Hiển thị sai trên thiết bị di động 1. Một số bố cục hoặc kích thước font không được tối ưu hóa cho đáp ứng. 1. Kiểm tra CSS, đảm bảo sử dụng lớp đáp ứng của Tailwind (như text-lg md:text-xl). 2. Thêm @media query cho bố cục phức tạp trong thành phần Slide.

6.2 Tối ưu hóa hiệu suất và mở rộng

  • Tối ưu ảnh: Đây là yếu tố ảnh hưởng nhiều nhất đến tốc độ tải. Đảm bảo:
  • Sử dụng định dạng hiện đại như WebP hoặc AVIF.
  • Sử dụng công cụ xử lý ảnh (như Squoosh, ImageOptim) hoặc thành phần next/image của Next.js (cần chỉnh sửa dự án) để nén.
  • Thêm thuộc tính widthheight rõ ràng cho thẻ img, tránh lệch bố cục.
  • Tối ưu font chữ: File font CursorGothic mặc định khá lớn. Nếu không yêu cầu cao về thương hiệu, có thể loại bỏ font tùy chỉnh, sử dụng stack font hệ thống font-family: system-ui, -apple-system, sans-serif;, sẽ tăng đáng kể tốc độ tải lần đầu.
  • Phân tích kích thước gói: Chạy pnpm build, Next.js sẽ xuất kích thước của các module. Nếu phát hiện một số dependencies (như Framer Motion) quá lớn, có thể cân nhắc:
  • Nhập theo nhu cầu: import { motion } from 'framer-motion' thay vì import toàn bộ thư viện.
  • Đánh giá xem có thực sự cần hoạt ảnh phức tạp không, có thể thay bằng CSS Transition.
  • Thêm tính năng tương tác: Nếu muốn nhúng trình soạn thảo code có thể chạy (như CodeSandbox nhúng) hoặc biểu đồ tương tác (như render flowchart bằng Mermaid.js) trong slide, cần:
  1. Nhập thành phần của thư viện bên thứ ba cho loại slide tương ứng.
  2. Lưu ý các thư viện này có thể tăng kích thước gói JavaScript phía máy khách.
  3. Cân nhắc sử dụng next/dynamic để nhập động, tách khỏi gói chính, tải theo nhu cầu.

6.3 Hướng phát triển dự án

Mẫu này là một điểm xuất sắc, bạn có thể xây dựng công cụ mạnh mẽ hơn dựa trên nó:

  1. Chuyển đổi chủ đề/bài trình bày: Chỉnh sửa lib/slides.ts để nó có thể xuất nhiều mảng bài trình bày. Ở cấp độ định tuyến (như /talk/ai-slop/talk/react-2024), tải tập dữ liệu slide khác nhau dựa trên tham số.
  2. Xuất ra PDF/PPT: Đây là yêu cầu phổ biến. Mặc dù không thể sao chép hoàn toàn hoạt ảnh web, nhưng có thể:
  • Sử dụng thư trình duyệt không đầu (như Puppeteer) viết script, tự động truy cập từng slide và chụp màn hình, sau đó hợp thành PDF.
  • Hoặc, sử dụng tính năng "In" của trình duyệt, chọn "Lưu dưới dạng PDF", và điều chỉnh kiểu in kỹ (thêm quy tắc @media print trong CSS).
  1. Hệ thống quản trị: Nếu muốn người không phải nhà phát triển cũng có thể chỉnh sửa slide, có thể xây dựng giao diện CRUD đơn giản, lưu dữ liệu slide trong cơ sở dữ liệu (như Supabase) hoặc file, và đọc động thông qua API.

Sau các bước trên, bạn không chỉ có thể sử dụng thành thạo mẫu trình chiếu này để tạo bài trình bày kỹ thuật chất lượng cao, mà còn hiểu sâu thiết kế cốt lõi của nó, thậm chí tùy chỉnh và mở rộng theo nhu cầu. Nó không chỉ là một công cụ, mà còn là một dự án xuất sắc thể hiện các phương pháp hay nhất trong phát triển web hiện đại. Lần tới khi cần trình bày kỹ thuật, hãy thử nó, tôi tin bạn sẽ yêu thích sự hiệu quả và tinh tế khi "viết" slide bằng code.

Thẻ: Next.js Tailwind CSS Framer Motion typescript Trình chiếu web

Đăng vào ngày 31 tháng 5 lúc 18:51