vue2 转 vite 流程
目前负责的后台系统项目由老的vue2项目拆出,因为在其他项目中开发环境使用过vite,效率很高,考虑将此项目开发和生产都转为vite。
安装
安装 vite : yarn add vite
安装支持vue2所需的插件:yarn add vite-plugin-vue2
新建vite.config.js
import { createVuePlugin } from 'vite-plugin-vue2'
import { defineConfig, loadEnv } from "vite";
import { resolve } from 'path'
export default ({ command, mode }) => {
return defineConfig({
base: './',
plugins: [
createVuePlugin()
],
resolve: {
alias: [{ find: '@', replacement: resolve(__dirname, 'src') },
{ find: '@assets', replacement: resolve(__dirname, 'src/assets') },
{ find: '@utils', replacement: resolve(__dirname, 'src/utils') },
{ find: '@plugs', replacement: resolve(__dirname, 'src/plugs') },
{ find: '@theme', replacement: resolve(__dirname, 'src/theme') },
{ find: '@pages', replacement: resolve(__dirname, 'src/pages') },
{ find: '@constants', replacement: resolve(__dirname, 'src/constants') },
{ find: '@components', replacement: resolve(__dirname, 'src/components') }],
},
// css预处理器配置
css: {
preprocessorOptions: {
less: {
javascriptEnabled: true
},
}
},
// 预览配置
preview: {
open: true, // 在服务器启动时自动在浏览器中打开应用程序
host: '0.0.0.0',
port: '4888'
},
// 本地运行配置,及反向代理配置
server: {
open: true, // 在服务器启动时自动在浏览器中打开应用程序
host: '0.0.0.0',
port: '3888',
proxy: {
'/hqrs': {
target: 'http://10.181.24.54:9610',
changeOrigin: true
}
}
},
})
}
新建index.html
vue-cli默认入口文件是放在public目录下面,vite是在根目录,所以要在根目录新建,或者修改vite.config的root。
index.html添加<script type="module" src="/src/main.js"></script>
项目启动
现在可以修改启动项为'serve': 'vite'执行yarn serve 发现报错
问题1:环境变量
这是项目内部封装的请求库,使用了.env环境变量文件配置一些域名、鉴权信息,但是vite项目内获取环境变量是用import.meta.env.VITE.XXX的方式,所以需要在配置文件中使用vite的loadEnv获取环境变量 并用 define 配置做替换, 另外就是环境变量一定要是VITE_前缀的才能被获取
import { defineConfig, loadEnv } from "vite";
export default ({ command, mode }) => {
let env = loadEnv(mode, process.cwd())
env = Object.keys(env).reduce((pre,cur)=>{
pre[cur.replace('VITE_', '')] = env[cur]
return pre
},{})
return defineConfig({
define: {
'process.env': env
},
...
})
})
问题2:cjs改为esm
这个原因是webpack使用的CommonJS模块化,可以使用require。vite使用的ESM,所有require注入的地方都要修改,上图报错的位置在路由
new VueRouter({
routes:[{
title: '登录',
path: '/login',
name: 'login',
component: resolve => require(['../pages/login/index.vue'], resolve)
},
...]
})
改为
new VueRouter({
routes:[{
title: '登录',
path: '/login',
name: 'login',
component: resolve => import('../pages/login/index.vue')
},
...]
})
问题3:.vue后缀
经过上面的修改,项目启动成功,但是部分页面报错
vite不推荐.vue后缀省略 原本项目大部分都不会加 很头疼 可以在vite.config resolve配置中添加extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue']配置解决此问题,但貌似不是所有版本支持,我的vite版本为2.9.5 可以使用。
兼容ie11
vite使用的esbuild构建,构建出来的文件模块也是esm的,只能支持现代浏览器,需要支持ie的需要使用官方提供的插件 @vitejs/plugin-legacy
开发环境就算了啊,没法兼容的,开发咱就用正常浏览器就可以了。
安装 yarn add @vitejs/plugin-legacy
修改vite.config.js
import legacy from '@vitejs/plugin-legacy'
export default ({ command, mode }) => {
return defineConfig({
...,
plugins: [
...,
legacy({
targets: ['ie >= 11'],
additionalLegacyPolyfills: ['regenerator-runtime/runtime']
})
],
...
})
})
插件改写
至此项目开发环境就完全跑通了,但是原项目发布是项目内开发了一个插件,会在webpack编译完成后执行发布流程。
那现在生产环境想要使用vite必须将此插件改为vite版本的,了解了下 修改的东西其实不多 vite的插件是rollup的扩展有一些自己内置的钩子 我这边也用不到
vite插件就是导出一个函数 函数返回插件对象,包括name、enforce,apply和一些钩子,enforce可以控制插件顺序我这边也用不到,apply是指定开发环境的,因为我这边插件是用来发布代码的,所以指定为build才执行。
一开始查阅资料是没有报错的情况下 buildEnd就会是最后一个钩子 实际使用会在rendering chunks前执行 这个时候文件还没有生成,所以改用了closeBundle,可以保证是最后执行。又大概查了下 buildEnd是在执行generate或者write之前被调用,这块确实不熟悉,但目前使用没啥问题。
export default function XXX() {
return {
name: 'xxx',
apply: 'build',
closeBundle(err) {
// 发布流程代码
...
}
}
}
这里执行又出现问题,发布的时候也会使用环境变量文件配置的环境变量,但是vite并没有给process.env注入,上面说到的使用define做替换只是在项目层面做了静态替换,不影响插件的,所以这里需要处理。
一开始我是考虑直接把使用loadEnv获取到的环境变量直接传参给插件,但总觉得有些别扭,突然想到可以了解下vue-cli是如何读取环境变量文件的,经过查阅,了解到可以使用dotenv读取.env并注入process,这样连.env内数据的VITE_前缀都不用加了
安装dotenv后 将vite.config修改
import dotenv from 'dotenv'
dotenv.config({ path: '.env.development' });
export default ({ command, mode }) => {
return defineConfig({
define: {
'process.env': process.env
},
...
})
})
最后
至此,老项目迁移vite也就算是成功了,难度不算大,但中间还是被一些问题牵制了很长时间。成果还是挺显著的,尤其在开发环境,效率提高很多