头图

I. Introduction

As we all know, Vite , as a next-generation front-end development and construction tool, is one word: fast. And Vite is already the default build tool for Vue3. Experiments show that after the project is migrated, from nearly 2 minutes in Vue-cli to 5 seconds in Vite (different project sizes and time), the speed is increased by dozens or even hundreds of times.

This article provides the most comprehensive solution on the entire network for the migration of old projects from Vue-cli to Vite. The following takes ant-design-vue-pro as an example to migrate, and the version of ant-design-vue is 1.7.8.

At the same time, the migrated warehouse is provided, welcome Star~

GitHub - Seals-Studio/ant-design-vue-pro-vite

For the migration of the Element-UI project, refer to the article: The most hard-core Element-UI in the entire network migrates from Vue-cli to Vite (2)

Comparison before and after migration (reference)

build tools Server startup time Page first load speed (no cache) Second load speed (with cache) Hot update HMR Pack
Webpack 83s 4.78s 3.35s 4.78s 3mins 37s
Vite 4.72s (0.72s for the second time) 1.71s 1.33s moment 51.45s

2. Delete package.json related dependencies

  1. Remove @vue and babel related

     {
        "@vue/babel-helper-vue-jsx-merge-props": "^1.2.1",
        "@vue/cli-plugin-babel": "^4.5.17",
        "@vue/cli-plugin-eslint": "^4.5.17",
        "@vue/cli-plugin-router": "^4.5.17",
        "@vue/cli-plugin-unit-jest": "^4.5.17",
        "@vue/cli-plugin-vuex": "^4.5.17",
        "@vue/cli-service": "^4.5.17",
        "@vue/eslint-config-standard": "^4.0.0",
        "@vue/test-utils": "^1.3.0",
        "babel-eslint": "^10.1.0",
        "babel-plugin-import": "^1.13.3",
        "babel-plugin-transform-remove-console": "^6.9.4",
    }
  2. Remove loader (webpack plugin) and webpack

     {
        "file-loader": "^6.2.0",
        "less-loader": "^5.0.0",
        "vue-svg-icon-loader": "^2.1.1",
        "git-revision-webpack-plugin": "^3.0.6",
        "webpack-theme-color-replacer": "^1.3.26",
    }
  3. delete babel.conf.js and jsconfig.json
  4. Install the pnpm tool
pnpm is a fast, disk space saving package management tool
 npm i -g pnpm
# 淘宝源
pnpm config set registry https://registry.npm.taobao.org  
pnpm config set disturl https://npm.taobao.org/dist
pnpm config set NVM_NODEJS_ORG_MIRROR http://npm.taobao.org/mirrors/node  
pnpm config set NVM_IOJS_ORG_MIRROR http://npm.taobao.org/mirrors/iojs  
pnpm config set PHANTOMJS_CDNURL https://npm.taobao.org/dist/phantomjs  
pnpm config set ELECTRON_MIRROR http://npm.taobao.org/mirrors/electron/  
pnpm config set SASS_BINARY_SITE http://npm.taobao.org/mirrors/node-sass  
pnpm config set SQLITE3_BINARY_SITE http://npm.taobao.org/mirrors/sqlite3  
pnpm config set PYTHON_MIRROR http://npm.taobao.org/mirrors/python

3. Install the latest version of vite and vite-plugin-vue2

 pnpm add vite vite-plugin-vue2 -D

Fourth, create a new vite.conf.js in the root directory

 import { defineConfig } from 'vite'
// vue2的vite插件
import { createVuePlugin } from 'vite-plugin-vue2'

export default ({ mode }) => {
  return defineConfig({
    plugins: [
      createVuePlugin({
        jsx: true
      })
    ]
  })
})

