CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-vue--compat

Vue 3 compatibility build for Vue 2 that provides configurable Vue 2 compatible behavior to facilitate migration from Vue 2 to Vue 3

Pending
Overview
Eval results
Files

migration-helpers.mddocs/

Migration Utilities

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.

Capabilities

compatUtils Object

Collection of utility functions for managing compatibility features and migration process.

declare const compatUtils: {
  warnDeprecation: (key: DeprecationTypes, instance, ...args) => void;
  isCompatEnabled: (key: DeprecationTypes, instance, enableForBuiltIn?) => boolean;
  checkCompatEnabled: (key: DeprecationTypes, instance) => boolean;
  softAssertCompatEnabled: (key: DeprecationTypes, instance) => boolean;
  createCompatVue: (createApp, wrappedCreateApp) => CompatVue;
};

Compatibility Checking

isCompatEnabled Function

Checks whether a specific compatibility feature is enabled for a component instance.

/**
 * Check if a compatibility feature is enabled
 * @param key - Deprecation type to check
 * @param instance - Component instance (null for global)
 * @param enableForBuiltIn - Enable for built-in components
 * @returns True if the feature is enabled
 */
isCompatEnabled(key: DeprecationTypes, instance: Component | null, enableForBuiltIn?: boolean): boolean;

Usage Example:

import { compatUtils, DeprecationTypes } from "vue";

// Check if global mount compatibility is enabled
if (compatUtils.isCompatEnabled(DeprecationTypes.GLOBAL_MOUNT, null)) {
  // Use Vue 2 mounting syntax
  new Vue(options).$mount('#app');
} else {
  // Use Vue 3 mounting syntax
  createApp(options).mount('#app');
}

// Check in component context
export default {
  mounted() {
    if (compatUtils.isCompatEnabled(DeprecationTypes.INSTANCE_LISTENERS, this)) {
      // Access $listeners
      console.log(this.$listeners);
    }
  }
};

checkCompatEnabled Function

Checks compatibility feature and throws error if disabled.

/**
 * Check compatibility feature and throw error if disabled
 * @param key - Deprecation type to check
 * @param instance - Component instance
 * @returns True if enabled, throws error if disabled
 */
checkCompatEnabled(key: DeprecationTypes, instance: Component | null): boolean;

softAssertCompatEnabled Function

Soft assertion for compatibility features with warnings.

/**
 * Soft assertion for compatibility features
 * @param key - Deprecation type to check
 * @param instance - Component instance
 * @returns True if enabled, logs warning if disabled
 */
softAssertCompatEnabled(key: DeprecationTypes, instance: Component | null): boolean;

Warning System

warnDeprecation Function

Emit deprecation warnings for Vue 2 features being used.

/**
 * Emit deprecation warning for Vue 2 features
 * @param key - Deprecation type
 * @param instance - Component instance
 * @param args - Additional warning arguments
 */
warnDeprecation(key: DeprecationTypes, instance: Component | null, ...args: any[]): void;

Usage Example:

import { compatUtils, DeprecationTypes } from "vue";

// Custom component using deprecated feature
export default {
  methods: {
    useDeprecatedFeature() {
      // Warn about deprecated usage
      compatUtils.warnDeprecation(
        DeprecationTypes.INSTANCE_SET, 
        this,
        'Using $set is deprecated. Use reactive assignment instead.'
      );
      
      // Still allow the deprecated functionality
      this.$set(this.data, 'newProp', 'value');
    }
  }
};

Constructor Creation

createCompatVue Function

Creates a Vue 2-compatible constructor from Vue 3 createApp functions.

/**
 * Create Vue 2-compatible constructor
 * @param createApp - Vue 3 createApp function
 * @param wrappedCreateApp - Wrapped createApp with compatibility
 * @returns CompatVue constructor
 */
createCompatVue(createApp: Function, wrappedCreateApp: Function): CompatVue;

Migration Patterns

Feature Detection Pattern

Check compatibility before using features:

import { compatUtils, DeprecationTypes } from "vue";

export default {
  mounted() {
    // Pattern: Check before using deprecated feature
    if (compatUtils.isCompatEnabled(DeprecationTypes.INSTANCE_EVENT_EMITTER, this)) {
      // Use Vue 2 event system
      this.$on('custom-event', this.handleEvent);
    } else {
      // Use Vue 3 event system (emits)
      this.$emit('custom-event', data);
    }
  },
  
  methods: {
    conditionalReactivity(obj, key, value) {
      // Pattern: Conditional reactivity
      if (compatUtils.isCompatEnabled(DeprecationTypes.GLOBAL_SET, null)) {
        Vue.set(obj, key, value);
      } else {
        // Vue 3 reactivity is automatic
        obj[key] = value;
      }
    }
  }
};

Migration Helper Mixins

Create reusable migration helpers:

// migration-mixin.js
import { compatUtils, DeprecationTypes } from "vue";

