A CLI tool to automatically migrate Vue 2 Class Components to Vue 3 Composition API with <script setup> syntax.
Inspired by the Vue Class Migrator tool.
- ✅ Converts Vue Class Components to Composition API
- ✅ Supports
<script setup>syntax - ✅ Handles props with
@Propdecorator - ✅ Converts class properties to
ref/reactivewith smart detection - ✅ Transforms
@Watchdecorators - ✅ Converts computed properties (getters/setters)
- ✅ Transforms methods and lifecycle hooks
- ✅ Detects and extracts composables (e.g.,
useRouter,useStore) - ✅ Supports Pinia stores
- ✅ Preserves TypeScript types
- ✅ Works with both
.tsand.vuefiles - ✅ Handles complex reactive object assignments
- ✅ Extracts emits from
$emitcalls - ✅ Dry-run mode for safe testing
- ✅ Backup option for original files
# Clone and build the project
git clone <this-repo>
cd vue-composition-migrator
npm install
npm run build
cd /path/to/your/vue2-project
path/to/vue-composition-migrator/dist migrate -d ./src --dry-run# From the vue-composition-migrator directory
cd vue-composition-migrator
npm install
npm run build
# Run on your Vue 2 project
node ./dist/cli.js migrate -d /path/to/your/vue2-project/src --dry-run# Test on a single component to see how it works
vue-composition-migrator check ./src/components/YourComponent.vue
# Or with the direct method
node /path/to/vue-composition-migrator/dist/cli.js check ./src/components/YourComponent.vue# Always start with a check to see how certain files will be migrated
vue-composition-migrator check ./src/components/MyComponent.vue
# When ready, run the actual migration
vue-composition-migrator migrate -d ./src# Only migrate .vue files
vue-composition-migrator migrate -d ./src -p "**/*.vue"
# Only migrate components directory
vue-composition-migrator migrate -d ./src/components
# Migrate a specific pattern
vue-composition-migrator migrate -d ./src -p "**/User*.vue"# Preview how a single file would be migrated
vue-composition-migrator check ./src/components/MyComponent.vue-d, --directory <path>- Directory to migrate (default: current directory)-p, --pattern <glob>- File pattern to match (default:**/*.{vue,ts})
import { Component, Vue, Prop } from 'vue-property-decorator';
@Component
export default class UserCard extends Vue {
@Prop({ required: true }) name!: string;
@Prop({ default: 0 }) age!: number;
private userStore = useUserStore();
count = 0;
user = { name: 'John', email: '[email protected]' };
get displayName() {
return `${this.name} (${this.age})`;
}
mounted() {
console.log('Component mounted');
this.loadUser();
}
async loadUser() {
this.user = await this.userStore.fetchUser();
}
increment() {
this.count++;
}
}<script setup lang="ts">
import { ref, reactive, computed, onMounted } from 'vue'
import { useUserStore } from '@/stores'
const props = defineProps<{
name: string
age?: number
}>()
const userStore = useUserStore()
const count = ref<number>(0)
const user = reactive({ name: 'John', email: '[email protected]' })
const displayName = computed(() => {
return `${props.name} (${props.age})`
})
const loadUser = async () => {
Object.assign(user, await userStore.fetchUser())
}
const increment = () => {
count.value++
}
onMounted(() => {
console.log('Component mounted')
loadUser()
})
</script>- ✅
@Componentdecorator - ✅
@Propdecorator (with types, defaults, required, validators) - ✅
@Watchdecorator (with options like immediate, deep) - ✅ Class properties → smart
ref/reactivedetection:- Primitives, arrays, and nullables →
ref - Objects →
reactive
- Primitives, arrays, and nullables →
- ✅ Computed properties (getters and getter/setter pairs)
- ✅ Methods transformation with proper
thisreference handling - ✅ Lifecycle hooks → Composition API equivalents
- ✅ Emit detection from
$emitcalls →defineEmits - ✅ Composables detection and extraction (including Pinia stores)
- ✅ Complex reactive object assignments →
Object.assign - ✅ Full TypeScript support with type preservation
- ✅ Vue SFC (.vue) files with template and style preservation
- 🚧
@Emitdecorator - 🚧
@Modeland@PropSyncdecorators - 🚧 Vuex
@State,@Getter,@Actiondecorators - 🚧 Mixins support
- 🚧 Provide/Inject pattern
-
"No Vue class component found in file"
- Make sure your component uses the
@Componentdecorator - The tool only migrates Vue Class Components, not Options API components
- Make sure your component uses the
-
Build errors after migration
- Check that all imports are correctly resolved
- Some composables might need to be installed separately
- Reactive object assignments might need manual review
-
Type errors
- The tool preserves TypeScript types, but some might need adjustment
- Check that imported types are still available
-
Runtime errors
- Reactive objects can't be reassigned directly; use
Object.assign - Refs need
.valueaccess in script (but not in template)
- Reactive objects can't be reassigned directly; use
- Test one component at a time with the
checkcommand before bulk migration - Run your test suite after migration to catch any issues
- Commit your code before running the migration
- The tool uses AST manipulation, so it preserves the exact structure of your code
- Complex class inheritance patterns may require manual intervention
- Some edge cases in decorator usage might not be fully supported
- Mixins are not yet supported and need manual migration
# Install dependencies
npm install
# Run tests
npm test
# Build the project
npm run build
# Run in development mode
npm run devMIT