/vue-codemod

Vue.js codemod scripts

Primary LanguageTypeScriptMIT LicenseMIT

vue-codemod

⚠️Attention: This repo is forked from https://github.com/vuejs/vue-codemod.

vue-codemod is a Vue 2 to Vue 3 migration tool, which can directly upgrade most of the Vue 2 syntax to Vue 3 syntax. With vue-codemod transformation and a small amount of manual modification, users can complete the smooth migration from Vue 2 to Vue 3.

中文

Transformation Rates

equ

Manually Upgraded: Number of patterns require manually upgrade

Auto Upgraded: Number of patterns upgraded by vue-codemod

No. Project Manually Upgraded Auto Upgraded Transformation Rates
1 vue2-element-touzi-admin 8 63 88.73%
2 vue-web-os 19 19 50.00%
3 amKnow 10 30 75.00%
4 vue-template 61 28 31.46%
5 coreui-free-vue-admin-template 4 63 94.03%
6 vue-weixin 1 54 98.19%
7 vue-WeChat 9 35 79.55%
8 vue2-management-platform 2 11 84.62%
9 vue-netease-music 18 37 67.27%
10 Mall-Vue 2 26 92.86%
11 vue-demo-kugou 4 13 76.47%
12 codemod-demo 0 24 100%

Getting Started

Installation

npm/yarn install is recommended. Users can also try beta version from GitHub

Install from npm/yarn

npm install @originjs/vue-codemod -g
// or
yarn global add @originjs/vue-codemod

Install form GitHub

  1. Clone from dev
git clone https://github.com/originjs/vue-codemod
  1. Install Dependencies
cd vue-codemod

npm install
// or
yarn install
  1. Install vue-codemod Globally
npm run build
npm install . -g
// or
yarn run build
yarn global add .

Usage

vue-codemod consists of different migration rules. Those rules are defined in transformation/index.ts and vue-transformation/index.ts.

vue-codemod <path> -t/-a [transformation params][...additional options]
  1. <path> indicates the path of execution, which can be files and folders
  2. -a means executing all rules.
  3. -t means executing one specific rule (Conflicts with -a). When -t is used, parameter is required.

Execute All Rules

vue-codemod src -a

src indicates the path of execution. -a means executing all rules.

Execute Specific Rule

vue-codemod src -t new-global-api

src indicates the path of execution. -t new-global-api means only executing the rule of new-global-api .

Here is the detailed rule list.

Output Format

vue-codemod src -a -f log

The -f option is used to specify the output format. The optional parameters are table, detail,log. If no parameters are specified, the default is table.

table : output the executed rules as a table

detail : list transformed files for each rule

log : output a report in the form of log file

Here is a sample output of -f table:

╔═══════════════════════════════╤═══════╗
║ Rule Names                    │ Count ║
╟───────────────────────────────┼───────╢
║ new-component-api             │   1   ║
║ new-global-api                │   1   ║
║ vue-router-v4                 │   1   ║
║ vuex-v4                       │   1   ║
║ new-directive-api             │   1   ║
║ remove-vue-set-and-delete     │   2   ║
║ rename-lifecycle              │   2   ║
║ add-emit-declarations         │   1   ║
║ tree-shaking                  │   1   ║
║ slot-attribute                │   1   ║
║ slot-default                  │   1   ║
║ slot-scope-attribute          │   1   ║
║ v-for-template-key            │   2   ║
║ v-else-if-key                 │   3   ║
║ transition-group-root         │   1   ║
║ v-for-v-if-precedence-changed │   1   ║
║ remove-listeners              │   1   ║
║ remove-v-on-native            │   1   ║
╚═══════════════════════════════╧═══════╝

Manual Migration Guide

During the operation of vue-codemod, the patterns that need to be manually upgraded will be identified and printed to the console as an object (will create a log file if -f log is declared). For more details, please refer to Manual Migration Guide.

Here is the example:

The list that you need to migrate your codes mannually:
index: 1
{
  path: 'src/main.js',
  position: '[33,0]',
  name: 'remove Vue(global api)',
  suggest: "The rule of thumb is any APIs that globally mutate Vue's behavior are now moved to the app instance.",
  website: 'https://v3-migration.vuejs.org/breaking-changes/global-api.html#a-new-global-api-createapp'
}

Help

vue-codemod --help

Output:

vue-codemod --help
Usage: vue-codemod [file pattern]

Options:
  -t, --transformation        Name or path of the transformation module [string]
  -p, --params                Custom params to the transformation
  -a, --runAllTransformation  run all transformation module            [boolean]
  -f, --reportFormatter       Specify an output report formatter
                                                    [string] [default: "detail"]
  -h, --help                  Show help                                [boolean]
  -v, --version               Show version number                      [boolean]