export const migrationMixin = {
  methods: {
    safeSet(target, key, value) {
      if (compatUtils.isCompatEnabled(DeprecationTypes.INSTANCE_SET, this)) {
        this.$set(target, key, value);
      } else {
        target[key] = value;
      }
    },
    
    safeDelete(target, key) {
      if (compatUtils.isCompatEnabled(DeprecationTypes.INSTANCE_DELETE, this)) {
        this.$delete(target, key);
      } else {
        delete target[key];
      }
    },
    
    isVue2Mode() {
      return compatUtils.isCompatEnabled(DeprecationTypes.GLOBAL_MOUNT, null);
    }
  }
};

// Use in components
export default {
  mixins: [migrationMixin],
  
  methods: {
    updateData() {
      // Use migration-safe methods
      this.safeSet(this.user, 'newField', 'value');
    }
  }
};

Progressive Migration Strategy

Gradually migrate components from Vue 2 to Vue 3 mode:

// Step 1: Start with Vue 2 compatibility
export default {
  name: 'ComponentV1',
  compatConfig: {
    MODE: 2, // Full Vue 2 compatibility
  },
  data() {
    return { count: 0 };
  },
  methods: {
    increment() {
      this.count++;
    }
  }
};

// Step 2: Migrate to hybrid mode
export default {
  name: 'ComponentV2',
  compatConfig: {
    MODE: 3, // Vue 3 mode
    INSTANCE_EVENT_EMITTER: true, // Keep some Vue 2 features
    OPTIONS_DATA_FN: true
  },
  data() {
    return { count: 0 };
  },
  setup() {
    // Start using Composition API alongside Options API
    const newFeature = ref('value');
    return { newFeature };
  }
};

// Step 3: Full Vue 3 migration
export default {
  name: 'ComponentV3',
  compatConfig: {
    MODE: 3 // Pure Vue 3 mode
  },
  setup() {
    // Full Composition API
    const count = ref(0);
    const increment = () => count.value++;
    return { count, increment };
  }
};

Build Tool Integration

Integrate compatibility checking with build tools:

// webpack plugin for migration analysis
class VueCompatAnalyzer {
  apply(compiler) {
    compiler.hooks.compilation.tap('VueCompatAnalyzer', (compilation) => {
      // Analyze Vue compat usage during build
      compilation.hooks.buildModule.tap('VueCompatAnalyzer', (module) => {
        if (module.resource?.endsWith('.vue')) {
          // Check for compatibility patterns
          this.analyzeComponent(module);
        }
      });
    });
  }
  
  analyzeComponent(module) {
    // Custom analysis logic
    const source = module._source?.source();
    if (source?.includes('compatConfig')) {
      console.log(`Component ${module.resource} uses compatibility config`);
    }
  }
}

Utility Types

DeprecationTypes

All available deprecation types for compatibility checking:

enum DeprecationTypes {
  // Global API
  GLOBAL_MOUNT = 'GLOBAL_MOUNT',
  GLOBAL_EXTEND = 'GLOBAL_EXTEND',
  GLOBAL_PROTOTYPE = 'GLOBAL_PROTOTYPE',
  GLOBAL_SET = 'GLOBAL_SET',
  GLOBAL_DELETE = 'GLOBAL_DELETE',
  GLOBAL_OBSERVABLE = 'GLOBAL_OBSERVABLE',
  
  // Instance API
  INSTANCE_SET = 'INSTANCE_SET',
  INSTANCE_DELETE = 'INSTANCE_DELETE',
  INSTANCE_DESTROY = 'INSTANCE_DESTROY',
  INSTANCE_EVENT_EMITTER = 'INSTANCE_EVENT_EMITTER',
  INSTANCE_LISTENERS = 'INSTANCE_LISTENERS',
  INSTANCE_CHILDREN = 'INSTANCE_CHILDREN',
  
  // Component Options
  OPTIONS_DATA_FN = 'OPTIONS_DATA_FN',
  OPTIONS_BEFORE_DESTROY = 'OPTIONS_BEFORE_DESTROY',
  OPTIONS_DESTROYED = 'OPTIONS_DESTROYED',
  
  // And many more...
}

Component Reference

type Component = ComponentOptions | ComponentPublicInstance;

Best Practices

1. Feature Detection Over Mode Detection

// Good: Check specific features
if (compatUtils.isCompatEnabled(DeprecationTypes.INSTANCE_LISTENERS, this)) {
  // Use $listeners
}

// Avoid: Mode-based detection
if (this.$compatMode === 2) {
  // Less maintainable
}

2. Graceful Degradation

methods: {
  safeEventHandler() {
    // Gracefully handle different Vue versions
    try {
      if (compatUtils.isCompatEnabled(DeprecationTypes.INSTANCE_EVENT_EMITTER, this)) {
        this.$on('event', handler);
      } else {
        // Vue 3 approach
        this.$emit('event', data);
      }
    } catch (error) {
      console.warn('Event handling fallback:', error);
    }
  }
}

3. Migration Tracking

// Track migration progress
const migrationStatus = {
  component: 'MyComponent',
  compatFeatures: [
    'INSTANCE_LISTENERS',
    'GLOBAL_EXTEND'
  ],
  migrationPlan: [
    'Remove $listeners usage',
    'Replace Vue.extend with defineComponent'
  ]
};

Install with Tessl CLI

npx tessl i tessl/npm-vue--compat

docs

configuration.md

constructor-api.md

global-api.md

index.md

migration-helpers.md

tile.json