diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..b16a639
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,27 @@
+name: CI
+
+on:
+  push:
+    branches: [ master ]
+  pull_request:
+    branches: [ master ]
+
+jobs:
+  build:
+
+    runs-on: ubuntu-latest
+
+    strategy:
+      matrix:
+        node-version: [10.x, 12.x, 14.x, 15.x]
+
+    steps:
+    - uses: actions/checkout@v2
+    - name: Use Node.js ${{ matrix.node-version }}
+      uses: actions/setup-node@v2
+      with:
+        node-version: ${{ matrix.node-version }}
+    - name: Run test
+      run: |
+        npm install
+        npm test
diff --git a/generator/codemods/global-api/__testfixtures__/basic.output.js b/generator/codemods/global-api/__testfixtures__/basic.output.js
index 684d042..b0788dd 100644
--- a/generator/codemods/global-api/__testfixtures__/basic.output.js
+++ b/generator/codemods/global-api/__testfixtures__/basic.output.js
@@ -1,4 +1,5 @@
 import { createApp } from 'vue';
 import App from './App.vue';
 
-createApp(App).mount('#app');
+const app = createApp(App);
+app.mount('#app');
diff --git a/generator/codemods/global-api/__testfixtures__/custom-root-prop.output.js b/generator/codemods/global-api/__testfixtures__/custom-root-prop.output.js
index b9ade05..59e84ff 100644
--- a/generator/codemods/global-api/__testfixtures__/custom-root-prop.output.js
+++ b/generator/codemods/global-api/__testfixtures__/custom-root-prop.output.js
@@ -1,7 +1,9 @@
 import { createApp, h } from 'vue';
 import App from './App.vue';
 
-createApp({
+const app = createApp({
   myOption: 'hello!',
   render: () => h(App),
-}).mount('#app');
+});
+
+app.mount('#app');
diff --git a/generator/codemods/global-api/__testfixtures__/next-tick.input.js b/generator/codemods/global-api/__testfixtures__/next-tick.input.js
new file mode 100644
index 0000000..1d22568
--- /dev/null
+++ b/generator/codemods/global-api/__testfixtures__/next-tick.input.js
@@ -0,0 +1,5 @@
+import Vue from 'vue';
+
+Vue.nextTick(() => {
+    console.log('foo');
+})
diff --git a/generator/codemods/global-api/__testfixtures__/next-tick.output.js b/generator/codemods/global-api/__testfixtures__/next-tick.output.js
new file mode 100644
index 0000000..e69e67e
--- /dev/null
+++ b/generator/codemods/global-api/__testfixtures__/next-tick.output.js
@@ -0,0 +1,5 @@
+import { nextTick } from 'vue';
+
+nextTick(() => {
+    console.log('foo');
+})
diff --git a/generator/codemods/global-api/__testfixtures__/vue-router.output.js b/generator/codemods/global-api/__testfixtures__/vue-router.output.js
index 82ac74e..138eb97 100644
--- a/generator/codemods/global-api/__testfixtures__/vue-router.output.js
+++ b/generator/codemods/global-api/__testfixtures__/vue-router.output.js
@@ -2,4 +2,5 @@ import { createApp } from 'vue';
 import App from './App.vue';
 import router from './router';
 
-createApp(App).use(router).mount('#app');
+const app = createApp(App).use(router);
+app.mount('#app');
diff --git a/generator/codemods/global-api/__testfixtures__/vuex.output.js b/generator/codemods/global-api/__testfixtures__/vuex.output.js
index f1a5d84..958566a 100644
--- a/generator/codemods/global-api/__testfixtures__/vuex.output.js
+++ b/generator/codemods/global-api/__testfixtures__/vuex.output.js
@@ -3,6 +3,7 @@ import App from './App.vue';
 import store from './store';
 import anotherStore from './another-store';
 