Five, index.html modification

  • Move public/index.html to the code root directory (same level as package.json)
  • Add the following to the body tag:

     <!-- 指明加载main.js -->
    <script type="module" src="/src/main.js"></script>
  • Replace variables injected by htmlWebpackPlugin plugin

    htmlWebpackPlugin is a webpack plugin, so it can no longer be used, vite provides vite-plugin-html plugin to inject variables into index.html
    1. Install vite-plugin-html

       pnpm add vite-plugin-html -D
    2. Modify vite.config.js, add configuration
     plugins: [
          // ...
          createHtmlPlugin({
            minify: true,
            inject: {
              data: {
                title: 'Ant Design Pro',
                cdn: {
                  css: [],
                  js: [
                        '//cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.min.js',
                        '//cdn.jsdelivr.net/npm/vue-router@3.5.1/dist/vue-router.min.js',
                        '//cdn.jsdelivr.net/npm/vuex@3.1.1/dist/vuex.min.js',
                        '//cdn.jsdelivr.net/npm/axios@0.21.1/dist/axios.min.js'
                  ]
                }
              }
            }
          }),
          // ...
        ]
    1. Modify index.html

      • Modify title

         <title><%= title %></title>
      • Modify css and js to import

         <!-- require cdn assets css -->
            <% for (var i in cdn.css) { %>
            <link rel="stylesheet" href="<%= cdn.css[i] %>" />
            <% } %>
        
            <!-- require cdn assets js -->
            <% for (var i in cdn.js) { %>
            <script type="text/javascript" src="<%= cdn.js[i] %>"></script>
            <% } %>

6. Environment variable replacement

For security reasons, vite can only recognize environment variables starting with VITE_ . The original VUE_ environment variable is not valid, and at the same time, process.env.xxx cannot be used to read environment variables. . Need to modify the vite.conf.js configuration, manually add process.env.xxx environment variable
  • Modify the vite.conf.js configuration and add environment variables

     import { defineConfig, loadEnv } from 'vite'
    
    export default ({ mode }) => {  
      const env = loadEnv(mode, process.cwd())
      return defineConfig({
        define: {
          'process.env': { ...env }
        },
      })
    })
  • Replace all environment variables beginning with VUE_ with VITE_
  • Change all process.env.NODE_ENV to import.meta.env.MODE
  • Change everything that starts with process.env. to import.meta.env.

7. Ant-Design-Vue is introduced on demand

  1. Install the vite-plugin-style-import plugin
 # 注意本插件必须采用1.4.1版本,不能采用最新版2.0.0
pnpm add vite-plugin-style-import@^1.4.1 -D
  1. Add vite.conf.js configuration

     plugins: [
        // ...
        styleImport({
            libs: [
              {
                libraryName: 'ant-design-vue',
                esModule: true,
                resolveStyle: (name) => {
                  return `ant-design-vue/es/${name}/style/index`
                },
              }
            ],
          }),
        // ...
    ]

Eight, Ant-Design-Vue introduces moment problem

The reason is that the bottom layer of antdv adopts: import * as moment from "moment";

Not compatible with ESM writing, refer to github issue: chore: v1 support vite

This article refers to the [] plugin and wrote a vite plugin to modify the introduction of moment at the bottom of antdv and change it to: import moment from moment

  1. Install dependencies

     pnpm add rollup@">=1.20.0 <2.0.0 || >=2.0.0 <3.0.0" -D
    pnpm add @rollup/plugin-replace -D
  2. Modify vite.conf.js configuration
 import path from 'path-browserify'
import fs from 'fs'
import replace from '@rollup/plugin-replace'


// 参考vite-plugin-antdv1-momentjs-resolver插件,修改正则表达式,兼容Windows路径
// https://github.com/carl-jin/vite-plugin-antdv1-momentjs-resolver/blob/main/src/index.js
// 将moment_util.js中import * as moment from moment修改import moment from moment
// 原正则表达式
// const antdvDefaultReg = /ant-design-vue\/[\w-\\\/]*\.js$/
// 修改后正则表达式
// const antdvDefaultReg = /ant-design-vue[\/|\\][\w-\\\/]*\.js$/
const AntdMomentResolver = (reg = /ant-design-vue[\/|\\][\w-\\\/]*\.js$/) => {
  return {
    name: 'vite-plugin-antdv1-momentjs-resolver',
    configResolved(config) {
      //  以来预构建时候替换 esbuild
      config.optimizeDeps.esbuildOptions.plugins = config.optimizeDeps.esbuildOptions.plugins
        ? config.optimizeDeps.esbuildOptions.plugins
        : []
      config.optimizeDeps.esbuildOptions.plugins.push({
        name: 'replace-code',
        setup(build) {
          build.onLoad(
            {
              filter: reg,
            },
            (args) => {
              // 首先获取源代码内容
              let source = fs.readFileSync(args.path, 'utf8')
              if (source.indexOf('import * as moment from')) {
                source = source.replace(/import\s\*\sas\smoment\sfrom/g, 'import moment from')
              }
              return {
                contents: source,
              }
            }
          )
        },
      })

      //  添加打包时的替换 rollup
      config.plugins.push(
        replace({
          values: {
            'import * as moment from': (id) => {
              return 'import moment from'
            },
          },
          include: [reg],
          preventAssignment: true,
        })
      )
    },
  }
}

