You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+121-1Lines changed: 121 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -90,6 +90,115 @@ Notes:
90
90
-`vue-i18n` is optional: the library provides a synchronous fallback translator. If your app uses `vue-i18n`, the library will automatically wire into it at runtime when available.
91
91
- If you're installing this library inside a monorepo or using pnpm workspaces, install peers at the workspace root so they are available to consuming packages.
92
92
93
+
## Server-Side Rendering (SSR)
94
+
95
+
This library is designed to be safe to import in SSR builds, but several features depend on browser-only APIs (DOM, Clipboard, Web Workers, Monaco, Mermaid, KaTeX). To avoid runtime errors during server-side rendering, the library lazy-loads heavyweight peers and guards browser globals where possible. However, some advanced features (Monaco editor, Mermaid progressive rendering, Web Workers) are inherently client-side and must be used inside client-only blocks in SSR environments.
96
+
97
+
Recommended consumption patterns:
98
+
99
+
- For Nuxt 3 (or other SSR frameworks): render the component client-side only. Example using Nuxt's <client-only> wrapper:
100
+
101
+
```vue
102
+
<template>
103
+
<client-only>
104
+
<MarkdownRender :content="markdown" />
105
+
</client-only>
106
+
</template>
107
+
```
108
+
109
+
For a fuller Nuxt 3 recipe and extra notes, see the docs: `docs/nuxt-ssr.md`.
110
+
111
+
- For Vite + plain SSR (or when you control hydration): conditionally render on the client with a small wrapper component:
112
+
113
+
```vue
114
+
<script setup lang="ts">
115
+
import { onMounted, ref } from 'vue'
116
+
import MarkdownRender from 'vue-renderer-markdown'
117
+
118
+
const mounted = ref(false)
119
+
onMounted(() => {
120
+
mounted.value = true
121
+
})
122
+
</script>
123
+
124
+
<template>
125
+
<div v-if="mounted">
126
+
<MarkdownRender :content="markdown" />
127
+
</div>
128
+
<div v-else>
129
+
<!-- SSR fallback: simple preformatted text to avoid heavy client peers -->
130
+
<pre>{{ markdown }}</pre>
131
+
</div>
132
+
</template>
133
+
```
134
+
135
+
Notes and caveats:
136
+
137
+
- If you depend on Monaco, Mermaid, KaTeX or the optional icon pack at runtime, install those peers in your app and ensure they are available on the client. The library will attempt to lazy-load them only in the browser.
138
+
- The library aims to avoid throwing on import during SSR. If you still see ReferenceErrors (e.g. `window is not defined`), please open an issue and include the stack trace — I'll prioritize a fix.
139
+
- For server-rendered markup that needs diagrams or highlighted code server-side, consider generating static HTML on the server (e.g., pre-render Mermaid/KaTeX output) and pass it into the renderer as raw HTML or a safe, server-side AST.
140
+
141
+
If you'd like, I can add an explicit "SSR" recipe and a Nuxt module example to the repo — say the word and I'll add it.
142
+
143
+
### SSR recipe (Nuxt 3 and Vite SSR)
144
+
145
+
Below are concrete recipes to run this renderer safely in SSR environments. These cover common setups and show how to avoid importing client-only peers during server rendering.
146
+
147
+
- Nuxt 3 (recommended for full-app SSR)
148
+
149
+
1. Install peers you need on the client (for example `mermaid`, `vue-use-monaco`) as normal dependencies in your Nuxt app.
150
+
2. Use Nuxt's `<client-only>` wrapper for pages or components that rely on client-only features like Monaco or progressive Mermaid:
151
+
152
+
```vue
153
+
<template>
154
+
<client-only>
155
+
<MarkdownRender :content="markdown" />
156
+
</client-only>
157
+
</template>
158
+
```
159
+
160
+
3. If you need server-rendered HTML for specific diagrams or math, pre-render those outputs on the server (for example using a small service or build step that runs KaTeX or Mermaid CLI) and pass the resulting HTML into your page as pre-rendered fragments.
161
+
162
+
- Vite + custom SSR (manual hydrate)
163
+
164
+
If you run your own Vite SSR pipeline, prefer a client-only wrapper to delay browser-only initialization until hydration:
165
+
166
+
```vue
167
+
<script setup lang="ts">
168
+
import { onMounted, ref } from 'vue'
169
+
import MarkdownRender from 'vue-renderer-markdown'
170
+
171
+
const mounted = ref(false)
172
+
onMounted(() => {
173
+
mounted.value = true
174
+
})
175
+
</script>
176
+
177
+
<template>
178
+
<div v-if="mounted">
179
+
<MarkdownRender :content="markdown" />
180
+
</div>
181
+
<div v-else>
182
+
<!-- Lightweight SSR fallback to avoid heavy peers on the server -->
183
+
<pre>{{ markdown }}</pre>
184
+
</div>
185
+
</template>
186
+
```
187
+
188
+
Notes:
189
+
190
+
- The package aims to be import-safe during SSR: heavy peers are lazy-loaded in the browser and many DOM/Worker usages are guarded. However, some features (Monaco editor, Web Workers, progressive Mermaid rendering) are client-only by nature — they must be used inside client-only wrappers or deferred with lifecycle hooks.
191
+
- To guard against regressions, this repo includes a small SSR smoke test you can run locally:
192
+
193
+
```bash
194
+
pnpm run check:ssr
195
+
```
196
+
197
+
This uses Vitest to import the library entry (`src/exports`) in a Node environment and will fail if the import throws during SSR.
198
+
199
+
- CI: a small GitHub Actions workflow (`.github/workflows/ci.yml`) has been added to run typecheck and tests (including the SSR smoke test) on push and PR to `main`.
200
+
201
+
If you'd like, I can add a short Nuxt module wrapper or a dedicated example page for Nuxt to the `playground/` directory — say the word and I'll scaffold it.
93
202
## Quick Start
94
203
95
204
### Choose Your Code Block Rendering Style
@@ -636,11 +745,22 @@ If your project uses Webpack instead of Vite, you can use the official `monaco-e
This short recipe shows a minimal, safe way to use `vue-renderer-markdown` in Nuxt 3 so that client-only features (Monaco, Mermaid, Web Workers) are only initialized in the browser.
4
+
5
+
## Install peers (client-side)
6
+
7
+
Install the peers you need in your Nuxt app. For example, to enable Mermaid and Monaco editor previews (optional):
8
+
9
+
```bash
10
+
# pnpm (recommended)
11
+
pnpm add mermaid vue-use-monaco
12
+
13
+
# npm
14
+
npm install mermaid vue-use-monaco
15
+
```
16
+
17
+
Do NOT import these peers from server-only code paths during SSR.
18
+
19
+
## Example page (client-only wrapper)
20
+
21
+
Create a page or component that defers mounting the renderer to the client. Nuxt provides a `<client-only>` built-in wrapper which is perfect:
22
+
23
+
```vue
24
+
<script setup lang="ts">
25
+
import { ref } from 'vue'
26
+
import MarkdownRender from 'vue-renderer-markdown'
27
+
28
+
const markdown = ref(`# Hello from Nuxt 3\n\nThis content is rendered only on the client.`)
29
+
</script>
30
+
31
+
<template>
32
+
<client-only>
33
+
<MarkdownRender :content="markdown" />
34
+
</client-only>
35
+
</template>
36
+
```
37
+
38
+
This ensures the `MarkdownRender` component (and any optional peers it lazy-loads) are only imported/initialized in the browser.
39
+
40
+
## Server-rendered diagrams or math
41
+
42
+
If you need server-rendered HTML for diagrams or math (so crawlers or first paint include them), pre-render those outputs during your build step or via a small server-side task. Example approaches:
43
+
44
+
- Use a build script that runs `mermaid-cli` / `katex` to convert certain diagrams/formulas to HTML/SVG during content generation and embed the resulting HTML into the page.
45
+
- Use a server endpoint that returns pre-rendered diagram SVG/HTML and fetch it on the client as needed.
46
+
47
+
Then pass pre-rendered fragments into the renderer as trusted HTML or a server-side AST so the client avoids heavy initialization for those artifacts.
48
+
49
+
## Notes
50
+
51
+
- Prefer `client-only` when using Monaco Editor, Web Workers, or progressive Mermaid.
52
+
- The library is designed to be import-safe during SSR: heavy peers are lazy-loaded in the browser and many DOM/Worker usages are guarded. If you see an import-time ReferenceError, please provide the stack trace.
53
+
54
+
---
55
+
56
+
If you'd like, I can also add a ready-to-run Nuxt 3 playground example under `playground/` (small project + page) that shows this integration end-to-end.
0 commit comments