pnpm + tsdown으로 React 라이브러리 만들기 ③ - Next.js demo 생성
pnpm + tsdown으로 React 라이브러리를 만드는 과정에서 Next.js demo 생성 방법에 대해 정리한 페이지입니다.
Tags
monorepo, Nextra, Next.js, pnpm, React, tsdown
Environment
pnpm v10.32.1
nextra v4.6.1
Next.js v16.1.6
react v19.2.3
tsdown v0.21.3
@tsdown/css v0.21.4
1. 개요
pnpm + tsdown으로 React 라이브러리를 만드는 방법에 대해 정리한 페이지입니다.
총 5개의 Part로 분리하여 작성하였으며, 이 페이지에서는 Next.js demo 생성 과정을 다룹니다.
- 1. 프로젝트 초기화하기
- 2. React 라이브러리 생성하기
- 3. Next.js demo 생성하기
- 4. 라이브러리 배포하기
- 5. demo 배포하기
2. Next.js demo 생성하기
2.1. demo 생성하기
먼저 apps 디렉토리를 생성합니다.
1mkdir apps
2cd apps이후 다음 명령어를 입력하여 생성한 React 라이브러리를 테스트할 demo 애플리케이션을 생성합니다.
1pnpm create next-app
이후 apps/demo 디렉토리에서 불필요한 pnpm-lock.yaml, pnpm-workspace.yaml, node_modules를 삭제합니다.
2.2. Nextra 설치하기
2.2.1. Nextra 의존성 설치하기
생성한 demo 앱에서는 라이브러리 문서를 작성할 예정이므로 정적 사이트 생성 도구인 Nextra를 설치하겠습니다.
apps/demo 디렉토리에서 다음 명령어를 입력하여 Nextra를 설치합니다.
1pnpm add nextra nextra-theme-docs2.2.2. next.config.ts 설정하기
next.config.ts 파일에서 nextra를 설정하고,
turbopack의 resolveAlias 옵션을 사용하여 mdx-components 파일을 alias로 등록합니다.
또한 output: "export" 옵션을 사용하여 정적 사이트로 빌드할 수 있도록 설정합니다.
1import type { NextConfig } from "next";
2import nextra from "nextra";
3
4const nextConfig: NextConfig = {
5 /* config options here */
6 reactCompiler: true,
7 output: "export",
8 images: {
9 unoptimized: true,
10 },
11};
12
13const withNextra = nextra({
14 // ... other Nextra config options
15});
16
17export default withNextra({
18 ...nextConfig,
19 turbopack: {
20 resolveAlias: {
21 // Path to your `mdx-components` file with extension
22 "next-mdx-import-source-file": "./src/mdx-components.tsx",
23 },
24 },
25});2.2.3. mdx-components.tsx 생성하기
apps/demo/src 디렉토리에 mdx-components.tsx를 생성합니다.
1/* mdx-components.tsx */
2
3import { useMDXComponents as getThemeComponents } from "nextra-theme-docs"; // nextra-theme-blog or your custom theme
4import { MDXComponents } from "nextra/mdx-components";
5
6// Get the default MDX components
7const themeComponents = getThemeComponents();
8
9// Merge components
10export function useMDXComponents(components: MDXComponents) {
11 return {
12 ...themeComponents,
13 ...components,
14 };
15}2.2.4. 검색 기능 추가하기
문서 내 검색 기능을 추가하기 위해 pagefind 패키지를 설치합니다.
1pnpm add -D pagefind이후 apps/demo 디렉토리 내 package.json 파일을 열고, 다음과 같은 postbuild 스크립트를 추가합니다.
Static exports:
1"scripts": {
2 "postbuild": "pagefind --site .next/server/app --output-path out/_pagefind"
3}2.2.5. 루트 layout 설정하기
먼저 apps/demo/src/app 디렉토리에 있는 page.tsx, favicon.ico 파일을 삭제합니다.
그리고 globals.css 파일을 열고 Tailwind CSS 부분만 남기고 내용을 삭제합니다.
1@import "tailwindcss";이후 apps/demo/src/app 디렉토리에 있는 layout.tsx 파일을 열고 다음과 같이 작성합니다.
1/* layout.tsx */
2
3import type { Metadata } from "next";
4import { Footer, Layout, Navbar } from "nextra-theme-docs";
5import { Head } from "nextra/components";
6import { getPageMap } from "nextra/page-map";
7import "./globals.css";
8import "nextra-theme-docs/style.css";
9import { Logo } from "@/components/Logo";
10
11export const metadata: Metadata = {
12 title: {
13 default: "react-toc",
14 template: "%s | react-toc",
15 },
16 authors: [{ name: "HyunJinNo", url: "https://github.com/HyunJinNo" }],
17};
18
19const navbar = (
20 <Navbar
21 logo={
22 <div className="flex flex-row items-center gap-2">
23 <Logo width={40} height={40} />
24 <p className="font-bold">react-toc</p>
25 </div>
26 }
27 projectLink="https://github.com/HyunJinNo/react-toc"
28 // ... Your additional navbar options
29 />
30);
31
32const footer = (
33 <Footer className="flex flex-row gap-1">
34 © {new Date().getFullYear()}
35 <a className="hover:underline" href="https://github.com/HyunJinNo">
36 HyunJinNo.
37 </a>
38 </Footer>
39);
40
41export default async function RootLayout({
42 children,
43}: Readonly<{
44 children: React.ReactNode;
45}>) {
46 return (
47 <html
48 // Not required, but good for SEO
49 lang="ko"
50 // Required to be set
51 dir="ltr"
52 // Suggested by `next-themes` package https://github.com/pacocoursey/next-themes#with-app
53 suppressHydrationWarning
54 >
55 <Head
56 // ... Your additional head options
57 >
58 {/* Your additional tags should be passed as `children` of `<Head>` element */}
59 <link rel="icon" href="/react-toc.webp" sizes="any" />
60 </Head>
61 <body>
62 <Layout
63 navbar={navbar}
64 pageMap={await getPageMap()}
65 docsRepositoryBase="https://github.com/shuding/nextra/tree/main/docs"
66 footer={footer}
67 // ... Your additional layout options
68 >
69 {children}
70 </Layout>
71 </body>
72 </html>
73 );
74}2.2.6. MDX 파일 생성하기
다음과 같이 MDX 파일을 생성하여 문서를 작성할 수 있습니다.
1---
2title: Introduction
3---
4
5# Introduction
6
7`react-toc` is a library that automatically generates a Table of Contents (TOC) from your headings with scroll tracking.
8
9## Features
10
11- 🔍 Automatically builds a nested TOC from `H2` ~ `H6` elements.
12- 🧱 Provides ready-to-use heading components (`H2` ~ `H6`) with unique, URL-friendly `id`.
13- 🎯 Highlights the active heading as the user scrolls.
14- ⚡ Smooth scrolling to sections when a TOC link is clicked.
15- 🎨 Fully customizable with CSS classes and scroll options.
16- 🧩 Works with React / Next.js.
17- ✏️ Written in TypeScript with full type support.2.2.7. _meta.global.js 설정하기
apps/demo/src 디렉토리에 _meta.global.js 파일을 생성하고,
모든 페이지 목록을 작성합니다.
1/* _meta.global.js */
2
3const config = {
4 index: {
5 type: "page",
6 title: "Easy-to-Use TOC Component",
7 display: "hidden",
8 theme: {
9 copyPage: false,
10 layout: "full",
11 toc: false,
12 },
13 },
14 docs: {
15 type: "page",
16 title: "Docs",
17 items: {
18 introduction: {
19 title: "Introduction",
20 },
21 "getting-started": {
22 title: "Getting Started",
23 },
24 api: {
25 title: "API Reference",
26 items: {
27 "toc-provider": {
28 title: "<TocProvider>",
29 },
30 toc: {
31 title: "<Toc>",
32 },
33 headings: {
34 title: "<H2> ~ <H6>",
35 },
36 },
37 },
38 },
39 },
40};
41
42export default config;
2.3. React 라이브러리 설치하기
apps/demo 디렉토리에 있는 package.json 파일을 열고, 다음과 같이 모노레포 내부 패키지를 지정합니다.
1{
2 "dependencies": {
3 "@hyunjinno/react-toc": "workspace:*"
4 }
5}이후 프로젝트 루트에서 다음 명령어를 입력하여 demo에 라이브러리를 설치할 수 있습니다.
1pnpm install2.4. React 라이브러리 사용하기
설치한 라이브러리를 다음과 같이 사용할 수 있습니다.
1/* layout.tsx */
2
3import "@hyunjinno/react-toc/style.css";1/* TocBasic.tsx */
2
3"use client";
4
5import { H2, H3, H4, H5, H6, Toc, TocProvider } from "@hyunjinno/react-toc";
6
7export const TocBasic = () => {
8 return (
9 <TocProvider className="mt-5 flex flex-row justify-between rounded-lg border border-gray-100 p-4 shadow">
10 <div className="flex flex-col gap-4">
11 <H2>a.1. Heading</H2>
12 <H2>a.2. Heading</H2>
13 <H3>a.2.1. Heading</H3>
14 <H3>a.2.2. Heading</H3>
15 <H3>a.2.3. Heading</H3>
16 <H4>a.2.3.1. Heading</H4>
17 <H4>a.2.3.2. Heading</H4>
18 <H4>a.2.3.3. Heading</H4>
19 <H5>a.2.3.3.1. Heading</H5>
20 <H6>a.2.3.3.1.1. Heading</H6>
21 <H3>a.2.4. Heading</H3>
22 <H2>a.3. Heading</H2>
23 </div>
24 <Toc className="w-44" />
25 </TocProvider>
26 );
27};
3. 다음 Part
다음 글에서는 React 라이브러리를 npm에 배포하는 과정을 다룹니다.
4. 참고 자료
- React+typescript 컴포넌트 라이브러리 생성하기 ③rollup 설정 — 콩부합시다
- 고티켓-react 컴포넌트 라이브러리 만들기(3)-rollup — 이찬진 컴퓨터 교실
- esbuild vs rollup vs webpack vs tsup | "웹 자바스크립트 번들러" npm 패키지 비교
- 리액트 컴포넌트 라이브러리를 빌드하고 배포하는 방법 — React와 TypeScript를 좋아하는 개발자
- 리액트 라이브러리 npm에 배포하기 with rollup
- rolldown/tsdown: The elegant bundler for libraries powered by Rolldown
- Nextra - Next.js Static Site Generator
- HyunJinNo/react-toc: A library that automatically generates a Table of Contents (TOC) from your headings with scroll tracking.