// 引入插件
export default ({ mode }) => {
    return defineConfig({
    plugins: [
          // ...
          AntdMomentResolver(),
          // ...
    ]
   })
}

9. Add an agent

  1. install path-browserify

     pnpm add path-browserify -D
  2. Add vite.conf.js configuration

     plugin: [],
        // ...
        server: {
          port: 8000,
          //proxy: {
          //  '/api': {
          //    target: 'https://mock.ihx.me/mock/5baf3052f7da7e07e04a5116/antd-pro',
          //    changeOrigin: true,
          //    ws: false,
          //    rewrite: (path) => path.replace(/^\/api/, ''),
          //  }
          //},
        },

Ten, package.json script command modification

Modify the script command as follows:

 "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview"
  },

Eleven, postcss configuration

  1. Install the plugin

     pnpm add postcss autoprefixer -D

12. Add eslint plugin

  1. Install the plugin

     pnpm remove eslint eslint-plugin-html eslint-plugin-vue
    pnpm add eslint eslint-plugin-html eslint-plugin-vue eslint-config-prettier eslint-plugin-prettier prettier -D
    # vite-eslint插件
    pnpm add vite-plugin-eslint -D
  2. Add vite.conf.js configuration

     import eslintPlugin from 'vite-plugin-eslint'
    
    export default ({ mode }) => {
        return defineConfig({
        plugins: [
            // ...
            eslintPlugin(),
            // ...
        ]
       })
    }

13. Add lang="jsx" to the file with jsx syntax

 <script lang="jsx">
    ...
</script>

14. Add @alias

Modify vite.conf.js configuration

 export default ({ mode }) => {
    return defineConfig({
       resolve: {
       // ...
         alias: [
           {
              find: /@\/.+/,
              replacement: (val) => {
                  return val.replace(/^@/, path.resolve(__dirname, './src/'))
              },
           },
         ]
       },
    )
}

15. Static file introduction

  1. Introducing dynamic components

     const modules = import.meta.glob('../views/**/*.vue')
    
    const currentRouter {
        ...
        // component: constantRouterComponents[item.component || item.key] || (() => import(`/src/views/${item.component}`)),
        component: constantRouterComponents[item.component || item.key] || modules[`../views/${item.component}.vue`],
        ...
    }
  2. Importing static images

    • Direct import image

       <template>
          <img :src="LogoImg" />
      </template>
      
      <script>
          import LogoImg from '/src/assets/img/logo.svg'
          export default {
              data() {
                  return {
                      LogoImg
                  }
              }
          }
      </script>
    • Adopt import.meta.globEager

        1. image loading

      <template>

       <img :src="getImg('../../assets/img/log.svg')" />

      </template>

      <script>

       export default {
          methods: {
              getImg(path) {
                  const modules = import.meta.globEager('../../assets/img/*.svg')
                  return modules[path].default
              }
          }
      }

      </script>

       * 2. require.context替换

      // before fixing
      // const req = require.context('./svg', false, /.svg$/)
      // const requireAll = requireContext => requireContext.keys().map(requireContext)

      // after modification
      const req = import.meta.globEager('./svg/*.svg')
      const requireAll = (requireContext) => Object.keys(requireContext).map((key) => requireContext[key].default)

     ### 十六、其他
  3. Problem: fim.js dependency package reference problem

    Solution: delete the viser-vue dependency package, you can use the official G2 package library @antv/g2plot instead

     pnpm remove viser-vue
    pnpm add @antv/g2plot
  4. Problem: ant-design-vue component List reference problem, List.Item is undefined

    Solution 1: Replace the code

     // 替换List组件代码,List.Item为undefined
     if (source.indexOf('Vue.component(List.Item.name, List.Item);')) {
        source = source.replace(
          'Vue.component(List.Item.name, List.Item);',
          'Vue.component("AListItem", Item);'
        )
     }
     if (source.indexOf('Vue.component(List.Item.Meta.name, List.Item.Meta);')) {
        source = source.replace(
          'Vue.component(List.Item.Meta.name, List.Item.Meta);',
           'Vue.component("AListItemMeta", Item.Meta);'
     )
    }

    Solution 2: Refer to List.Item separately


silianpan
160 声望9 粉丝

专注于web前端,spring boot,微服务架构。坚持原创技术分享,为开源贡献力量。