-
-
Notifications
You must be signed in to change notification settings - Fork 101
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(runtime-vapor): implement app.config.performance (#230)
* feat(runtime-capor): add app.config.performance * refactor: move formatComponentName to component.ts * refactor: update import in warning.ts * fix * refactor * fix order --------- Co-authored-by: 三咲智子 Kevin Deng <[email protected]>
- Loading branch information
1 parent
ad3d8fa
commit 3ac951b
Showing
7 changed files
with
275 additions
and
43 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
/* eslint-disable no-restricted-globals */ | ||
import type { App } from './apiCreateVaporApp' | ||
import type { ComponentInternalInstance } from './component' | ||
|
||
interface AppRecord { | ||
id: number | ||
app: App | ||
version: string | ||
types: Record<string, string | Symbol> | ||
} | ||
|
||
enum DevtoolsHooks { | ||
APP_INIT = 'app:init', | ||
APP_UNMOUNT = 'app:unmount', | ||
COMPONENT_UPDATED = 'component:updated', | ||
COMPONENT_ADDED = 'component:added', | ||
COMPONENT_REMOVED = 'component:removed', | ||
COMPONENT_EMIT = 'component:emit', | ||
PERFORMANCE_START = 'perf:start', | ||
PERFORMANCE_END = 'perf:end', | ||
} | ||
|
||
export interface DevtoolsHook { | ||
enabled?: boolean | ||
emit: (event: string, ...payload: any[]) => void | ||
on: (event: string, handler: Function) => void | ||
once: (event: string, handler: Function) => void | ||
off: (event: string, handler: Function) => void | ||
appRecords: AppRecord[] | ||
/** | ||
* Added at https://github.com/vuejs/devtools/commit/f2ad51eea789006ab66942e5a27c0f0986a257f9 | ||
* Returns whether the arg was buffered or not | ||
*/ | ||
cleanupBuffer?: (matchArg: unknown) => boolean | ||
} | ||
|
||
export let devtools: DevtoolsHook | ||
|
||
let buffer: { event: string; args: any[] }[] = [] | ||
|
||
let devtoolsNotInstalled = false | ||
|
||
function emit(event: string, ...args: any[]) { | ||
if (devtools) { | ||
devtools.emit(event, ...args) | ||
} else if (!devtoolsNotInstalled) { | ||
buffer.push({ event, args }) | ||
} | ||
} | ||
|
||
export function setDevtoolsHook(hook: DevtoolsHook, target: any) { | ||
devtools = hook | ||
if (devtools) { | ||
devtools.enabled = true | ||
buffer.forEach(({ event, args }) => devtools.emit(event, ...args)) | ||
buffer = [] | ||
} else if ( | ||
// handle late devtools injection - only do this if we are in an actual | ||
// browser environment to avoid the timer handle stalling test runner exit | ||
// (#4815) | ||
typeof window !== 'undefined' && | ||
// some envs mock window but not fully | ||
window.HTMLElement && | ||
// also exclude jsdom | ||
// eslint-disable-next-line no-restricted-syntax | ||
!window.navigator?.userAgent?.includes('jsdom') | ||
) { | ||
const replay = (target.__VUE_DEVTOOLS_HOOK_REPLAY__ = | ||
target.__VUE_DEVTOOLS_HOOK_REPLAY__ || []) | ||
replay.push((newHook: DevtoolsHook) => { | ||
setDevtoolsHook(newHook, target) | ||
}) | ||
// clear buffer after 3s - the user probably doesn't have devtools installed | ||
// at all, and keeping the buffer will cause memory leaks (#4738) | ||
setTimeout(() => { | ||
if (!devtools) { | ||
target.__VUE_DEVTOOLS_HOOK_REPLAY__ = null | ||
devtoolsNotInstalled = true | ||
buffer = [] | ||
} | ||
}, 3000) | ||
} else { | ||
// non-browser env, assume not installed | ||
devtoolsNotInstalled = true | ||
buffer = [] | ||
} | ||
} | ||
|
||
export function devtoolsInitApp(app: App, version: string) { | ||
emit(DevtoolsHooks.APP_INIT, app, version, {}) | ||
} | ||
|
||
export function devtoolsUnmountApp(app: App) { | ||
emit(DevtoolsHooks.APP_UNMOUNT, app) | ||
} | ||
|
||
export const devtoolsComponentAdded = /*#__PURE__*/ createDevtoolsComponentHook( | ||
DevtoolsHooks.COMPONENT_ADDED, | ||
) | ||
|
||
export const devtoolsComponentUpdated = | ||
/*#__PURE__*/ createDevtoolsComponentHook(DevtoolsHooks.COMPONENT_UPDATED) | ||
|
||
const _devtoolsComponentRemoved = /*#__PURE__*/ createDevtoolsComponentHook( | ||
DevtoolsHooks.COMPONENT_REMOVED, | ||
) | ||
|
||
export const devtoolsComponentRemoved = ( | ||
component: ComponentInternalInstance, | ||
) => { | ||
if ( | ||
devtools && | ||
typeof devtools.cleanupBuffer === 'function' && | ||
// remove the component if it wasn't buffered | ||
!devtools.cleanupBuffer(component) | ||
) { | ||
_devtoolsComponentRemoved(component) | ||
} | ||
} | ||
|
||
/*! #__NO_SIDE_EFFECTS__ */ | ||
function createDevtoolsComponentHook(hook: DevtoolsHooks) { | ||
return (component: ComponentInternalInstance) => { | ||
emit( | ||
hook, | ||
component.appContext.app, | ||
component.uid, | ||
component.parent ? component.parent.uid : undefined, | ||
component, | ||
) | ||
} | ||
} | ||
|
||
export const devtoolsPerfStart = /*#__PURE__*/ createDevtoolsPerformanceHook( | ||
DevtoolsHooks.PERFORMANCE_START, | ||
) | ||
|
||
export const devtoolsPerfEnd = /*#__PURE__*/ createDevtoolsPerformanceHook( | ||
DevtoolsHooks.PERFORMANCE_END, | ||
) | ||
|
||
function createDevtoolsPerformanceHook(hook: DevtoolsHooks) { | ||
return (component: ComponentInternalInstance, type: string, time: number) => { | ||
emit(hook, component.appContext.app, component.uid, component, type, time) | ||
} | ||
} | ||
|
||
export function devtoolsComponentEmit( | ||
component: ComponentInternalInstance, | ||
event: string, | ||
params: any[], | ||
) { | ||
emit( | ||
DevtoolsHooks.COMPONENT_EMIT, | ||
component.appContext.app, | ||
component, | ||
event, | ||
params, | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
/* eslint-disable no-restricted-globals */ | ||
import { | ||
type ComponentInternalInstance, | ||
formatComponentName, | ||
} from './component' | ||
import { devtoolsPerfEnd, devtoolsPerfStart } from './devtools' | ||
|
||
let supported: boolean | ||
let perf: Performance | ||
|
||
export function startMeasure( | ||
instance: ComponentInternalInstance, | ||
type: string, | ||
) { | ||
if (instance.appContext.config.performance && isSupported()) { | ||
perf.mark(`vue-${type}-${instance.uid}`) | ||
} | ||
|
||
if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) { | ||
devtoolsPerfStart(instance, type, isSupported() ? perf.now() : Date.now()) | ||
} | ||
} | ||
|
||
export function endMeasure(instance: ComponentInternalInstance, type: string) { | ||
if (instance.appContext.config.performance && isSupported()) { | ||
const startTag = `vue-${type}-${instance.uid}` | ||
const endTag = startTag + `:end` | ||
perf.mark(endTag) | ||
perf.measure( | ||
`<${formatComponentName(instance, instance.component)}> ${type}`, | ||
startTag, | ||
endTag, | ||
) | ||
perf.clearMarks(startTag) | ||
perf.clearMarks(endTag) | ||
} | ||
|
||
if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) { | ||
devtoolsPerfEnd(instance, type, isSupported() ? perf.now() : Date.now()) | ||
} | ||
} | ||
|
||
function isSupported() { | ||
if (supported !== undefined) { | ||
return supported | ||
} | ||
if (typeof window !== 'undefined' && window.performance) { | ||
supported = true | ||
perf = window.performance | ||
} else { | ||
supported = false | ||
} | ||
return supported | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters