webpack迁移vite小结

Vite 是新一代的前端开发与构建工具,相比于传统的webpack,Vite 有着极速的本地项目启动速度(通常不超过5s)以及极速的热更新速度(几乎无感知)。
Vite 官网:https://cn.vitejs.dev/

下面分享 Webpack 项目(vue-cli项目)迁移至 Vite 的过程步骤、遇到的问题及解决方式。

一、项目背景

首先不建议做同时支持webpack和vite,这种只适合自己玩玩,实际项目中要考虑多人开发时的协作和维护成本,只用一种最好。

二、引入Vite

1、package.json

  • scripts里替换命令:
"dev": "vite",
"serve": "vite preview",
"build": "vue-tsc --noEmit && vite build"
  • devDependencies移除依赖:
    webpack迁移vite小结_第1张图片
  • 添加依赖:
npm i @vitejs/[email protected] [email protected] [email protected] -D

2、vite配置文件

移除vue.config.js,
添加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从public文件夹移动到项目根目录里。
官方说明:https://vitejs.cn/guide/#index-html-and-project-root

4、TS相关

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

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

5、启动

尝试npm run dev运行:
(十有八九跑不起来,问题往下翻。)

三、不兼容点

1、环境变量

webpack里的构建时环境变量默认存储在process.env里,
而vite是存储在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相反)

所以项目里用到的相关地方需要修改,例如process.env.NODE_ENV应替换为import.meta.env.MODE。

2、.env文件

  • vue-cli项目的.env文件自定义变量名都是以VUE_APP_开头,
  • vite里需要改成以VITE_开头

3、路由history模式

  • vue-cli项目如果是部署在服务器子目录下,需要配置vue.config.js里的publicPath字段为子目录路径,例如 /h5
  • 而vite里需要配置vite.config.ts里的base字段,且该字段需要以/结尾,例如 /h5/

4、.vue文件的引入方式

vite + ts 里所有.vue文件的引入都必须精确到.vue拓展名,

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

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

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

5、JSX支持

  • webpack项目支持jsx是使用的@vue/babel-plugin-jsx插件,
  • vite里对应的插件是@vitejs/plugin-vue-jsx
    vite.config.ts里需要配置:
    import vueJsx from '@vitejs/plugin-vue-jsx'
    
    plugins: [
      ...,
      vueJsx(),
    ],
    

6、require.context

  • require context 是 webpack 提供的特有的模块方法,用于导入一个目录下的所有文件
    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 })
    
  • 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 })
    

四、第三方插件

一些适用于webpack的第三方插件在vite里肯定不适用了,只能寻找替代方案。

1、svg-sprite-loader

改用vite-plugin-svg-icons

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

2、path-to-regexp

  • vue-cli项目里可以直接使用path-to-regexp包,估计是vue-cli有相关依赖
  • vite里需要手动安装,npm i path-to-regexp -S
    最新版是按需引入方式import { pathToRegexp } from 'path-to-regexp'

3、autoprefixer

如果项目配置了autoprefixer,也需要手动安装依赖npm i autoprefixer -D
另外vite也能自动读取postcss.config.js配置:

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

4、path模块

vite里在运行在浏览器端的业务代码里不支持直接使用path模块书写路径,需要使用path-browserify

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

5、全局less引入

  • webpack里可以通过配置style-resources-loader插件来引入一个less文件作为全局less自动导入,从而在任意.vue文件的