Skip to content

Commit cbcfe11

Browse files
JanAkryum
authored andcommitted
fix: Introduce client version observer compatible with Meteor 1.8.1 (#369)
* Updated vue2-hot from vuejs * added support for new `_clientVersions` object introduced in autoupdate for Meteor 1.8.1 ( meteor/meteor@13308cf )
1 parent 4dd9c48 commit cbcfe11

File tree

2 files changed

+64
-13
lines changed

2 files changed

+64
-13
lines changed

packages/vue-component-dev-client/client/dev-client.js

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -83,14 +83,20 @@ function checkNewVersionDocument (doc) {
8383
}
8484
}
8585

86-
const ClientVersions = Autoupdate._ClientVersions
87-
if (ClientVersions) {
88-
ClientVersions.find().observe({
89-
added: checkNewVersionDocument,
90-
changed: checkNewVersionDocument,
91-
})
86+
if (Autoupdate._clientVersions) {
87+
// logic for autoupdate since Meteor 1.8.1
88+
Autoupdate._clientVersions.watch(checkNewVersionDocument)
9289
} else {
93-
console.warn('%cHMR', tagStyle, 'ClientVersions collection is not available, the app may full reload.')
90+
// logic for autoupdate before Meteor 1.8.1
91+
const ClientVersions = Autoupdate._ClientVersions
92+
if (ClientVersions) {
93+
ClientVersions.find().observe({
94+
added: checkNewVersionDocument,
95+
changed: checkNewVersionDocument,
96+
})
97+
} else {
98+
console.warn('%cHMR', tagStyle, 'ClientVersions collection is not available, the app may full reload.')
99+
}
94100
}
95101

96102
Meteor.startup(function () {

packages/vue-component-dev-client/client/vue2-hot.js

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
let Vue // late bind
22
let version
3-
const map = (window.__VUE_HOT_MAP__ = Object.create(null))
3+
const map = Object.create(null)
4+
if (typeof window !== 'undefined') {
5+
window.__VUE_HOT_MAP__ = map
6+
}
47
let installed = false
8+
let isBrowserify = false
59
let initHookName = 'beforeCreate'
610

711
exports.install = (vue, browserify) => {
@@ -10,6 +14,7 @@ exports.install = (vue, browserify) => {
1014

1115
Vue = vue.__esModule ? vue.default : vue
1216
version = Vue.version.split('.').map(Number)
17+
isBrowserify = browserify
1318

1419
// compat with < 2.0.0-alpha.7
1520
if (Vue.config._lifecycleHooks.indexOf('init') > -1) {
@@ -20,8 +25,9 @@ exports.install = (vue, browserify) => {
2025
if (!exports.compatible) {
2126
console.warn(
2227
'[HMR] You are using a version of vue-hot-reload-api that is ' +
23-
'only compatible with Vue.js core ^2.0.0.'
28+
'only compatible with Vue.js core ^2.0.0.'
2429
)
30+
return
2531
}
2632
}
2733

@@ -34,6 +40,8 @@ exports.install = (vue, browserify) => {
3440
*/
3541

3642
exports.createRecord = (id, options) => {
43+
if (map[id]) return
44+
3745
let Ctor = null
3846
if (typeof options === 'function') {
3947
Ctor = options
@@ -43,10 +51,20 @@ exports.createRecord = (id, options) => {
4351
map[id] = {
4452
Ctor,
4553
options,
46-
instances: [],
54+
instances: []
4755
}
4856
}
4957

58+
/**
59+
* Check if module is recorded
60+
*
61+
* @param {String} id
62+
*/
63+
64+
exports.isRecorded = (id) => {
65+
return typeof map[id] !== 'undefined'
66+
}
67+
5068
/**
5169
* Make a Component options object hot.
5270
*
@@ -137,7 +155,7 @@ exports.rerender = tryWrap((id, options) => {
137155
instance.$options.render = options.render
138156
instance.$options.staticRenderFns = options.staticRenderFns
139157
// reset static trees
140-
// pre 2.5, all static trees are cahced together on the instance
158+
// pre 2.5, all static trees are cached together on the instance
141159
if (instance._staticTrees) {
142160
instance._staticTrees = []
143161
}
@@ -149,10 +167,16 @@ exports.rerender = tryWrap((id, options) => {
149167
if (Array.isArray(instance.$options.cached)) {
150168
instance.$options.cached = []
151169
}
170+
152171
// post 2.5.4: v-once trees are cached on instance._staticTrees.
153172
// Pure static trees are cached on the staticRenderFns array
154173
// (both already reset above)
174+
175+
// 2.6: temporarily mark rendered scoped slots as unstable so that
176+
// child components can be forced to update
177+
const restore = patchScopedSlots(instance)
155178
instance.$forceUpdate()
179+
instance.$nextTick(restore)
156180
})
157181
} else {
158182
// functional or no instance created yet
@@ -201,7 +225,7 @@ exports.reload = tryWrap((id, options) => {
201225
// preserve pre 2.2 behavior for global mixin handling
202226
record.Ctor.extendOptions = options
203227
}
204-
const newCtor = (record.Ctor.super || record.Ctor).extend(options)
228+
const newCtor = record.Ctor.super.extend(options)
205229
record.Ctor.options = newCtor.options
206230
record.Ctor.cid = newCtor.cid
207231
record.Ctor.prototype = newCtor.prototype
@@ -220,7 +244,28 @@ exports.reload = tryWrap((id, options) => {
220244
console.warn(
221245
'Root or manually mounted instance modified. Full reload required.'
222246
)
223-
window.location.reload()
224247
}
225248
})
226249
})
250+
251+
// 2.6 optimizes template-compiled scoped slots and skips updates if child
252+
// only uses scoped slots. We need to patch the scoped slots resolving helper
253+
// to temporarily mark all scoped slots as unstable in order to force child
254+
// updates.
255+
function patchScopedSlots (instance) {
256+
if (!instance._u) return
257+
// https://github.com/vuejs/vue/blob/dev/src/core/instance/render-helpers/resolve-scoped-slots.js
258+
const original = instance._u
259+
instance._u = slots => {
260+
try {
261+
// 2.6.4 ~ 2.6.6
262+
return original(slots, true)
263+
} catch (e) {
264+
// 2.5 / >= 2.6.7
265+
return original(slots, null, true)
266+
}
267+
}
268+
return () => {
269+
instance._u = original
270+
}
271+
}

0 commit comments

Comments
 (0)