-createApp(App).use(store).mount('#app');
-
-createApp(App).use(anotherStore).mount('#app');
+const app = createApp({}).use(h => h(App));
+app.mount('#app');
+const app = createApp({}).use(h => h(App));
+app.mount('#app');
diff --git a/generator/codemods/global-api/__tests__/global-api-test.js b/generator/codemods/global-api/__tests__/global-api-test.js
index ab05aaa..f63f9c9 100644
--- a/generator/codemods/global-api/__tests__/global-api-test.js
+++ b/generator/codemods/global-api/__tests__/global-api-test.js
@@ -8,3 +8,4 @@ defineTest(__dirname, 'index', null, 'custom-root-prop')
 defineTest(__dirname, 'index', null, 'vue-router')
 defineTest(__dirname, 'index', null, 'vuex')
 defineTest(__dirname, 'index', null, 'vue-use')
+defineTest(__dirname, 'index', null, 'next-tick')
diff --git a/generator/codemods/global-api/create-app-mount.js b/generator/codemods/global-api/create-app-mount.js
index 6cba44d..b878986 100644
--- a/generator/codemods/global-api/create-app-mount.js
+++ b/generator/codemods/global-api/create-app-mount.js
@@ -7,13 +7,21 @@ module.exports = function createAppMount(context) {
   const { j, root } = context
 
   // new Vue(...).$mount()
-  const mountCalls = root.find(j.CallExpression, n => {
-    return (
-      n.callee.type === 'MemberExpression' &&
-      n.callee.property.name === '$mount' &&
-      n.callee.object.type === 'NewExpression' &&
-      n.callee.object.callee.name === 'Vue'
-    )
+  const mountCalls = root.find(j.ExpressionStatement, {
+    expression: {
+      type: 'CallExpression',
+      callee: {
+        type: 'MemberExpression',
+        object: {
+          type: 'NewExpression',
+          callee: {
+            type: 'Identifier',
+            name: 'Vue'
+          }
+        },
+        property: { type: 'Identifier', name: '$mount' }
+      }
+    }
   })
 
   if (!mountCalls.length) {
@@ -23,16 +31,26 @@ module.exports = function createAppMount(context) {
   const addImport = require('../utils/add-import')
   addImport(context, { imported: 'createApp' }, 'vue')
 
-  mountCalls.replaceWith(({ node }) => {
-    let rootProps = node.callee.object.arguments[0]
-    const el = node.arguments[0]
+  const rootProps = mountCalls.at(0).get().node.expression.callee.object
+    .arguments
+  mountCalls.insertBefore(
+    j.variableDeclaration('const', [
+      j.variableDeclarator(
+        j.identifier('app'),
+        j.callExpression(j.identifier('createApp'), rootProps)
+      )
+    ])
+  )
 
-    return j.callExpression(
-      j.memberExpression(
-        j.callExpression(j.identifier('createApp'), [rootProps]),
-        j.identifier('mount')
-      ),
-      [el]
+  const args = mountCalls.at(0).get().node.expression.arguments
+  mountCalls.insertBefore(
+    j.expressionStatement(
+      j.callExpression(
+        j.memberExpression(j.identifier('app'), j.identifier('mount'), false),
+        args
+      )
     )
-  })
+  )
+
+  mountCalls.remove()
 }
diff --git a/generator/codemods/global-api/global-filter.js b/generator/codemods/global-api/global-filter.js
new file mode 100644
index 0000000..714043a
--- /dev/null
+++ b/generator/codemods/global-api/global-filter.js
@@ -0,0 +1,75 @@
+/**
+ * @param {Object} context
+ * @param {import('jscodeshift').JSCodeshift} context.j
+ * @param {ReturnType<import('jscodeshift').Core>} context.root
+ */
+module.exports = function createAppMount(context) {
+  const { j, root } = context
+
+  // find const appName = createApp(...)
+  const appDeclare = root.find(j.VariableDeclarator, {
+    id: { type: 'Identifier' },
+    init: {
+      type: 'CallExpression',
+      callee: {
+        type: 'Identifier',
+        name: 'createApp'
+      }
+    }
+  })
+  if (!appDeclare.length) {
+    return
+  }
+  const appName = appDeclare.at(0).get().node.id.name
+
+  // Vue.filter('filterName', function(value) {}) =>
+  // app.config.globalProperties.$filters = { filterName(value) {} }
+  const filters = root.find(j.ExpressionStatement, {
+    expression: {
+      type: 'CallExpression',
+      callee: {
+        type: 'MemberExpression',
+        object: { type: 'Identifier', name: 'Vue' },
+        property: { type: 'Identifier', name: 'filter' }
+      }
+    }
+  })
+  if (!filters.length) {
+    return
+  }
+
+  const methods = []
+  for (let i = 0; i < filters.length; i++) {
+    const filter = filters.at(i)
+    const args = filter.get().node.expression.arguments
+
+    methods.push(
+      j.objectMethod(
+        'method',
+        j.identifier(args[0].value),
+        args[1].params,
+        args[1].body
+      )
+    )
+  }
+
+  filters
+    .at(0)
+    .insertBefore(
+      j.expressionStatement(
+        j.assignmentExpression(
+          '=',
+          j.memberExpression(
+            j.identifier(appName),
+            j.identifier('config.globalProperties.$filters'),
+            false
+          ),
+          j.objectExpression(methods)
+        )
+      )
+    )
+
+  for (let i = 0; i < filters.length; i++) {
+    filters.at(i).remove()
+  }
+}
diff --git a/generator/codemods/global-api/index.js b/generator/codemods/global-api/index.js
index 6ab3557..5891f9a 100644
--- a/generator/codemods/global-api/index.js
+++ b/generator/codemods/global-api/index.js
@@ -11,6 +11,10 @@ module.exports = function(fileInfo, api) {
   require('./remove-production-tip')(context)
   require('./remove-vue-use')(context)
   require('./remove-contextual-h')(context)
+  require('./next-tick')(context)
+  require('./observable')(context)
+  require('./version')(context)
+  require('./global-filter')(context)
 
   // remove extraneous imports
   const removeExtraneousImport = require('../utils/remove-extraneous-import')
diff --git a/generator/codemods/global-api/next-tick.js b/generator/codemods/global-api/next-tick.js
new file mode 100644
index 0000000..f713005
--- /dev/null
+++ b/generator/codemods/global-api/next-tick.js
@@ -0,0 +1,30 @@
+/**
+ * @param {Object} context
+ * @param {import('jscodeshift').JSCodeshift} context.j
+ * @param {ReturnType<import('jscodeshift').Core>} context.root
+ */
+module.exports = function createAppMount(context) {
+  const { j, root } = context
+
+  // Vue.nextTick(() => {})
+  const nextTickCalls = root.find(j.CallExpression, n => {
+    return (
+      n.callee.type === 'MemberExpression' &&
+      n.callee.property.name === 'nextTick' &&
+      n.callee.object.name === 'Vue'
+    )
+  })
+
+  if (!nextTickCalls.length) {
+    return
+  }
+
+  const addImport = require('../utils/add-import')
+  addImport(context, { imported: 'nextTick' }, 'vue')
+
+  nextTickCalls.replaceWith(({ node }) => {
+    const el = node.arguments[0]
+
+    return j.callExpression(j.identifier('nextTick'), [el])
+  })
+}
diff --git a/generator/codemods/global-api/observable.js b/generator/codemods/global-api/observable.js
new file mode 100644
index 0000000..9a01221
--- /dev/null
+++ b/generator/codemods/global-api/observable.js
@@ -0,0 +1,30 @@
+/**
+ * @param {Object} context
+ * @param {import('jscodeshift').JSCodeshift} context.j
+ * @param {ReturnType<import('jscodeshift').Core>} context.root
+ */
+module.exports = function createAppMount(context) {
+  const { j, root } = context
+
+  // Vue.observable(state)
+  const observableCalls = root.find(j.CallExpression, n => {
+    return (
+      n.callee.type === 'MemberExpression' &&
+      n.callee.property.name === 'observable' &&
+      n.callee.object.name === 'Vue'
+    )
+  })
+
+  if (!observableCalls.length) {
+    return
+  }
+
+  const addImport = require('../utils/add-import')
+  addImport(context, { imported: 'reactive' }, 'vue')
+
+  observableCalls.replaceWith(({ node }) => {
+    const el = node.arguments[0]
+
+    return j.callExpression(j.identifier('reactive'), [el])
+  })
+}
diff --git a/generator/codemods/global-api/version.js b/generator/codemods/global-api/version.js
new file mode 100644
index 0000000..fa8e894
--- /dev/null
+++ b/generator/codemods/global-api/version.js
@@ -0,0 +1,29 @@
+/**
+ * @param {Object} context
+ * @param {import('jscodeshift').JSCodeshift} context.j
+ * @param {ReturnType<import('jscodeshift').Core>} context.root
+ */
+module.exports = function createAppMount(context) {
+  const { j, root } = context
+
+  // Vue.version
+  const versionCalls = root.find(j.MemberExpression, n => {
+    return (
+      n.property.name === 'version' &&
+      n.object.name === 'Vue'
+    )
+  })
+
+  if (!versionCalls.length) {
+    return
+  }
+
+  const addImport = require('../utils/add-import')
+  addImport(context, { imported: 'version' }, 'vue')
+
+  versionCalls.replaceWith(({ node }) => {
+    const property = node.property.name
+
+    return j.identifier(property)
+  })
+}
diff --git a/generator/codemods/vue-addition/index.js b/generator/codemods/vue-addition/index.js
new file mode 100644
index 0000000..918fa38
--- /dev/null
+++ b/generator/codemods/vue-addition/index.js
@@ -0,0 +1,28 @@
+module.exports = function(files, filename) {
+  let content = files[filename]
+  content = removeEventNative(content)
+  content = addTransitionFrom(content)
+  files[filename] = content
+}
+
+// template
+// v-on:event.native => v-on:event
+// @event.native => @event
+function removeEventNative(content) {
+  const reg = new RegExp(
+    '(?<=<template>[\\s\\S]*?\\s(?:v-on:|@)\\w+).native(?==[\\s\\S]*?</template>)',
+    'g'
+  )
+  return content.replace(reg, '')
+}
+
+// style
+// .xxx-enter => .xxx-enter-from
+// .xxx-leave => .xxx-leave-from
+function addTransitionFrom(content) {
+  const reg = new RegExp(
+    '(?<=<style[\\s>][\\s\\S]*?\\s\\.[A-Za-z0-9_-]+-)(enter|leave)(?=[,{\\s][\\s\\S]*?</style>)',
+    'g'
+  )
+  return content.replace(reg, '$1-from')
+}
diff --git a/generator/codemods/vue/__testfixtures__/add-emit-declaration.input.js b/generator/codemods/vue/__testfixtures__/add-emit-declaration.input.js
new file mode 100644
index 0000000..4b02f03
--- /dev/null
+++ b/generator/codemods/vue/__testfixtures__/add-emit-declaration.input.js
@@ -0,0 +1,9 @@
+export default {
+    props: ['text'],
+    methods: {
+        input: function(){
+            this.$emit('increment');
+            this.$emit('decrement');
+        }
+    }
+}
diff --git a/generator/codemods/vue/__testfixtures__/add-emit-declaration.output.js b/generator/codemods/vue/__testfixtures__/add-emit-declaration.output.js
new file mode 100644
index 0000000..0426910
--- /dev/null
+++ b/generator/codemods/vue/__testfixtures__/add-emit-declaration.output.js
@@ -0,0 +1,11 @@
+export default {
+    emits: ["increment", "decrement"],
+    props: ['text'],
+
+    methods: {
+        input: function(){
+            this.$emit('increment');
+            this.$emit('decrement');
+        }
+    }
+};
diff --git a/generator/codemods/vue/__testfixtures__/rename-lifecycle.input.js b/generator/codemods/vue/__testfixtures__/rename-lifecycle.input.js
new file mode 100644
index 0000000..cd67429
--- /dev/null
+++ b/generator/codemods/vue/__testfixtures__/rename-lifecycle.input.js
@@ -0,0 +1,8 @@
+export default {
+    destroyed: function () {
+        console.log('foo')
+    },
+    beforeDestroy: function () {
+        console.log('bar')
+    }
+}
diff --git a/generator/codemods/vue/__testfixtures__/rename-lifecycle.output.js b/generator/codemods/vue/__testfixtures__/rename-lifecycle.output.js
new file mode 100644
index 0000000..3f243ec
--- /dev/null
+++ b/generator/codemods/vue/__testfixtures__/rename-lifecycle.output.js
@@ -0,0 +1,8 @@
+export default {
+    unmounted: function () {
+        console.log('foo')
+    },
+    beforeUnmount: function () {
+        console.log('bar')
+    }
+}
diff --git a/generator/codemods/vue/__tests__/vue-test.js b/generator/codemods/vue/__tests__/vue-test.js
new file mode 100644
index 0000000..3e3c669
--- /dev/null
+++ b/generator/codemods/vue/__tests__/vue-test.js
@@ -0,0 +1,6 @@
+jest.autoMockOff()
+
+const { defineTest } = require('jscodeshift/dist/testUtils')
+
+defineTest(__dirname, 'index', null, 'add-emit-declaration')
+defineTest(__dirname, 'index', null, 'rename-lifecycle')
diff --git a/generator/codemods/vue/add-emit-declaration.js b/generator/codemods/vue/add-emit-declaration.js
new file mode 100644
index 0000000..8959092
--- /dev/null
+++ b/generator/codemods/vue/add-emit-declaration.js
@@ -0,0 +1,74 @@
+/**
+ * @param {Object} context
+ * @param {import('jscodeshift').JSCodeshift} context.j
+ * @param {ReturnType<import('jscodeshift').Core>} context.root
+ */
+module.exports = function addEmitDeclaration(context) {
+  const { j, root } = context
+
+  // this.$emit('xxx') => emits: ['xxx']
+  const this$emits = root.find(j.CallExpression, {
+    callee: {
+      type: 'MemberExpression',
+      object: { type: 'ThisExpression' },
+      property: {
+        type: 'Identifier',
+        name: '$emit'
+      }
+    }
+  })
+
+  const emits = []
+  for (let i = 0; i < this$emits.length; i++) {
+    const arg = this$emits.at(i).get().node.arguments[0]
+    if (arg.type === 'StringLiteral') {
+      emits.push(arg.value)
+    }
+  }
+
+  if (emits.length === 0) {
+    return
+  }
+
+  const defaultObject = root
+    .find(j.ExportDefaultDeclaration)
+    .at(0)
+    .find(j.ObjectExpression)
+    .at(0)
+
+  let oldEmits = emits
+  let emitsProperty = defaultObject.find(j.ObjectProperty, {
+    key: {
+      type: 'Identifier',
+      name: 'emits'
+    }
+  })
+  if (emitsProperty.length > 0) {
+    oldEmits = emitsProperty
+      .at(0)
+      .get()
+      .node.value.elements.map(el => el.value)
+
+    let hasChange = false
+    for (const el of emits) {
+      if (!oldEmits.includes(el)) {
+        oldEmits.push(el)
+        hasChange = true
+      }
+    }
+    if (!hasChange) {
+      return
+    }
+    emitsProperty.remove()
+  }
+
+  defaultObject.replaceWith(({ node }) => {
+    node.properties.unshift(
+      j.objectProperty(
+        j.identifier('emits'),
+        j.arrayExpression(oldEmits.map(el => j.stringLiteral(el)))
+      )
+    )
+    return node
+  })
+}
diff --git a/generator/codemods/vue/add-watch-deep.js b/generator/codemods/vue/add-watch-deep.js
new file mode 100644
index 0000000..edbfe4d
--- /dev/null
+++ b/generator/codemods/vue/add-watch-deep.js
@@ -0,0 +1,124 @@
+/**
+ * @param {Object} context
+ * @param {import('jscodeshift').JSCodeshift} context.j
+ * @param {ReturnType<import('jscodeshift').Core>} context.root
+ */
+module.exports = function addEmitDeclaration(context) {
+  const { j, root } = context
+
+  // this.$watch(...) add deep option
+  const this$watches = root.find(j.CallExpression, {
+    callee: {
+      type: 'MemberExpression',
+      object: { type: 'ThisExpression' },
+      property: {
+        type: 'Identifier',
+        name: '$watch'
+      }
+    }
+  })
+
+  for (let i = 0; i < this$watches.length; i++) {
+    const watchFunc = this$watches.at(i)
+    const deepProperty = watchFunc.find(j.ObjectProperty, {
+      key: {
+        type: 'Identifier',
+        name: 'deep'
+      }
+    })
+    if (deepProperty.length > 0) {
+      continue
+    }
+    const args = watchFunc.get().node.arguments
+    if (args.length < 2) {
+      continue
+    }
+    if (args[1].type != 'ObjectExpression') {
+      if (args.length < 3) {
+        watchFunc.replaceWith(nodePath => {
+          nodePath.node.arguments.push(j.objectExpression([]))
+          return nodePath.node
+        })
+      }
+      const target = watchFunc.find(j.ObjectExpression).at(0)
+      target.replaceWith(nodePath => {
+        nodePath.node.properties.push(
+          j.objectProperty(j.identifier('deep'), j.booleanLiteral(true))
+        )
+        return nodePath.node
+      })
+    }
+  }
+
+  // watch: {...} add deep option
+  const watchFuncs = root
+    .find(j.ExportDefaultDeclaration)
+    .at(0)
+    .find(j.ObjectExpression)
+    .at(0)
+    .find(j.ObjectProperty, {
+      key: {
+        type: 'Identifier',
+        name: 'watch'
+      }
+    })
+    .at(0)
+    .find(j.ObjectExpression)
+    .at(0)
+    .find(j.ObjectProperty)
+
+  for (let i = 0; i < watchFuncs.length; i++) {
+    const watchProperty = watchFuncs.at(i)
+    if (!inExportDefaultLevel(watchProperty, 2)) {
+      continue
+    }
+    const deepProperty = watchProperty.find(j.ObjectProperty, {
+      key: {
+        type: 'Identifier',
+        name: 'deep'
+      }
+    })
+    if (deepProperty.length > 0) {
+      continue
+    }
+
+    if (watchProperty.get().node.value.type === 'ObjectExpression') {
+      const target = watchProperty.find(j.ObjectExpression).at(0)
+      target.replaceWith(nodePath => {
+        nodePath.node.properties.push(
+          j.objectProperty(j.identifier('deep'), j.booleanLiteral(true))
+        )
+        return nodePath.node
+      })
+    } else {
+      watchProperty.replaceWith(nodePath => {
+        nodePath.node.value = j.objectExpression([
+          j.objectProperty(j.identifier('handler'), nodePath.node.value),
+          j.objectProperty(j.identifier('deep'), j.booleanLiteral(true))
+        ])
+        return nodePath.node
+      })
+    }
+  }
+}
+
+function getExportDefaultLevel(collection) {
+  let path = collection.get()
+  let level = 0
+  while (path) {
+    if (path.node.type === 'ExportDefaultDeclaration') {
+      return level
+    }
+    path = path.parentPath
+    level++
+  }
+  return -1
+}
+
+function inExportDefaultLevel(collection, level) {
+  const lvl = getExportDefaultLevel(collection)
+  if (level * 3 === lvl) {
+    return true
+  }
+  return false
+}
diff --git a/generator/codemods/vue/index.js b/generator/codemods/vue/index.js
new file mode 100644
index 0000000..b0d67ee
--- /dev/null
+++ b/generator/codemods/vue/index.js
@@ -0,0 +1,14 @@
+/** @type {import('jscodeshift').Transform} */
+module.exports = function(fileInfo, api) {
+  const j = api.jscodeshift
+  const root = j(fileInfo.source)
+  const context = { j, root }
+
+  require('./add-emit-declaration')(context)
+  require('./add-watch-deep')(context)
+  require('./rename-lifecycle')(context)
+
+  return root.toSource({ lineTerminator: '\n' })
+}
+
+module.exports.parser = 'babylon'
diff --git a/generator/codemods/vue/rename-lifecycle.js b/generator/codemods/vue/rename-lifecycle.js
new file mode 100644
index 0000000..48f3673
--- /dev/null
+++ b/generator/codemods/vue/rename-lifecycle.js
@@ -0,0 +1,28 @@
+/** @type {import('jscodeshift').Transform} */
+
+const DEPRECATED_LIFECYCLE = Object.create(null)
+DEPRECATED_LIFECYCLE.destroyed = 'unmounted'
+DEPRECATED_LIFECYCLE.beforeDestroy = 'beforeUnmount'
+
+module.exports = function renameLifecycle(context) {
+  const { j, root } = context
+
+  const renameDeprecatedLifecycle = path => {
+    const name = path.node.key.name
+
+    if (
+      DEPRECATED_LIFECYCLE[name] &&
+      path.parent &&
+      path.parent.parent &&
+      path.parent.parent.value.type === 'ExportDefaultDeclaration'
+    ) {
+      path.value.key.name = DEPRECATED_LIFECYCLE[name]
+    }
+  }
+
+  root.find(j.ObjectProperty).forEach(renameDeprecatedLifecycle)
+  root.find(j.ObjectMethod).forEach(renameDeprecatedLifecycle)
+  root.find(j.ClassProperty).forEach(renameDeprecatedLifecycle)
+
+  return root.toSource({ lineTerminator: '\n' })
+}
diff --git a/generator/index.js b/generator/index.js
index d9f4604..f6d2480 100644
--- a/generator/index.js
+++ b/generator/index.js
@@ -22,6 +22,14 @@ module.exports = (api) => {
   const globalAPITransform = require('./codemods/global-api')
   api.transformScript(api.entryFile, globalAPITransform)
 
+  const vueTransform = require('./codemods/vue')
+  const vueFiles = Object.keys(api.generator.files).filter(el =>
+    el.endsWith('.vue')
+  )
+  for (let i = 0; i < vueFiles.length; i++) {
+    api.transformScript(vueFiles[i], vueTransform)
+  }
+
   if (api.hasPlugin('eslint')) {
     api.extendPackage({
       devDependencies: {
@@ -126,3 +134,15 @@ module.exports = (api) => {
     api.exitLog('Documentation available at https://github.com/vuejs/vue-test-utils-next')
   }
 }
+
+module.exports.hooks = api => {
+  api.postProcessFiles(files => {
+    const vueTransform = require('./codemods/vue-addition')
+    const vueFiles = Object.keys(api.generator.files).filter(el =>
+      el.endsWith('.vue')
+    )
+    for (let i = 0; i < vueFiles.length; i++) {
+      vueTransform(files, vueFiles[i])
+    }
+  })
+}