Examples:
  vue-codemod ./src -a                  Run all rules to convert all
                                            relevant files in the ./src folder
  vue-codemod                           Run slot-attribute rule to convert
  ./src/components/HelloWorld.vue -t        HelloWorld.vue
  slot-attribute

Migrating from Vue 2 to Vue 3

  1. Run the -a command: vue-codemod <path> -a
  2. Manually migrate some cases which vue-codemod doesn't cover based on Manual Migration Guide.
  3. Make sure to use @vue/compat to build
  4. Serve the app in development mode, fix the runtime deprecation warnings

Note: even though most of the migration process can be automated, please be aware there might still be subtle differences between Vue 3 and Vue 2 runtime, and the codemods may have uncovered edge cases. Please double check before deploying your Vue 3 app into production.

Typical Migration Case

We forked vue2-element-touzi-admin, and try to migrate it from Vue 2 to Vue 3 with vue-codemod, we have recorded every step of the operation, if you are interested, please see Typical Migration Case

Rule List

Rule Names Descriptions or links
new-component-api https://v3-migration.vuejs.org/breaking-changes/global-api.html#a-new-global-api-createapp
vue-class-component-v8 vuejs/vue-class-component#406
new-global-api https://v3-migration.vuejs.org/breaking-changes/global-api.html#a-new-global-api-createapp
vue-router-v4 https://next.router.vuejs.org/guide/migration/index.html#new-router-becomes-createrouter
https://next.router.vuejs.org/guide/migration/index.html#new-history-option-to-replace-mode
https://next.router.vuejs.org/guide/migration/index.html#replaced-onready-with-isready
vuex-v4 new Store (...) => createStore (...)
define-component Vue.extend (...) => defineComponent (...)
new-vue-to-create-app https://v3-migration.vuejs.org/breaking-changes/global-api.html#a-new-global-api-createapp
scoped-slots-to-slots https://v3-migration.vuejs.org/breaking-changes/slots-unification.html#overview
new-directive-api https://v3-migration.vuejs.org/breaking-changes/custom-directives.html#overview
remove-vue-set-and-delete https://v3-migration.vuejs.org/breaking-changes/#removed-apis
rename-lifecycle https://v3-migration.vuejs.org/breaking-changes/#other-minor-changes
add-emit-declaration https://v3-migration.vuejs.org/breaking-changes/emits-option.html
tree-shaking https://v3-migration.vuejs.org/breaking-changes/global-api-treeshaking.html
v-model https://v3-migration.vuejs.org/breaking-changes/v-model.html#overview
render-to-resolveComponent https://v3-migration.vuejs.org/breaking-changes/render-function-api.html#registered-component
remove-contextual-h-from-render https://v3-migration.vuejs.org/breaking-changes/render-function-api.html#render-function-argument
remove-production-tip https://v3-migration.vuejs.org/breaking-changes/global-api.html#a-new-global-api-createapp
remove-trivial-root createApp ({ render: () => h (App) }) => createApp (App)
vue-as-namespace-import import Vue from "vue" => import * as Vue from "vue"
slot-attribute https://v2.vuejs.org/v2/guide/components-slots.html#Deprecated-Syntax
slot-default If component tag did not contain a <slot> element, any content provided between its opening and closing tag would be discarded.
slot-scope-attribute https://v2.vuejs.org/v2/guide/components-slots.html#Scoped-Slots
v-for-template-key https://v3-migration.vuejs.org/breaking-changes/key-attribute.html#with-template-v-for
v-else-if-key https://v3-migration.vuejs.org/breaking-changes/key-attribute.html#on-conditional-branches
transition-group-root https://v3-migration.vuejs.org/breaking-changes/transition-group.html#overview
v-bind-order-sensitive https://v3-migration.vuejs.org/breaking-changes/v-bind.html#overview
v-for-v-if-precedence-changed https://v3-migration.vuejs.org/breaking-changes/v-if-v-for.html#overview
remove-listeners https://v3-migration.vuejs.org/breaking-changes/listeners-removed.html#overview
v-bind-sync https://v3-migration.vuejs.org/breaking-changes/v-model.html#overview
remove-v-on-native https://v3-migration.vuejs.org/breaking-changes/v-on-native-modifier-removed.html#overview
router-link-event-tag https://next.router.vuejs.org/guide/migration/index.html#removal-of-event-and-tag-props-in-router-link
router-link-exact https://next.router.vuejs.org/guide/migration/index.html#removal-of-the-exact-prop-in-router-link
router-view-keep-alive-transition https://next.router.vuejs.org/guide/migration/index.html#router-view-keep-alive-and-transition

Post Transformation

  • Running transformations will generally ruin the formatting of your files. A recommended way to solve that problem is by using Prettier or eslint --fix.
  • Even after running prettier its possible to have unnecessary new lines added/removed. This can be solved by ignoring white spaces while staging the changes in git.
git diff --ignore-blank-lines | git apply --cached