레시피
Pele와 pele-animate는 DOM이 필요하므로 어떤 프레임워크에서든 원칙은 같습니다. 페이지가 렌더링된 뒤에 클라이언트에서 마운트해야 합니다. 서버 렌더링이 이 패키지를 건드리지 않도록, 프레임워크의 마운트 훅 안에서 동적 import()로 불러오시기 바랍니다.
기본 형태는 항상 다음과 같습니다.
const [{ mount }, { watch, prepare }, { icons }] = await Promise.all([
import('pele'),
import('pele-animate'),
import('pele-animate/glyphs'),
import('pele-animate/tabler/computers'), // 사용할 아이콘 카테고리
import('pele-animate/style.css'),
]);
mount(el, prepare(src), { icons });
watch(el, src);| 프레임워크 | 상태 | 코드를 두는 곳 |
|---|---|---|
| 일반 HTML / Vite | 검증함 | 시작하기와 같은 모듈 스크립트 |
| Astro | 운영 환경에서 검증함 (DoveRunner 문서 사이트) | 다이어그램 요소를 찾는 클라이언트 <script> |
| SvelteKit 3 | 검증함 (빌드와 브라우저, static 어댑터) | 페이지 또는 컴포넌트의 onMount(async () => { ... }) |
| Nuxt 4 | 검증함 (빌드와 브라우저, static generate) | .client.vue 컴포넌트의 onMounted |
| React / Next.js | 검증하지 않음 | useEffect를 쓰는 클라이언트 컴포넌트('use client') |
| Vue (Nuxt 제외) | 검증하지 않음 | onMounted |
모든 프레임워크에 공통으로 적용되는 참고 사항입니다.
- 다이어그램마다 Mermaid 소스를 담은 별도 요소(
<pre>또는<div>)를 두고, 요소마다mount와watch를 한 번씩 호출합니다. - 새로고침 없이 페이지가 바뀌는 경우(클라이언트 사이드 라우팅)에는 새 요소에 대해 다시 마운트합니다.
- CSS(
pele-animate/style.css)는 한 번만 import하면 됩니다. TypeScript에서는 CSS를 부수 효과로 import하려면*.css모듈 선언이 필요합니다(Vite 프로젝트는vite/client에서 받습니다). - 정적 사이트 생성기도 문제없습니다. 서버가 필요한 부분은 없습니다.
Astro
<pre class="mermaid" set:text={src}></pre>
<script>
// 브라우저에서만 실행됩니다
import { mount } from 'pele';
import { watch, prepare } from 'pele-animate';
import { icons } from 'pele-animate/glyphs';
import 'pele-animate/tabler/computers';
import 'pele-animate/style.css';
document.querySelectorAll('pre.mermaid').forEach((el) => {
const src = el.textContent ?? '';
mount(el as HTMLElement, prepare(src), { icons });
watch(el as HTMLElement, src);
});
</script>SvelteKit
<script>
import { onMount } from 'svelte';
let el;
const src = 'flowchart LR\n A --> B';
onMount(async () => {
const [{ mount }, { watch, prepare }, { icons }] = await Promise.all([
import('pele'), import('pele-animate'), import('pele-animate/glyphs'), import('pele-animate/style.css'),
]);
mount(el, prepare(src), { icons });
watch(el, src);
});
</script>
<div bind:this={el}></div>