|
1 |
| -import { defineConfigWithTheme } from 'vitepress' |
| 1 | +import { EnhanceAppContext, defineConfigWithTheme } from 'vitepress' |
| 2 | +import { setup } from '@css-render/vue3-ssr' |
2 | 3 | import { createContainer } from './utils'
|
3 | 4 | import { ThemeConfig } from './theme'
|
4 | 5 | import tags from './tags'
|
| 6 | +import { renderToString } from 'vue/server-renderer' |
| 7 | +import { Mutex } from 'async-mutex' |
| 8 | + |
| 9 | +const transformHtmlMutex = new Mutex() |
5 | 10 |
|
6 | 11 | export default defineConfigWithTheme<ThemeConfig>({
|
7 | 12 | title: 'SynBlog',
|
@@ -39,6 +44,29 @@ export default defineConfigWithTheme<ThemeConfig>({
|
39 | 44 |
|
40 | 45 | ignoreDeadLinks: 'localhostLinks',
|
41 | 46 |
|
| 47 | + async transformHtml(html, id, ctx) { |
| 48 | + // VitePress 似乎是对所有页面同时进行渲染,但因为限制只能拿到一个固定的 App 实例,所以需要加互斥锁,防止抢 router |
| 49 | + const release = await transformHtmlMutex.acquire() |
| 50 | + try { |
| 51 | + // ./theme/index.ts 中存了一个全局的 App 实例下来 |
| 52 | + const { app, router } = (globalThis as any).__EnhanceAppContext__ as EnhanceAppContext |
| 53 | + const { collect } = setup(app) |
| 54 | + |
| 55 | + // 随后仿照 VitePress 走 SSR 渲染流程 |
| 56 | + // https://github.com/vuejs/vitepress/blob/main/src/client/app/ssr.ts |
| 57 | + const path = (this.base || '/') + ctx.page.replace(/\.md$/, '.html') |
| 58 | + await router.go(path) |
| 59 | + await renderToString(app) |
| 60 | + |
| 61 | + // 此时可以收集到所有的 CSS 了! |
| 62 | + const styles = collect() |
| 63 | + return html.replace('<head>', `<head>${styles}`) |
| 64 | + } finally { |
| 65 | + // 释放互斥锁 |
| 66 | + release() |
| 67 | + } |
| 68 | + }, |
| 69 | + |
42 | 70 | themeConfig: {
|
43 | 71 | tags,
|
44 | 72 |
|
|
0 commit comments