Skip to content

Commit 689c107

Browse files
committed
feat: config.performance
1 parent f916bcf commit 689c107

File tree

7 files changed

+95
-12
lines changed

7 files changed

+95
-12
lines changed

flow/component.js

+1
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ declare interface Component {
5050

5151
// private properties
5252
_uid: number;
53+
_name: string; // this only exists in dev mode
5354
_isVue: true;
5455
_self: Component;
5556
_renderProxy: Component;

src/core/config.js

+6
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export type Config = {
77
optionMergeStrategies: { [key: string]: Function };
88
silent: boolean;
99
productionTip: boolean;
10+
performance: boolean;
1011
devtools: boolean;
1112
errorHandler: ?Function;
1213
ignoredElements: Array<string>;
@@ -44,6 +45,11 @@ const config: Config = {
4445
*/
4546
devtools: process.env.NODE_ENV !== 'production',
4647

48+
/**
49+
* Whether to record perf
50+
*/
51+
performance: process.env.NODE_ENV !== 'production',
52+
4753
/**
4854
* Error handler for watcher errors
4955
*/

src/core/instance/init.js

+14-1
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,23 @@
11
/* @flow */
22

3+
import config from '../config'
4+
import { perf } from '../util/perf'
35
import { initProxy } from './proxy'
46
import { initState } from './state'
57
import { initRender } from './render'
68
import { initEvents } from './events'
79
import { initInjections } from './inject'
810
import { initLifecycle, callHook } from './lifecycle'
9-
import { mergeOptions } from '../util/index'
11+
import { mergeOptions, formatComponentName } from '../util/index'
1012

1113
let uid = 0
1214

1315
export function initMixin (Vue: Class<Component>) {
1416
Vue.prototype._init = function (options?: Object) {
17+
if (process.env.NODE_ENV !== 'production' && config.performance && perf) {
18+
perf.mark('init')
19+
}
20+
1521
const vm: Component = this
1622
// a uid
1723
vm._uid = uid++
@@ -45,6 +51,13 @@ export function initMixin (Vue: Class<Component>) {
4551
initState(vm)
4652
initInjections(vm)
4753
callHook(vm, 'created')
54+
55+
if (process.env.NODE_ENV !== 'production' && config.performance && perf) {
56+
vm._name = formatComponentName(vm, false)
57+
perf.mark('init end')
58+
perf.measure(`${vm._name} init`, 'init', 'init end')
59+
}
60+
4861
if (vm.$options.el) {
4962
vm.$mount(vm.$options.el)
5063
}

src/core/instance/lifecycle.js

+35-4
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,22 @@
11
/* @flow */
22

3+
import config from '../config'
4+
import { perf } from '../util/perf'
35
import Watcher from '../observer/watcher'
46
import { resetRefs } from '../vdom/modules/ref'
57
import { createEmptyVNode } from '../vdom/vnode'
68
import { observerState } from '../observer/index'
79
import { updateComponentListeners } from './events'
810
import { resolveSlots } from './render-helpers/resolve-slots'
9-
import { warn, validateProp, remove, noop, emptyObject, handleError } from '../util/index'
11+
12+
import {
13+
warn,
14+
noop,
15+
remove,
16+
handleError,
17+
emptyObject,
18+
validateProp
19+
} from '../util/index'
1020

1121
export let activeInstance: any = null
1222

@@ -149,10 +159,31 @@ export function mountComponent (
149159
}
150160
}
151161
callHook(vm, 'beforeMount')
152-
vm._watcher = new Watcher(vm, function updateComponent () {
153-
vm._update(vm._render(), hydrating)
154-
}, noop)
162+
163+
let updateComponent
164+
if (process.env.NODE_ENV !== 'production' && config.performance && perf) {
165+
updateComponent = () => {
166+
const name = vm._name
167+
const startTag = `start ${name}`
168+
const endTag = `end ${name}`
169+
perf.mark(startTag)
170+
const vnode = vm._render()
171+
perf.mark(endTag)
172+
perf.measure(`${name} render`, startTag, endTag)
173+
perf.mark(startTag)
174+
vm._update(vnode, hydrating)
175+
perf.mark(endTag)
176+
perf.measure(`${name} patch`, startTag, endTag)
177+
}
178+
} else {
179+
updateComponent = () => {
180+
vm._update(vm._render(), hydrating)
181+
}
182+
}
183+
184+
vm._watcher = new Watcher(vm, updateComponent, noop)
155185
hydrating = false
186+
156187
// manually mounted instance, call mounted on self
157188
// mounted is called for render-created child components in its inserted hook
158189
if (vm.$vnode == null) {

src/core/util/debug.js

+17-6
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ let formatComponentName
66

77
if (process.env.NODE_ENV !== 'production') {
88
const hasConsole = typeof console !== 'undefined'
9+
const classifyRE = /(?:^|[-_/])(\w)/g
10+
const classify = str => str
11+
.replace(classifyRE, c => c.toUpperCase())
12+
.replace(/-/g, '')
913

1014
warn = (msg, vm) => {
1115
if (hasConsole && (!config.silent)) {
@@ -15,21 +19,28 @@ if (process.env.NODE_ENV !== 'production') {
1519
}
1620
}
1721

18-
formatComponentName = vm => {
22+
formatComponentName = (vm, includeFile) => {
1923
if (vm.$root === vm) {
20-
return 'root instance'
24+
return '<Root>'
2125
}
22-
const name = vm._isVue
26+
let name = vm._isVue
2327
? vm.$options.name || vm.$options._componentTag
2428
: vm.name
29+
30+
const file = vm._isVue && vm.$options.__file
31+
if (!name && file) {
32+
const match = file.match(/([^/\\]+)\.vue$/)
33+
name = match && match[1]
34+
}
35+
2536
return (
26-
(name ? `component <${name}>` : `anonymous component`) +
27-
(vm._isVue && vm.$options.__file ? ` at ${vm.$options.__file}` : '')
37+
(name ? `<${classify(name)}>` : `<Anonymous>`) +
38+
(file && includeFile !== false ? file : '')
2839
)
2940
}
3041

3142
const formatLocation = str => {
32-
if (str === 'anonymous component') {
43+
if (str === `<Anonymous>`) {
3344
str += ` - use the "name" option for better debugging messages.`
3445
}
3546
return `\n(found in ${str})`

src/core/util/perf.js

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { inBrowser } from './env'
2+
3+
export let perf
4+
5+
if (process.env.NODE_ENV !== 'production') {
6+
perf = inBrowser && window.performance
7+
if (perf && (!perf.mark || !perf.measure)) {
8+
perf = undefined
9+
}
10+
}

src/entries/web-runtime-with-compiler.js

+12-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
/* @flow */
22

33
import Vue from './web-runtime'
4-
import { warn, cached } from 'core/util/index'
4+
import config from 'core/config'
5+
import { perf } from 'core/util/perf'
56
import { query } from 'web/util/index'
7+
import { warn, cached } from 'core/util/index'
68
import { shouldDecodeNewlines } from 'web/util/compat'
79
import { compileToFunctions } from 'web/compiler/index'
810

@@ -54,13 +56,22 @@ Vue.prototype.$mount = function (
5456
template = getOuterHTML(el)
5557
}
5658
if (template) {
59+
if (process.env.NODE_ENV !== 'production' && config.performance && perf) {
60+
perf.mark('compile')
61+
}
62+
5763
const { render, staticRenderFns } = compileToFunctions(template, {
5864
warn: msg => warn(msg, this),
5965
shouldDecodeNewlines,
6066
delimiters: options.delimiters
6167
}, this)
6268
options.render = render
6369
options.staticRenderFns = staticRenderFns
70+
71+
if (process.env.NODE_ENV !== 'production' && config.performance && perf) {
72+
perf.mark('compile end')
73+
perf.measure(`${this._name} compile`, 'compile', 'compile end')
74+
}
6475
}
6576
}
6677
return mount.call(this, el, hydrating)

0 commit comments

Comments
 (0)