0
# Migration Utilities
1
2
Helper functions and utilities for managing the migration process, checking compatibility modes, and integrating with Vue 3 features during the transition from Vue 2 to Vue 3.
3
4
## Capabilities
5
6
### compatUtils Object
7
8
Collection of utility functions for managing compatibility features and migration process.
9
10
```javascript { .api }
11
declare const compatUtils: {
12
warnDeprecation: (key: DeprecationTypes, instance, ...args) => void;
13
isCompatEnabled: (key: DeprecationTypes, instance, enableForBuiltIn?) => boolean;
14
checkCompatEnabled: (key: DeprecationTypes, instance) => boolean;
15
softAssertCompatEnabled: (key: DeprecationTypes, instance) => boolean;
16
createCompatVue: (createApp, wrappedCreateApp) => CompatVue;
17
};
18
```
19
20
### Compatibility Checking
21
22
#### isCompatEnabled Function
23
24
Checks whether a specific compatibility feature is enabled for a component instance.
25
26
```javascript { .api }
27
/**
28
* Check if a compatibility feature is enabled
29
* @param key - Deprecation type to check
30
* @param instance - Component instance (null for global)
31
* @param enableForBuiltIn - Enable for built-in components
32
* @returns True if the feature is enabled
33
*/
34
isCompatEnabled(key: DeprecationTypes, instance: Component | null, enableForBuiltIn?: boolean): boolean;
35
```
36
37
**Usage Example:**
38
39
```javascript
40
import { compatUtils, DeprecationTypes } from "vue";
41
42
// Check if global mount compatibility is enabled
43
if (compatUtils.isCompatEnabled(DeprecationTypes.GLOBAL_MOUNT, null)) {
44
// Use Vue 2 mounting syntax
45
new Vue(options).$mount('#app');
46
} else {
47
// Use Vue 3 mounting syntax
48
createApp(options).mount('#app');
49
}
50
51
// Check in component context
52
export default {
53
mounted() {
54
if (compatUtils.isCompatEnabled(DeprecationTypes.INSTANCE_LISTENERS, this)) {
55
// Access $listeners
56
console.log(this.$listeners);
57
}
58
}
59
};
60
```
61
62
#### checkCompatEnabled Function
63
64
Checks compatibility feature and throws error if disabled.
65
66
```javascript { .api }
67
/**
68
* Check compatibility feature and throw error if disabled
69
* @param key - Deprecation type to check
70
* @param instance - Component instance
71
* @returns True if enabled, throws error if disabled
72
*/
73
checkCompatEnabled(key: DeprecationTypes, instance: Component | null): boolean;
74
```
75
76
#### softAssertCompatEnabled Function
77
78
Soft assertion for compatibility features with warnings.
79
80
```javascript { .api }
81
/**
82
* Soft assertion for compatibility features
83
* @param key - Deprecation type to check
84
* @param instance - Component instance
85
* @returns True if enabled, logs warning if disabled
86
*/
87
softAssertCompatEnabled(key: DeprecationTypes, instance: Component | null): boolean;
88
```
89
90
### Warning System
91
92
#### warnDeprecation Function
93
94
Emit deprecation warnings for Vue 2 features being used.
95
96
```javascript { .api }
97
/**
98
* Emit deprecation warning for Vue 2 features
99
* @param key - Deprecation type
100
* @param instance - Component instance
101
* @param args - Additional warning arguments
102
*/
103
warnDeprecation(key: DeprecationTypes, instance: Component | null, ...args: any[]): void;
104
```
105
106
**Usage Example:**
107
108
```javascript
109
import { compatUtils, DeprecationTypes } from "vue";
110
111
// Custom component using deprecated feature
112
export default {
113
methods: {
114
useDeprecatedFeature() {
115
// Warn about deprecated usage
116
compatUtils.warnDeprecation(
117
DeprecationTypes.INSTANCE_SET,
118
this,
119
'Using $set is deprecated. Use reactive assignment instead.'
120
);
121
122
// Still allow the deprecated functionality
123
this.$set(this.data, 'newProp', 'value');
124
}
125
}
126
};
127
```
128
129
### Constructor Creation
130
131
#### createCompatVue Function
132
133
Creates a Vue 2-compatible constructor from Vue 3 createApp functions.
134
135
```javascript { .api }
136
/**
137
* Create Vue 2-compatible constructor
138
* @param createApp - Vue 3 createApp function
139
* @param wrappedCreateApp - Wrapped createApp with compatibility
140
* @returns CompatVue constructor
141
*/
142
createCompatVue(createApp: Function, wrappedCreateApp: Function): CompatVue;
143
```
144
145
## Migration Patterns
146
147
### Feature Detection Pattern
148
149
Check compatibility before using features:
150
151
```javascript
152
import { compatUtils, DeprecationTypes } from "vue";
153
154
export default {
155
mounted() {
156
// Pattern: Check before using deprecated feature
157
if (compatUtils.isCompatEnabled(DeprecationTypes.INSTANCE_EVENT_EMITTER, this)) {
158
// Use Vue 2 event system
159
this.$on('custom-event', this.handleEvent);
160
} else {
161
// Use Vue 3 event system (emits)
162
this.$emit('custom-event', data);
163
}
164
},
165
166
methods: {
167
conditionalReactivity(obj, key, value) {
168
// Pattern: Conditional reactivity
169
if (compatUtils.isCompatEnabled(DeprecationTypes.GLOBAL_SET, null)) {
170
Vue.set(obj, key, value);
171
} else {
172
// Vue 3 reactivity is automatic
173
obj[key] = value;
174
}
175
}
176
}
177
};
178
```
179
180
### Migration Helper Mixins
181
182
Create reusable migration helpers:
183
184
```javascript
185
// migration-mixin.js
186
import { compatUtils, DeprecationTypes } from "vue";
187
188
export const migrationMixin = {
189
methods: {
190
safeSet(target, key, value) {
191
if (compatUtils.isCompatEnabled(DeprecationTypes.INSTANCE_SET, this)) {
192
this.$set(target, key, value);
193
} else {
194
target[key] = value;
195
}
196
},
197
198
safeDelete(target, key) {
199
if (compatUtils.isCompatEnabled(DeprecationTypes.INSTANCE_DELETE, this)) {
200
this.$delete(target, key);
201
} else {
202
delete target[key];
203
}
204
},
205
206
isVue2Mode() {
207
return compatUtils.isCompatEnabled(DeprecationTypes.GLOBAL_MOUNT, null);
208
}
209
}
210
};
211
212
// Use in components
213
export default {
214
mixins: [migrationMixin],
215
216
methods: {
217
updateData() {
218
// Use migration-safe methods
219
this.safeSet(this.user, 'newField', 'value');
220
}
221
}
222
};
223
```
224
225
### Progressive Migration Strategy
226
227
Gradually migrate components from Vue 2 to Vue 3 mode:
228
229
```javascript
230
// Step 1: Start with Vue 2 compatibility
231
export default {
232
name: 'ComponentV1',
233
compatConfig: {
234
MODE: 2, // Full Vue 2 compatibility
235
},
236
data() {
237
return { count: 0 };
238
},
239
methods: {
240
increment() {
241
this.count++;
242
}
243
}
244
};
245
246
// Step 2: Migrate to hybrid mode
247
export default {
248
name: 'ComponentV2',
249
compatConfig: {
250
MODE: 3, // Vue 3 mode
251
INSTANCE_EVENT_EMITTER: true, // Keep some Vue 2 features
252
OPTIONS_DATA_FN: true
253
},
254
data() {
255
return { count: 0 };
256
},
257
setup() {
258
// Start using Composition API alongside Options API
259
const newFeature = ref('value');
260
return { newFeature };
261
}
262
};
263
264
// Step 3: Full Vue 3 migration
265
export default {
266
name: 'ComponentV3',
267
compatConfig: {
268
MODE: 3 // Pure Vue 3 mode
269
},
270
setup() {
271
// Full Composition API
272
const count = ref(0);
273
const increment = () => count.value++;
274
return { count, increment };
275
}
276
};
277
```
278
279
### Build Tool Integration
280
281
Integrate compatibility checking with build tools:
282
283
```javascript
284
// webpack plugin for migration analysis
285
class VueCompatAnalyzer {
286
apply(compiler) {
287
compiler.hooks.compilation.tap('VueCompatAnalyzer', (compilation) => {
288
// Analyze Vue compat usage during build
289
compilation.hooks.buildModule.tap('VueCompatAnalyzer', (module) => {
290
if (module.resource?.endsWith('.vue')) {
291
// Check for compatibility patterns
292
this.analyzeComponent(module);
293
}
294
});
295
});
296
}
297
298
analyzeComponent(module) {
299
// Custom analysis logic
300
const source = module._source?.source();
301
if (source?.includes('compatConfig')) {
302
console.log(`Component ${module.resource} uses compatibility config`);
303
}
304
}
305
}
306
```
307
308
## Utility Types
309
310
### DeprecationTypes
311
312
All available deprecation types for compatibility checking:
313
314
```javascript { .api }
315
enum DeprecationTypes {
316
// Global API
317
GLOBAL_MOUNT = 'GLOBAL_MOUNT',
318
GLOBAL_EXTEND = 'GLOBAL_EXTEND',
319
GLOBAL_PROTOTYPE = 'GLOBAL_PROTOTYPE',
320
GLOBAL_SET = 'GLOBAL_SET',
321
GLOBAL_DELETE = 'GLOBAL_DELETE',
322
GLOBAL_OBSERVABLE = 'GLOBAL_OBSERVABLE',
323
324
// Instance API
325
INSTANCE_SET = 'INSTANCE_SET',
326
INSTANCE_DELETE = 'INSTANCE_DELETE',
327
INSTANCE_DESTROY = 'INSTANCE_DESTROY',
328
INSTANCE_EVENT_EMITTER = 'INSTANCE_EVENT_EMITTER',
329
INSTANCE_LISTENERS = 'INSTANCE_LISTENERS',
330
INSTANCE_CHILDREN = 'INSTANCE_CHILDREN',
331
332
// Component Options
333
OPTIONS_DATA_FN = 'OPTIONS_DATA_FN',
334
OPTIONS_BEFORE_DESTROY = 'OPTIONS_BEFORE_DESTROY',
335
OPTIONS_DESTROYED = 'OPTIONS_DESTROYED',
336
337
// And many more...
338
}
339
```
340
341
### Component Reference
342
343
```javascript { .api }
344
type Component = ComponentOptions | ComponentPublicInstance;
345
```
346
347
## Best Practices
348
349
### 1. Feature Detection Over Mode Detection
350
351
```javascript
352
// Good: Check specific features
353
if (compatUtils.isCompatEnabled(DeprecationTypes.INSTANCE_LISTENERS, this)) {
354
// Use $listeners
355
}
356
357
// Avoid: Mode-based detection
358
if (this.$compatMode === 2) {
359
// Less maintainable
360
}
361
```
362
363
### 2. Graceful Degradation
364
365
```javascript
366
methods: {
367
safeEventHandler() {
368
// Gracefully handle different Vue versions
369
try {
370
if (compatUtils.isCompatEnabled(DeprecationTypes.INSTANCE_EVENT_EMITTER, this)) {
371
this.$on('event', handler);
372
} else {
373
// Vue 3 approach
374
this.$emit('event', data);
375
}
376
} catch (error) {
377
console.warn('Event handling fallback:', error);
378
}
379
}
380
}
381
```
382
383
### 3. Migration Tracking
384
385
```javascript
386
// Track migration progress
387
const migrationStatus = {
388
component: 'MyComponent',
389
compatFeatures: [
390
'INSTANCE_LISTENERS',
391
'GLOBAL_EXTEND'
392
],
393
migrationPlan: [
394
'Remove $listeners usage',
395
'Replace Vue.extend with defineComponent'
396
]
397
};
398
```