perf(theme): 优化 node 结构

This commit is contained in:
pengzhanbo 2024-06-05 00:34:27 +08:00
parent e395e98128
commit 74a69948b8
12 changed files with 82 additions and 45 deletions

View File

@ -42,8 +42,9 @@ useEventListener('message', (event) => {
&& payload
&& payload.feature === props.feature
&& payload.meta === props.meta
)
) {
height.value = `${Math.ceil(payload.height)}px`
}
})
function parseData(data: string | MessageData): MessageData {

View File

@ -34,8 +34,9 @@ export function useNetlifyFunctionsPlugin(app: App, options: UseNetlifyFunctionP
(plugin: PluginObject) =>
plugin.name === 'vuepress-plugin-netlify-functions',
)
)
) {
app.use(netlifyFunctionsPlugin())
}
const { proxyPrefix, directory } = getOptions()
const source = path.join(options.directory, '**/*.js')

View File

@ -28,7 +28,7 @@ export function searchPlugin({
onPrepared: app => prepareSearchIndex({ app, isSearchable, searchOptions }),
onWatched: async (app, watchers) => {
onWatched: (app, watchers) => {
const searchIndexWatcher = chokidar.watch('pages/**/*.js', {
cwd: app.dir.temp(),
ignoreInitial: true,

View File

@ -25,8 +25,9 @@ export function lineNumberPlugin(md: Markdown, { lineNumbers = true }: LineNumbe
if (
(!lineNumbers && !enableLineNumbers)
|| (lineNumbers && disableLineNumbers)
)
) {
return rawCode
}
const code = rawCode.slice(
rawCode.indexOf('<code>'),
@ -39,8 +40,9 @@ export function lineNumberPlugin(md: Markdown, { lineNumbers = true }: LineNumbe
typeof lineNumbers === 'number'
&& lines.length < lineNumbers
&& !enableLineNumbers
)
) {
return rawCode
}
const startNumbers
= Number(info.match(LINE_NUMBERS_START_REGEXP)?.[1] ?? 1) - 1

View File

@ -1,6 +1,6 @@
import { onMounted, onUnmounted, onUpdated } from 'vue'
import type { Ref } from 'vue'
import type { PlumeThemeLocaleData } from '../../shared/index.js'
import type { ThemeOutline } from '../../shared/index.js'
import { throttleAndDebounce } from '../utils/index.js'
import { useAside } from './aside.js'
@ -41,7 +41,7 @@ export type MenuItem = Omit<Header, 'slug' | 'children'> & {
children?: MenuItem[]
}
export function getHeaders(range: PlumeThemeLocaleData['outline']): MenuItem[] {
export function getHeaders(range?: ThemeOutline): MenuItem[] {
const headers = Array.from(
document.querySelectorAll('.plume-content :where(h1,h2,h3,h4,h5,h6)'),
)
@ -68,8 +68,9 @@ function serializeHeader(h: Element): string {
if (
(node as Element).classList.contains('badge-view')
|| (node as Element).classList.contains('ignore-header')
)
) {
continue
}
ret += node.textContent
}
@ -88,7 +89,7 @@ function serializeHeader(h: Element): string {
return ret.trim()
}
export function resolveHeaders(headers: MenuItem[], range?: PlumeThemeLocaleData['outline']): MenuItem[] {
export function resolveHeaders(headers: MenuItem[], range?: ThemeOutline): MenuItem[] {
if (range === false)
return []

View File

@ -0,0 +1,18 @@
import { addViteConfig, addViteOptimizeDepsInclude, addViteSsrNoExternal } from '@vuepress/helper'
import type { App } from 'vuepress'
export function extendsBundlerOptions(bundlerOptions: any, app: App): void {
addViteConfig(bundlerOptions, app, {
build: {
chunkSizeWarningLimit: 1024,
},
})
addViteOptimizeDepsInclude(bundlerOptions, app, '@vueuse/core', true)
addViteSsrNoExternal(bundlerOptions, app, [
'@vuepress/helper',
'@vuepress/plugin-reading-time',
'@vuepress/plugin-watermark',
])
}

View File

@ -92,8 +92,9 @@ export function getPlugins({
}))
}
if (pluginOptions.nprogress !== false)
if (pluginOptions.nprogress !== false) {
plugins.push(nprogressPlugin())
}
if (pluginOptions.git ?? isProd) {
plugins.push(gitPlugin({
@ -171,14 +172,17 @@ export function getPlugins({
}))
}
if (pluginOptions.comment)
if (pluginOptions.comment) {
plugins.push(commentPlugin(pluginOptions.comment))
}
if (pluginOptions.baiduTongji !== false && pluginOptions.baiduTongji?.key && isProd)
if (pluginOptions.baiduTongji !== false && pluginOptions.baiduTongji?.key && isProd) {
plugins.push(baiduTongjiPlugin(pluginOptions.baiduTongji))
}
if (pluginOptions.sitemap !== false && hostname && isProd)
if (pluginOptions.sitemap !== false && hostname && isProd) {
plugins.push(sitemapPlugin({ hostname }))
}
if (pluginOptions.seo !== false && hostname && isProd) {
plugins.push(seoPlugin({

View File

@ -0,0 +1,11 @@
import { type TemplateRendererContext, templateRenderer } from 'vuepress/utils'
import { getThemePackage } from './utils.js'
export function templateBuildRenderer(template: string, context: TemplateRendererContext) {
const pkg = getThemePackage()
template = template
.replace('{{ themeVersion }}', pkg.version || '')
.replace(/^\s+|\s+$/gm, '')
.replace(/\n/g, '')
return templateRenderer(template, context)
}

View File

@ -1,11 +1,13 @@
import type { Page, Theme } from 'vuepress/core'
import { templateRenderer } from 'vuepress/utils'
import { addViteConfig, addViteOptimizeDepsInclude, addViteSsrNoExternal, isPlainObject } from '@vuepress/helper'
import { isPlainObject } from '@vuepress/helper'
import type { PlumeThemeOptions, PlumeThemePageData } from '../shared/index.js'
import { getPlugins } from './plugins/index.js'
import { extendsPageData, setupPage } from './setupPages.js'
import { THEME_NAME, getThemePackage, logger, resolve, templates } from './utils.js'
import { THEME_NAME, logger, resolve, templates } from './utils.js'
import { resolveEncrypt, resolveLocaleOptions, resolvePageHead } from './config/index.js'
import { extendsBundlerOptions } from './extendsBundlerOptions.js'
import { templateBuildRenderer } from './templateBuildRenderer.js'
import { setupPrepare, watchPrepare } from './prepare/index.js'
export function plumeTheme({
themePlugins,
@ -15,7 +17,6 @@ export function plumeTheme({
...localeOptions
}: PlumeThemeOptions = {}): Theme {
const pluginOptions = plugins ?? themePlugins ?? {}
const pkg = getThemePackage()
const watermarkFullPage = isPlainObject(pluginOptions.watermark)
? pluginOptions.watermark.fullPage !== false
@ -29,6 +30,7 @@ export function plumeTheme({
return (app) => {
localeOptions = resolveLocaleOptions(app, localeOptions)
return {
name: THEME_NAME,
@ -43,34 +45,26 @@ export function plumeTheme({
plugins: getPlugins({ app, pluginOptions, localeOptions, encrypt, hostname }),
onInitialized: async app => await setupPage(app, localeOptions),
onInitialized: async (app) => {
await setupPage(app, localeOptions)
},
onPrepared: async (app) => {
await setupPrepare(app)
},
onWatched: (app, watchers) => {
watchPrepare(app, watchers)
},
extendsPage: (page) => {
extendsPageData(page as Page<PlumeThemePageData>, localeOptions)
resolvePageHead(page, localeOptions)
},
extendsBundlerOptions(bundlerOptions, app) {
addViteConfig(bundlerOptions, app, {
build: {
chunkSizeWarningLimit: 1024,
},
})
addViteOptimizeDepsInclude(bundlerOptions, app, '@vueuse/core', true)
addViteSsrNoExternal(bundlerOptions, app, [
'@vuepress/helper',
'@vuepress/plugin-reading-time',
'@vuepress/plugin-watermark',
])
},
extendsBundlerOptions,
templateBuildRenderer(template, context) {
template = template
.replace('{{ themeVersion }}', pkg.version || '')
.replace(/^\s+|\s+$/gm, '')
.replace(/\n/g, '')
return templateRenderer(template, context)
},
templateBuildRenderer,
}
}
}

View File

@ -1,8 +1,12 @@
export type PlumeThemeImage =
export type ThemeImage =
| string
| { src: string, alt?: string }
| { dark: string, light: string, alt?: string }
export type ThemeColor = string | { light: string, dark: string }
export type ThemeOutline = false | number | [number, number] | 'deep'
export interface SocialLink {
icon: SocialLinkIcon
link: string

View File

@ -1,5 +1,6 @@
import type { WatermarkPluginFrontmatter } from '@vuepress/plugin-watermark'
import type { NavItemWithLink, PlumeThemeImage } from '.'
import type { ThemeImage, ThemeOutline } from './base.js'
import type { NavItemWithLink } from './options/navbar.js'
/* =============================== Home begin ==================================== */
export interface PlumeThemeHomeFrontmatter extends Omit<PlumeThemeHomeBanner, 'type'> {
@ -58,7 +59,7 @@ export interface PlumeThemeHomeHero extends PlumeHomeConfigBase {
export interface PlumeThemeHomeTextImage extends PlumeHomeConfigBase {
type: 'text-image' | 'image-text'
image: PlumeThemeImage
image: ThemeImage
width?: number | string
title?: string
description?: string
@ -101,7 +102,7 @@ export interface PlumeThemeHomeProfile extends PlumeHomeConfigBase {
type: 'profile'
name?: string
description?: string
avatar?: PlumeThemeImage
avatar?: ThemeImage
circle?: boolean
}
@ -119,7 +120,7 @@ export interface PlumeThemePageFrontmatter {
contributors?: boolean
prev?: string | NavItemWithLink
next?: string | NavItemWithLink
outline?: false | number | [number, number] | 'deep'
outline?: ThemeOutline
backToTop?: boolean
externalLink?: boolean
readingTime?: boolean

View File

@ -1,6 +1,6 @@
import type { LocaleData } from 'vuepress/core'
import type { NotesDataOptions } from '@vuepress-plume/plugin-notes-data'
import type { SocialLink, SocialLinkIconUnion } from '../base.js'
import type { SocialLink, SocialLinkIconUnion, ThemeOutline } from '../base.js'
import type { PlumeThemeBlog } from '../blog.js'
import type { NavItem } from './navbar.js'
@ -74,7 +74,7 @@ export interface PlumeThemeLocaleData extends LocaleData {
*/
notes?: false | NotesDataOptions
outline?: false | number | [number, number] | 'deep'
outline?: ThemeOutline
/**
* language text