Skip to content

Commit 2231ec1

Browse files
authored
fix: try to detect global mixins adding meta info (#467)
* feat: try to detect global mixins adding meta info * fix: add find polyfill for ie * fix: only detect global mixins when Vue.devtools: true
1 parent 35b7099 commit 2231ec1

File tree

3 files changed

+52
-10
lines changed

3 files changed

+52
-10
lines changed

src/shared/mixin.js

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { triggerUpdate } from '../client/update'
22
import { isUndefined, isFunction } from '../utils/is-type'
3+
import { find } from '../utils/array'
34
import { ensuredPush } from '../utils/ensure'
45
import { rootConfigKey } from './constants'
56
import { hasMetaInfo } from './meta-helpers'
@@ -18,12 +19,13 @@ export default function createMixin (Vue, options) {
1819
const rootKey = '$root'
1920
const $root = this[rootKey]
2021
const $options = this.$options
22+
const devtoolsEnabled = Vue.config.devtools
2123

2224
Object.defineProperty(this, '_hasMetaInfo', {
2325
configurable: true,
2426
get () {
2527
// Show deprecation warning once when devtools enabled
26-
if (Vue.config.devtools && !$root[rootConfigKey].deprecationWarningShown) {
28+
if (devtoolsEnabled && !$root[rootConfigKey].deprecationWarningShown) {
2729
warn('VueMeta DeprecationWarning: _hasMetaInfo has been deprecated and will be removed in a future version. Please use hasMetaInfo(vm) instead')
2830
$root[rootConfigKey].deprecationWarningShown = true
2931
}
@@ -41,6 +43,17 @@ export default function createMixin (Vue, options) {
4143
if (!$root[rootConfigKey]) {
4244
$root[rootConfigKey] = { appId }
4345
appId++
46+
47+
if (devtoolsEnabled && $root.$options[options.keyName]) {
48+
// use nextTick so the children should be added to $root
49+
this.$nextTick(() => {
50+
// find the first child that lists fnOptions
51+
const child = find($root.$children, c => c.$vnode && c.$vnode.fnOptions)
52+
if (child && child.$vnode.fnOptions[options.keyName]) {
53+
warn(`VueMeta has detected a possible global mixin which adds a ${options.keyName} property to all Vue components on the page. This could cause severe performance issues. If possible, use $meta().addApp to add meta information instead`)
54+
}
55+
})
56+
}
4457
}
4558

4659
// to speed up updates we keep track of branches which have a component with vue-meta info defined
@@ -83,14 +96,18 @@ export default function createMixin (Vue, options) {
8396
$root[rootConfigKey].initialized = this.$isServer
8497

8598
if (!$root[rootConfigKey].initialized) {
86-
ensuredPush($options, 'beforeMount', function () {
87-
const $root = this[rootKey]
88-
// if this Vue-app was server rendered, set the appId to 'ssr'
89-
// only one SSR app per page is supported
90-
if ($root.$el && $root.$el.nodeType === 1 && $root.$el.hasAttribute('data-server-rendered')) {
91-
$root[rootConfigKey].appId = options.ssrAppId
92-
}
93-
})
99+
if (!$root[rootConfigKey].initializedSsr) {
100+
$root[rootConfigKey].initializedSsr = true
101+
102+
ensuredPush($options, 'beforeMount', function () {
103+
const $root = this
104+
// if this Vue-app was server rendered, set the appId to 'ssr'
105+
// only one SSR app per page is supported
106+
if ($root.$el && $root.$el.nodeType === 1 && $root.$el.hasAttribute('data-server-rendered')) {
107+
$root[rootConfigKey].appId = options.ssrAppId
108+
}
109+
})
110+
}
94111

95112
// we use the mounted hook here as on page load
96113
ensuredPush($options, 'mounted', function () {
@@ -155,6 +172,7 @@ export default function createMixin (Vue, options) {
155172
if (!this.$parent || !hasMetaInfo(this)) {
156173
return
157174
}
175+
delete this._hasMetaInfo
158176

159177
this.$nextTick(() => {
160178
if (!options.waitOnDestroyed || !this.$el || !this.$el.offsetParent) {

src/utils/array.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,19 @@
1111
// which means the polyfills are removed for other build formats
1212
const polyfill = process.env.NODE_ENV === 'test'
1313

14+
export function find (array, predicate, thisArg) {
15+
if (polyfill && !Array.prototype.find) {
16+
// idx needs to be a Number, for..in returns string
17+
for (let idx = 0; idx < array.length; idx++) {
18+
if (predicate.call(thisArg, array[idx], idx, array)) {
19+
return array[idx]
20+
}
21+
}
22+
return
23+
}
24+
return array.find(predicate, thisArg)
25+
}
26+
1427
export function findIndex (array, predicate, thisArg) {
1528
if (polyfill && !Array.prototype.findIndex) {
1629
// idx needs to be a Number, for..in returns string

test/unit/utils.test.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/**
22
* @jest-environment node
33
*/
4-
import { findIndex, includes, toArray } from '../../src/utils/array'
4+
import { find, findIndex, includes, toArray } from '../../src/utils/array'
55
import { ensureIsArray } from '../../src/utils/ensure'
66
import { hasGlobalWindowFn } from '../../src/utils/window'
77

@@ -29,6 +29,17 @@ describe('shared', () => {
2929
})
3030

3131
/* eslint-disable no-extend-native */
32+
test('find polyfill', () => {
33+
const _find = Array.prototype.find
34+
Array.prototype.find = false
35+
36+
const arr = [1, 2, 3]
37+
expect(find(arr, (v, i) => i === 0)).toBe(1)
38+
expect(find(arr, (v, i) => i === 3)).toBe(undefined)
39+
40+
Array.prototype.find = _find
41+
})
42+
3243
test('findIndex polyfill', () => {
3344
const _findIndex = Array.prototype.findIndex
3445
Array.prototype.findIndex = false

0 commit comments

Comments
 (0)