Summary of webpack migration vite

Vite is a new generation of front-end development and construction tools. Compared with traditional webpack, Vite has extremely fast local project startup speed (usually no more than 5s) and extremely fast hot update speed (almost imperceptible).
Vite official website: https://cn.vitejs.dev/

Let's share the process steps, problems encountered and solutions of migrating Webpack project (vue-cli project) to Vite.

1. Project Background

First of all, it is not recommended to support webpack and vite at the same time. This is only suitable for playing by yourself. In actual projects, the collaboration and maintenance costs of multi-person development should be considered, and only one is the best.

2. Introducing Vite

1、package.json

  • Substitute commands in scripts:
"dev": "vite",
"serve": "vite preview",
"build": "vue-tsc --noEmit && vite build"
  • devDependencies remove dependencies:
    insert image description here
  • Add dependencies:
npm i @vitejs/[email protected] [email protected] [email protected] -D

2. vite configuration file

Remove vue.config.js and
add vite.config.ts:

  import {
    
     defineConfig } from 'vite'
  import vue from '@vitejs/plugin-vue'
  import path from 'path'
  
  // https://vitejs.dev/config/
  export default defineConfig({
    
    
    plugins: [
      vue(),
    ],
    resolve: {
    
    
      alias: {
    
    
        '@': path.resolve(__dirname, './src')
      }
    },
    server: {
    
    
      host: '0.0.0.0',
      port: 9000,
      proxy: {
    
    },
    },
  })

3、index.html

index.html is moved from the public folder to the project root directory.
Official description: https://vitejs.cn/guide/#index-html-and-project-root

4. TS related

+ tsconfig.json
	tsconfig.json的compilerOptions里添加配置:
	```json
	"isolatedModules": true,
	```
+ `/src/shims-vue.d.ts`(没有就新建):
	```js
	/// <reference types="vite/client" />

	declare module '*.vue' {
	  import type { DefineComponent } from 'vue'
	  const component: DefineComponent<{}, {}, any>
	  export default component
	}
	```
	注意其他第三方的ts声明放入另一个文件`/src/shims-tsx.d.ts`里,和vue-cli模式一致。

5. Start

