perf: optimize debug logs (#371)

This commit is contained in:
pengzhanbo 2024-12-07 05:14:02 +08:00 committed by GitHub
parent 54c460e2c9
commit e7ba5621f7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
19 changed files with 78 additions and 83 deletions

View File

@ -1,4 +1,4 @@
import type { Bundler, Langs, Options, PromptResult } from './types.js'
import type { Bundler, Langs, PromptResult } from './types.js'
import { createRequire } from 'node:module'
import process from 'node:process'
import { cancel, confirm, group, select, text } from '@clack/prompts'
@ -20,7 +20,7 @@ export async function prompt(mode: Mode, root?: string): Promise<PromptResult> {
const result: PromptResult = await group({
displayLang: async () => {
const lang = await select<Options<Langs>, Langs>({
const lang = await select<Langs>({
message: 'Select a language to display / 选择显示语言',
options: languageOptions,
})
@ -68,7 +68,7 @@ export async function prompt(mode: Mode, root?: string): Promise<PromptResult> {
initialValue: false,
}),
defaultLanguage: () => select<Options<Langs>, Langs>({
defaultLanguage: () => select<Langs>({
message: t('question.defaultLanguage'),
options: languageOptions,
}),
@ -93,7 +93,7 @@ export async function prompt(mode: Mode, root?: string): Promise<PromptResult> {
})
},
bundler: () => select<Options<Bundler>, Bundler>({
bundler: () => select<Bundler>({
message: t('question.bundler'),
options: bundlerOptions,
}),
@ -102,7 +102,7 @@ export async function prompt(mode: Mode, root?: string): Promise<PromptResult> {
if (mode === Mode.init) {
return DeployType.custom
}
return await select<Options<DeployType>, DeployType>({
return await select<DeployType>({
message: t('question.deploy'),
options: deployOptions,
initialValue: DeployType.custom,

View File

@ -5,7 +5,7 @@ import type {
} from '../types.js'
import {
getLocalePaths,
getRootLangPath,
inferRootLocalePath,
isPlainObject,
} from '@vuepress/helper'
import { ensureLeadingSlash, resolveLocalePath } from 'vuepress/shared'
@ -18,7 +18,7 @@ export function createCopyCodeButtonRender(app: App, options?: boolean | CopyCod
const { className = 'copy', locales: userLocales = {} }
= isPlainObject(options) ? options : {}
const root = getRootLangPath(app)
const root = inferRootLocalePath(app)
const locales: LocaleConfig<CopyCodeLocaleOptions> = {
// fallback locale
'/': userLocales['/'] || copyCodeButtonLocales[root],

View File

@ -13,7 +13,7 @@ import grayMatter from 'gray-matter'
import jsonToYaml from 'json2yaml'
import { fs, hash, path } from 'vuepress/utils'
import { getThemeConfig } from '../loadConfig/index.js'
import { logger } from '../utils/index.js'
import { perfLog, perfMark } from '../utils/index.js'
import { readMarkdown, readMarkdownList } from './readFile.js'
import { resolveOptions } from './resolveOptions.js'
@ -88,7 +88,7 @@ export function initAutoFrontmatter(
}
export async function generateAutoFrontmatter(app: App) {
const start = performance.now()
perfMark('generate:frontmatter')
if (!generate)
return
@ -109,9 +109,7 @@ export async function generateAutoFrontmatter(app: App) {
await generate.updateCache(app)
if (app.env.isDebug) {
logger.info(`Generate auto frontmatter: ${(performance.now() - start).toFixed(2)}ms`)
}
perfLog('generate:frontmatter', app.env.isDebug)
}
export async function watchAutoFrontmatter(app: App, watchers: any[]) {

View File

@ -1,13 +1,13 @@
import type { App } from 'vuepress'
import type { PlumeThemePluginOptions } from '../../shared/index.js'
import { entries, fromEntries, getLocalePaths, getRootLangPath, isPlainObject } from '@vuepress/helper'
import { entries, fromEntries, getLocalePaths, inferRootLocalePath, isPlainObject } from '@vuepress/helper'
import { PRESET_LOCALES } from '../locales/index.js'
export function resolveProvideData(
app: App,
plugins: PlumeThemePluginOptions,
): Record<string, any> {
const root = getRootLangPath(app)
const root = inferRootLocalePath(app)
const locales = [...getLocalePaths(app), root]
return {
// 注入水印配置

View File

@ -6,7 +6,7 @@ import { colors } from 'vuepress/utils'
import { logger } from '../utils/index.js'
const CONFIG_FILE_NAME = 'plume.config'
const extensions: string[] = ['ts', 'js', 'mts', 'cts', 'mjs', 'cjs']
const extensions: string[] = ['ts', 'js', 'mjs', 'cjs', 'mts', 'cts']
export async function findConfigPath(app: App, configPath?: string): Promise<string | undefined> {
const cwd = process.cwd()

View File

@ -6,7 +6,7 @@ import { deepMerge } from '@pengzhanbo/utils'
import { watch } from 'chokidar'
import { path } from 'vuepress/utils'
import { resolveLocaleOptions } from '../config/resolveLocaleOptions.js'
import { logger } from '../utils/index.js'
import { perfLog, perfMark } from '../utils/index.js'
import { compiler } from './compiler.js'
import { findConfigPath } from './findConfigPath.js'
@ -41,7 +41,7 @@ export async function initConfigLoader(
defaultConfig: ThemeConfig,
{ configFile, onChange }: InitConfigLoaderOptions = {},
) {
const start = performance.now()
perfMark('load-config')
const { encrypt, autoFrontmatter, ...localeOptions } = defaultConfig
loader = {
configFile,
@ -58,21 +58,18 @@ export async function initConfigLoader(
},
}
const findStart = performance.now()
perfMark('load-config:find')
loader.configFile = await findConfigPath(app, configFile)
if (app.env.isDebug) {
logger.info(`Find config path: ${(performance.now() - findStart).toFixed(2)}ms`)
}
perfLog('load-config:find', app.env.isDebug)
if (onChange) {
loader.changeEvents.push(onChange)
}
const loadStart = performance.now()
perfMark('load-config:loaded')
const { config, dependencies = [] } = await loader.load()
if (app.env.isDebug) {
logger.info(`theme config call load: ${(performance.now() - loadStart).toFixed(2)}ms`)
}
perfLog('load-config:loaded', app.env.isDebug)
loader.loaded = true
loader.dependencies = [...dependencies]
updateResolvedConfig(app, config)
@ -80,9 +77,7 @@ export async function initConfigLoader(
loader.whenLoaded.forEach(fn => fn(loader!.resolvedConfig))
loader.whenLoaded = []
if (app.env.isDebug) {
logger.info(`Load config: ${(performance.now() - start).toFixed(2)}ms`)
}
perfLog('load-config', app.env.isDebug)
}
export function watchConfigFile(app: App, watchers: any[], onChange: ChangeEvent) {

View File

@ -2,12 +2,13 @@ import type { App, Page } from 'vuepress/core'
import type { PlumeThemeLocaleOptions } from '../../shared/index.js'
import { getRootLang } from '@vuepress/helper'
import { createPage } from 'vuepress/core'
import { withBase } from '../utils/index.js'
import { perfLog, perfMark, withBase } from '../utils/index.js'
export async function createPages(app: App, localeOption: PlumeThemeLocaleOptions) {
if (localeOption.blog === false)
return
perfMark('create:blog-pages')
const pageList: Promise<Page>[] = []
const locales = localeOption.locales || {}
const rootLang = getRootLang(app)
@ -53,4 +54,6 @@ export async function createPages(app: App, localeOption: PlumeThemeLocaleOption
}
app.pages.push(...await Promise.all(pageList))
perfLog('create:blog-pages', app.env.isDebug)
}

View File

@ -21,7 +21,7 @@ import { watermarkPlugin } from '@vuepress/plugin-watermark'
import { type MarkdownEnhancePluginOptions, mdEnhancePlugin } from 'vuepress-plugin-md-enhance'
import { markdownPowerPlugin } from 'vuepress-plugin-md-power'
import { resolveDocsearchOptions, resolveSearchOptions } from '../config/index.js'
import { deleteAttrs } from '../utils/index.js'
import { omit } from '../utils/index.js'
export interface SetupPluginOptions {
app: App
@ -119,7 +119,7 @@ export function getPlugins(
const options: MarkdownEnhancePluginOptions = {
...pluginOptions.markdownEnhance,
}
plugins.push(mdEnhancePlugin(deleteAttrs(options, 'hint', 'alert', 'imgSize', 'imgLazyload', 'imgMark', 'figure', 'obsidianImgSize', 'katex', 'mathjax', 'tabs', 'codetabs', 'align', 'mark', 'sub', 'sup', 'attrs', 'tasklist', 'footnote')))
plugins.push(mdEnhancePlugin(omit(options, 'hint', 'alert', 'imgSize', 'imgLazyload', 'imgMark', 'figure', 'obsidianImgSize', 'katex', 'mathjax', 'tabs', 'codetabs', 'align', 'mark', 'sub', 'sup', 'attrs', 'tasklist', 'footnote')))
}
if (pluginOptions.markdownPower !== false) {

View File

@ -1,7 +1,7 @@
import type { App } from 'vuepress'
import { watch } from 'chokidar'
import { getThemeConfig } from '../loadConfig/index.js'
import { logger } from '../utils/index.js'
import { perfLog, perfMark } from '../utils/index.js'
import { prepareArticleTagColors } from './prepareArticleTagColor.js'
import { preparedBlogData } from './prepareBlogData.js'
import { prepareEncrypt } from './prepareEncrypt.js'
@ -11,7 +11,7 @@ import { prepareSidebar } from './prepareSidebar.js'
export async function prepareData(
app: App,
): Promise<void> {
const start = performance.now()
perfMark('prepare:data')
const { localeOptions, encrypt } = getThemeConfig()
await Promise.all([
prepareArticleTagColors(app, localeOptions),
@ -21,9 +21,7 @@ export async function prepareData(
prepareIcons(app, localeOptions),
])
if (app.env.isDebug) {
logger.info(`Prepare data: ${(performance.now() - start).toFixed(2)}ms`)
}
perfLog('prepare:data', app.env.isDebug)
}
export function watchPrepare(

View File

@ -2,7 +2,7 @@ import type { App } from 'vuepress'
import type { PlumeThemeLocaleOptions } from '../../shared/index.js'
import { toArray } from '@pengzhanbo/utils'
import { isPlainObject } from 'vuepress/shared'
import { logger, nanoid, resolveContent, writeTemp } from '../utils/index.js'
import { nanoid, perfLog, perfMark, resolveContent, writeTemp } from '../utils/index.js'
export type TagsColorsItem = readonly [
string, // normal color
@ -35,19 +35,14 @@ export const PRESET: TagsColorsItem[] = [
const cache: Record<number, string> = {}
export async function prepareArticleTagColors(app: App, localeOptions: PlumeThemeLocaleOptions): Promise<void> {
const start = performance.now()
perfMark('prepare:tag-colors')
const blog = isPlainObject(localeOptions.blog) ? localeOptions.blog : {}
const { js, css } = genCode(app, blog.tagsTheme ?? 'colored')
await writeTemp(app, 'internal/articleTagColors.css', css)
await writeTemp(app, 'internal/articleTagColors.js', js)
if (app.env.isDebug) {
logger.info(
`Generate article tag colors: ${(performance.now() - start).toFixed(2)}ms`,
)
}
perfLog('prepare:tag-colors', app.env.isDebug)
}
export function genCode(app: App, theme: 'colored' | 'brand' | 'gray'): { js: string, css: string } {

View File

@ -11,7 +11,7 @@ import { removeLeadingSlash } from '@vuepress/helper'
import { createFilter } from 'create-filter'
import dayjs from 'dayjs'
import { resolveNotesOptions } from '../config/index.js'
import { logger, normalizePath, resolveContent, writeTemp } from '../utils/index.js'
import { normalizePath, perfLog, perfMark, resolveContent, writeTemp } from '../utils/index.js'
import { isEncryptPage } from './prepareEncrypt.js'
const HEADING_RE = /<h(\d)[^>]*>.*?<\/h\1>/gi
@ -32,7 +32,7 @@ export async function preparedBlogData(
return
}
const start = performance.now()
perfMark('prepare:blog-data')
const blog = localeOptions.blog || {}
const notesList = resolveNotesOptions(localeOptions)
@ -100,6 +100,5 @@ export async function preparedBlogData(
const content = resolveContent(app, { name: 'blogPostData', content: blogData })
await writeTemp(app, 'internal/blogData.js', content)
if (app.env.isDebug)
logger.info(`prepare blog data time spent: ${(performance.now() - start).toFixed(2)}ms`)
perfLog('prepare:blog-data', app.env.isDebug)
}

View File

@ -3,7 +3,7 @@ import type { Page } from 'vuepress/core'
import type { EncryptOptions, PlumeThemePageData } from '../../shared/index.js'
import { isNumber, isString, random, toArray } from '@pengzhanbo/utils'
import { genSaltSync, hashSync } from 'bcrypt-ts'
import { createFsCache, type FsCache, hash, logger, resolveContent, writeTemp } from '../utils/index.js'
import { createFsCache, type FsCache, hash, perfLog, perfMark, resolveContent, writeTemp } from '../utils/index.js'
export type EncryptConfig = readonly [
boolean, // global
@ -19,7 +19,7 @@ let contentHash = ''
let fsCache: FsCache<[string, EncryptConfig]> | null = null
export async function prepareEncrypt(app: App, encrypt?: EncryptOptions) {
const start = performance.now()
perfMark('prepare:encrypt')
if (!fsCache && app.env.isDev) {
fsCache = createFsCache(app, 'encrypt')
@ -40,9 +40,7 @@ export async function prepareEncrypt(app: App, encrypt?: EncryptOptions) {
fsCache?.write([currentHash, resolvedEncrypt])
if (app.env.isDebug) {
logger.info(`Generate encrypt: ${(performance.now() - start).toFixed(2)}ms`)
}
perfLog('prepare:encrypt', app.env.isDebug)
}
const salt = () => genSaltSync(random(8, 16))

View File

@ -5,7 +5,7 @@ import { isArray, uniq } from '@pengzhanbo/utils'
import { entries, isLinkAbsolute, isLinkHttp, isPlainObject } from '@vuepress/helper'
import { isPackageExists } from 'local-pkg'
import { fs } from 'vuepress/utils'
import { createFsCache, type FsCache, interopDefault, logger, nanoid, resolveContent, writeTemp } from '../utils/index.js'
import { createFsCache, type FsCache, interopDefault, logger, nanoid, perfLog, perfMark, resolveContent, writeTemp } from '../utils/index.js'
interface IconData {
className: string
@ -37,7 +37,7 @@ function isIconify(icon: any): icon is string {
}
export async function prepareIcons(app: App, localeOptions: PlumeThemeLocaleOptions) {
const start = performance.now()
perfMark('prepare:icons:total')
if (!isInstalled) {
await writeTemp(app, JS_FILENAME, resolveContent(app, { name: 'icons', content: '{}' }))
return
@ -47,6 +47,7 @@ export async function prepareIcons(app: App, localeOptions: PlumeThemeLocaleOpti
await fsCache.read()
}
perfMark('prepare:pages:icons')
const iconList: string[] = []
app.pages.forEach(page => iconList.push(...getIconsWithPage(page)))
iconList.push(...getIconWithThemeConfig(localeOptions))
@ -64,11 +65,9 @@ export async function prepareIcons(app: App, localeOptions: PlumeThemeLocaleOpti
collectMap[collect].push(name)
})
if (app.env.isDebug) {
logger.info(`Generate icons with pages and theme config: ${(performance.now() - start).toFixed(2)}ms`)
}
perfLog('prepare:pages:icons', app.env.isDebug)
const collectStart = performance.now()
perfMark('prepare:icons:imports')
if (!locate) {
const mod = await interopDefault(import('@iconify/json'))
@ -83,9 +82,7 @@ export async function prepareIcons(app: App, localeOptions: PlumeThemeLocaleOpti
logger.warn(`[iconify] Unknown icons: ${unknownList.join(', ')}`)
}
if (app.env.isDebug) {
logger.info(`Generate icons with iconify collect: ${(performance.now() - collectStart).toFixed(2)}ms`)
}
perfLog('prepare:icons:imports', app.env.isDebug)
let cssCode = ''
const map: Record<string, string> = {}
@ -104,9 +101,8 @@ export async function prepareIcons(app: App, localeOptions: PlumeThemeLocaleOpti
])
fsCache?.write(cache)
if (app.env.isDebug) {
logger.info(`Generate icons total time: ${(performance.now() - start).toFixed(2)}ms`)
}
perfLog('prepare:icons:total', app.env.isDebug)
}
function getIconsWithPage(page: Page): string[] {

View File

@ -13,10 +13,10 @@ import {
isPlainObject,
removeLeadingSlash,
} from '@vuepress/helper'
import { logger, normalizeLink, resolveContent, writeTemp } from '../utils/index.js'
import { normalizeLink, perfLog, perfMark, resolveContent, writeTemp } from '../utils/index.js'
export async function prepareSidebar(app: App, localeOptions: PlumeThemeLocaleOptions) {
const start = performance.now()
perfMark('prepare:sidebar')
const sidebar = getAllSidebar(localeOptions)
const { resolved, autoHome } = getSidebarData(app, sidebar)
@ -24,9 +24,7 @@ export async function prepareSidebar(app: App, localeOptions: PlumeThemeLocaleOp
sidebar.__home__ = autoHome as any
await writeTemp(app, 'internal/sidebar.js', resolveContent(app, { name: 'sidebar', content: sidebar }))
if (app.env.isDebug) {
logger.info(`Generate sidebar: ${(performance.now() - start).toFixed(2)}ms`)
}
perfLog('prepare:sidebar', app.env.isDebug)
}
function getSidebarData(

View File

@ -6,7 +6,7 @@ import { type FSWatcher, watch } from 'chokidar'
import { resolveImageSize } from 'vuepress-plugin-md-power'
import { hash } from 'vuepress/utils'
import { resolveThemeData } from '../config/resolveThemeData.js'
import { logger, resolveContent, writeTemp } from '../utils/index.js'
import { perfLog, perfMark, resolveContent, writeTemp } from '../utils/index.js'
let bulletinFileWatcher: FSWatcher | null = null
const bulletinFiles: Record<string, string> = {}
@ -18,7 +18,7 @@ export async function prepareThemeData(
localeOptions: PlumeThemeLocaleOptions,
pluginOptions: PlumeThemePluginOptions,
): Promise<void> {
const start = performance.now()
perfMark('prepare:theme-data')
const resolvedThemeData = resolveThemeData(app, localeOptions)
await resolveProfileImage(app, resolvedThemeData, pluginOptions)
@ -31,9 +31,7 @@ export async function prepareThemeData(
await resolveBulletin(app, resolvedThemeData)
await updateThemeData(app, resolvedThemeData)
if (app.env.isDebug) {
logger.info(`Generate theme data: ${(performance.now() - start).toFixed(2)}ms`)
}
perfLog('prepare:theme-data', app.env.isDebug)
}
async function updateThemeData(app: App, themeData: PlumeThemeData) {

View File

@ -0,0 +1 @@
export const THEME_NAME = 'vuepress-theme-plume'

View File

@ -1,13 +1,9 @@
import { Logger } from '@vuepress/helper'
export const THEME_NAME = 'vuepress-theme-plume'
export const logger = new Logger(THEME_NAME)
export * from './constants.js'
export * from './createFsCache.js'
export * from './deleteAttrs.js'
export * from './hash.js'
export * from './interopDefault.js'
export * from './logger.js'
export * from './omit.js'
export * from './package.js'
export * from './path.js'
export * from './resolveContent.js'

View File

@ -0,0 +1,20 @@
import { Logger } from '@vuepress/helper'
import { colors } from 'vuepress/utils'
import { THEME_NAME } from './constants.js'
export const logger = new Logger(THEME_NAME)
// { mark: startTime }
const perf: Record<string, number> = {}
export function perfMark(mark: string): void {
perf[mark] = performance.now()
}
export function perfLog(mark: string, isDebug = false): void {
const startTime = perf[mark]
if (!startTime || !isDebug)
return
logger.info(`${colors.magenta('[perf spent time]')} ${colors.green(mark)}: ${colors.cyan(`${(performance.now() - startTime).toFixed(2)}ms`)}`)
}

View File

@ -1,4 +1,4 @@
export function deleteAttrs<
export function omit<
T extends Record<string, any> = Record<string, any>,
>(obj: T, ...attrs: (keyof T)[]): Omit<T, keyof T> {
const res = {} as T