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.
- The main technology stack and version of the original project:
[email protected]
[email protected]
[email protected] - Based on [email protected]
- Migrate to [email protected]
2. Introducing Vite
1、package.json
- Substitute commands in scripts:
"dev": "vite",
"serve": "vite preview",
"build": "vue-tsc --noEmit && vite build"
- devDependencies remove dependencies:
- 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 dev
run:
(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-jsx
plugin, - 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 context
It is a unique module method provided by webpack for importing all files in a directoryconst 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 vite
import.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-loader
in the tags of any .vue file .<style>
- Vite.config.ts can be configured in vite:
In addition, variables defined by less cannot use alias shortcut identifiers when defining paths, and need to use absolute paths instead:css: { preprocessorOptions: { less: { additionalData: `@import "${ path.resolve(__dirname, 'src/styles/variable.less')}";`, javascriptEnabled: true, } } },
// 原方式 @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 --fix
directly - 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" ] },
- The lint of the vue-cli project is run
- Lock dependency versions
- In the end, it was found that it was a dependency version problem. The dependency version in package.json
npm i
was 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.
- In the end, it was found that it was a dependency version problem. The dependency version in package.json
- 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.ts
Full 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, } } }, })