Skip to content

Commit

Permalink
feat(Blog): ✨ Using Client Side nuxt-Shiki for syntax highlighting
Browse files Browse the repository at this point in the history
Since Server-Side Markdown + Syntax Highlight Parsing is taking too much time, especially on first time visit or after a few hours.
This changes will slightly increase client side bundle size.
  • Loading branch information
bKoZii committed Oct 11, 2024
1 parent 9cbee5a commit 61ce97c
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 20 deletions.
20 changes: 11 additions & 9 deletions components/global/ProsePre.vue
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<template>
<div class="pre relative">
<div v-if="$props.filename" class="rounded-t-lg border-b-0 bg-neutral-900 p-2 text-xs dark:border dark:border-neutral-700 dark:bg-neutral-900">
<div class="relative">
<div v-if="$props.filename" class="rounded-t-lg bg-neutral-900 p-2 text-xs border border-b border-neutral-600 dark:border-neutral-800 dark:border-b-0 dark:bg-neutral-900">
<div class="flex flex-row flex-nowrap items-center justify-between gap-2 text-white">
<span class="tracking-normal">{{ $props.filename }}</span>
<UButton
variant="solid"
variant="soft"
class="p-1"
:color="copied ? 'primary' : 'white'"
size="xs"
Expand All @@ -15,7 +15,6 @@
/>
</div>
</div>

<div v-else>
<UButton
variant="solid"
Expand All @@ -28,18 +27,19 @@
@click="copy($props.code as string)"
/>
</div>
<pre
class="pre-body"
:class="`${$props.class} ${$props.filename ? '!rounded-t-none': '!rounded-t-lg'} !mt-0 !rounded-t-none tracking-normal dark:border dark:border-t-0 dark:border-neutral-700`"
><slot /></pre>
<div
:class="`${$props.class} ${$props.filename ? 'prose-pre:rounded-t-none': 'rounded-t-lg'} !mt-0 tracking-normal m-0 prose-pre:m-0 `"
v-html="html"
/>
</div>
</template>

<script setup lang="ts">
import type { BundledLanguage } from 'shiki'
const toast = useToast()
defineProps({
const props = defineProps({
code: {
type: String,
default: '',
Expand All @@ -66,6 +66,8 @@ defineProps({
},
})
const html = await useShikiHighlighted(props.code, { lang: props.language })
const { copy, copied } = useClipboard()
watch(copied, (value) => {
Expand Down
29 changes: 21 additions & 8 deletions nuxt.config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// https://nuxt.com/docs/api/configuration/nuxt-config
import wasm from '@rollup/plugin-wasm'

export default defineNuxtConfig({
devtools: {
Expand Down Expand Up @@ -30,6 +31,7 @@ export default defineNuxtConfig({
'@formkit/auto-animate/nuxt',
'@nuxtjs/mdc',
'@vueuse/nuxt',
'nuxt-shiki',
],

app: {
Expand Down Expand Up @@ -159,20 +161,31 @@ export default defineNuxtConfig({
},
},
mdc: {
highlight: {
highlighter: 'shiki',
theme: 'aurora-x',
themes: ['aurora-x'],
langs: ['javascript', 'typescript', 'json', 'vue', 'shell', 'php'],
wrapperStyle: false,
},
highlight: false,
headings: {
anchorLinks: false,
},
components: {
prose: false,
map: {
['pre']: 'ProsePre',
pre: 'ProsePre',
},
},
},
shiki: {
bundledLangs: ['javascript', 'typescript', 'vue', 'shell', 'php'],
bundledThemes: ['houston'],
defaultTheme: 'houston',
},
vite: {
plugins: [wasm()],
build: {
rollupOptions: {
output: {
manualChunks: {
wasm: ['*.wasm'],
},
},
},
},
},
Expand Down
13 changes: 10 additions & 3 deletions pages/blog/[slug].vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
<section
class="prose prose-neutral dark:prose-invert prose-sm md:prose-base prose-h1:mb-5 prose-h2:my-4 prose-pre:text-sm dark:prose-pre:border dark:prose-pre:border-neutral-800 prose-li:my-1 max-w-none font-sans tracking-tight"
>
<div v-if="blogSlug.content">
<MDC :value="blogSlug.content" tag="article" />
<div v-if="ast">
<MDCRenderer :body="ast" tag="article" />
</div>
<div v-else-if="status == 'pending'">
<div v-else-if="status == 'pending' || parseStatus == 'pending'">
<LazyUAlert
class="not-prose"
title="Loading"
Expand Down Expand Up @@ -81,6 +81,13 @@ const { status } = await useAsyncData(
},
},
)
const { data: ast, status: parseStatus } = await useFetch('/api/mdc', {
method: 'POST',
body: { content: blogSlug.value?.content },
cache: 'force-cache',
})
useSeoMeta({
title: blogSlug.value?.title,
ogTitle: '%s [Blogs - Konkamon]',
Expand Down

0 comments on commit 61ce97c

Please sign in to comment.