Try to npm run devrun:
(Nine times out of ten, it won't work, and the question will be scrolled down.)

3. Incompatibility

1. Environment variables

The build-time environment variables in webpack are stored in process.env by default,
and vite is stored in import.meta.env,

import.meta.env.MODE: {
    
    string} 应用运行的模式。
import.meta.env.BASE_URL: {
    
    string} 部署应用时的基本 URL。他由base 配置项决定。
import.meta.env.PROD: {
    
    boolean} 应用是否运行在生产环境。
import.meta.env.DEV: {
    
    boolean} 应用是否运行在开发环境 (永远与 import.meta.env.PROD相反)

Therefore, the relevant places used in the project need to be modified. For example, process.env.NODE_ENV should be replaced with import.meta.env.MODE.

2. .env file

  • The .env file custom variable names of the vue-cli project all start with VUE_APP_,
  • Vite needs to be changed to start with VITE_

3. Routing history mode

  • If the vue-cli project is deployed in the server subdirectory, you need to configure the publicPath field in vue.config.js as the subdirectory path, such as /h5
  • In vite, the base field in vite.config.ts needs to be configured, and the field needs to end with /, such as /h5/

4. How to import .vue files

The introduction of all .vue files in vite + ts must be accurate to the .vue extension,

// 文件路径 src/components/Headers/index.vue

// 原方式
import Headers from '@/components/Headers'

// vite里
import Headers from '@/components/Headers/index.vue'

5. JSX support

  • The webpack project supports jsx by using the @vue/babel-plugin-jsxplugin,
  • The corresponding plug-ins in @vitejs/plugin-vue-jsx
    vite need to be configured in vite.config.ts:
    import vueJsx from '@vitejs/plugin-vue-jsx'
    
    plugins: [
      ...,
      vueJsx(),
    ],
    

6、require.context

  • require contextIt is a unique module method provided by webpack for importing all files in a directory
    const routes = require.context('./modules', true, /([\w\d-]+)\/routes\.ts/)
        .keys()
        .map(id => context(id))
        .map(mod => mod.__esModule ? mod.default : mod)
        .reduce((pre, list) => [...pre, ...list], [])
    
    export default new VueRouter({
          
           routes })
    
  • Need to use in viteimport.meta.globEager
    const routesModules = import.meta.globEager<{
          
          default: unknown[]}>('./modules/**/routes.ts')
    const routes = Object
      .keys(routesModules)
      .reduce<any[]>((pre, k) => [...pre, ...routesMod[k].default], [])
    
    export default new VueRouter({
          
           routes })
    

Fourth, third-party plug-ins

Some third-party plugins for webpack are definitely not applicable in vite, and we can only find alternatives.

1、svg-sprite-loader

Use vite-plugin-svg-icons instead

  • Configure global registration in main.ts:
    import SvgIcon from '@/components/SvgIcon/index.vue'
    
    const app = createApp(App)
    app.component('SvgIcon', SvgIcon)
    
  • Configure plugins in vite.config.ts:
    plugins: [
      ...,
      svgIcons({
          
          
        iconDirs: [path.resolve(process.cwd(), 'src/assets/svgs')],
        symbolId: 'icon-[dir]-[name]'
      })
    ],
    

2、path-to-regexp

  • The path-to-regexp package can be used directly in the vue-cli project. It is estimated that vue-cli has related dependencies
  • Vite needs to be installed manually npm i path-to-regexp -S, the
    latest version is imported on demandimport { pathToRegexp } from 'path-to-regexp'

3、autoprefix

If the project is configured with autoprefixer, you also need to manually install dependencies npm i autoprefixer -D,
and vite can also automatically read the postcss.config.js configuration:

	module.exports = {
    
    
	  plugins: [
	    require('autoprefixer'),
	  ]
	}

4. path module

In vite, it is not supported to directly use the path module to write the path in the business code running on the browser side, you need to usepath-browserify

// 原方式
import path from 'path'
// vite里(npm i path-browserify -S)
import path from 'path-browserify'

5. Global less introduction

  • In webpack, you can configure a plugin to introduce a less file as a global less automatic import, so that you can directly use the defined less variable or less mixin style-resources-loaderin the tags of any .vue file .<style>
  • Vite.config.ts can be configured in vite:
    css: {
          
          
        preprocessorOptions: {
          
          
          less: {
          
          
            additionalData: `@import "${
            
            path.resolve(__dirname, 'src/styles/variable.less')}";`,
            javascriptEnabled: true,
          }
        }
    },
    
    In addition, variables defined by less cannot use alias shortcut identifiers when defining paths, and need to use absolute paths instead:
    // 原方式
    @imgPath: '~@/assets/images';
    // vite里
    @imgPath: '/src/assets/images';
    

5. Other error reporting issues

1. @charset warning when packaging

This is related to the @charset configuration used by element-plus, and may also be used by other third-party dependencies. In short, vite verifies the use of @charset more strictly.

Workaround: configure vite to ignore warnings.

  • postcss.config.js
    module.exports = {
          
          
      plugins: [
        require('autoprefixer'),
        // 移除打包element时的@charset警告
        {
          
          
          postcssPlugin: 'internal:charset-removal',
          AtRule: {
          
          
            charset: (atRule) => {
          
          
              if (atRule.name === 'charset') {
          
          
                atRule.remove()
              }
            }
          }
        },
      ]
    }
    

2. Pre-commit failure problem

The project is configured with husky + pre-commit hook, and code lint verification is performed during git commit, but it fails after migrating vite.

The original project uses [email protected] [email protected], the solution steps:

  • Custom lint command
    • The lint of the vue-cli project is run vue-cli-service lint --fixdirectly
    • In vite, you have to write it yourself.
      "scripts": {
              
              
         	"lint": "eslint . --ext .js,.jsx,.vue,.ts,.tsx --fix"
      },
      "husky": {
              
              
          "hooks": {
              
              
            "pre-commit": "lint-staged"
          }
        },
        "lint-staged": {
              
              
          "*.{js,jsx,vue,ts,tsx}": [
            "npm run lint"
          ]
        },
      
  • Lock dependency versions
    • In the end, it was found that it was a dependency version problem. The dependency version in package.json npm iwas overwritten later. It may be that vite-related dependencies were overwritten. Find the package.lock.json file to verify.
    • The solution is to manually install the dependencies again separately:
      npm i [email protected] [email protected] -D
      
    • Note that package.lock.json should not be configured to be ignored by .gitignore. This is a version lock file, so I won't go into details.
  • yorkie-related errors
    yorkie is a module used with husky, and you need to manually install dependencies when you encounter errors:
    bash npm i yorkie -D

6. Conclusion

Originally, the migration was not too complicated, but because the project uses ts and eslint, the code verification is relatively strict, which makes the migration work at least double the workload, but the time spent is worth it, and rigorous code and specifications can guarantee the project. Continuous and stable operation and maintenance.

appendix:

  • vite.config.tsFull code:
    import {
          
           defineConfig } from 'vite'
    import vue from '@vitejs/plugin-vue'
    import path from 'path'
    import svgIcons from 'vite-plugin-svg-icons'
    import vueJsx from '@vitejs/plugin-vue-jsx'
    
    // https://vitejs.dev/config/
    export default defineConfig({
          
          
      base: '/yj99admin/',
      resolve: {
          
          
        alias: {
          
          
          '@': path.resolve(__dirname, './src')
        }
      },
      server: {
          
          
        host: '0.0.0.0',
        port: 9000,
        proxy: {
          
          },
      plugins: [
        vue(),
        svgIcons({
          
          
          iconDirs: [path.resolve(process.cwd(), 'src/assets/svgs')],
          symbolId: 'icon-[dir]-[name]'
        }),
        vueJsx(),
      ],
      css: {
          
          
        preprocessorOptions: {
          
          
          less: {
          
          
            additionalData: `@import "${
            
            path.resolve(__dirname, 'src/styles/variable.less')}";`,
            javascriptEnabled: true,
          }
        }
      },
    })
    

Guess you like

Origin blog.csdn.net/u010059669/article/details/121808645