文章目录
前言
vue cli 脚手架转成vite启动
简单说说这个项目的一些底层基本结构哈,以及写这篇博客的目的。
这个项目底层结构是vue2.7.14 + vant ,使用vue cli脚手架搭建的一个H5项目,由于内容比较多,并没有使用vue3重构,但是由于内容过多,渐渐的启动特别耗时,所以计划该用vite去优化启动项。
写这篇博客,是记录本人在这个转换过程中遇到的一些问题。
在实际的过程中我用了两种方案,第一种利用插件webpack-to-vite。第二种是自己搭建vite。
方案一(借用插件转换)
webpack-to-vite & wp2vite
在我动手之前,就各种百度查资料了哈,因为我想秉持着偷懒的原则,想利用插件快速转换。
在我浏览了n个网站后,找到了感觉还比较可靠的两种插件,当然第二个插件我没用,我这里用的是第一个插件。
以下两个插件地址
webpack-to-vite
wp2vite
由于我是用了第一个插件,接下来的方案一都是围绕第一个插件开始的。
启动命令,转换
typescript
// <project path> 项目地址
npx @originjs/webpack-to-vite <project path>
或者
npm install @originjs/webpack-to-vite -g
webpack-to-vite <project path>
转换后,会在你项目中的同级目录下生成一个project-name-TOVITE文件,这个文件就是转换后的了。
最后就是打开,安装包,启动了,然后开始踩坑了。
方案一转换遇到的问题
- Error: Vue packages version mismatch:
研究了下,这个问题呢其实是在说vue的包版本不匹配。那就手动改改咯,vue-template-compiler版本改成2.7.14。
问题解决,跑起来了 - 跑起来空的
这里我猜测是index.html没有配置main.ts的引入,导致的,所以我在vite.config.js加上了一些配置。
加完运行起来又抛了一个错误。 - TypeError: vite.createFilter is not a function
这个错误我查了下,说是表明你正在尝试调用vite.createFilter这个函数,但是在你当前的Vite版本中,这个函数不存在或者已经被重命名、移除或者未正确导出。让我升级下版本,我就升级了vite,这个问题结束,又出现新的问题。 - [vite] Internal server error: Unexpected token (9:900)
我怀疑是vite-plugin-vue2插件的问题,于是换了一个,在vite.config.js中加上了以下代码。
typescript
import vue from '@vitejs/plugin-vue2'
plugins: [
vue(),
]
然而引发了下面这个问题。
- [Vue warn]: Failed to mount component: template or render function not defined.
好不容易跑起来了,结果页面抛出了又一个错误。
一脸懵逼的我,继续百度查问题,说是可能是vue的问题,于是我把上面的给去掉了,回归到上一个问题上。
但是这不就进入死循环了,还是说上个问题是其他原因导致的。
绕来绕去,我放弃了方案一了,我打算不用这个转的,自己安装vite,配置vite.config.js
也不能说这合格插件不行吧,可能我这项目比较复制,比较老,不适合
方案二(手动调整)
以下是我手动的方式调整文件
- package.json文件
typescript
// 运行命令
"serve-vite": "vite --host"
// 额外,安装包
"@originjs/vite-plugin-commonjs": "^1.0.3", // 用于将一些commonJs的规范转成es的
"postcss-plugin-px2rem": "^0.8.1", // px单位转成rem配置
"vite-plugin-html": "^3.2.2",
"vite-plugin-style-import": "^2.0.0", // 这个是用来处理vant的样式配置问题
"@vitejs/plugin-vue2": "^2.3.1", // 兼容vue2
"vite": "^5.4.10", // vite
- 根目录增加 testVite.html,里面内容和vue cli脚手架里的index.html是一摸一样的,唯一的不同是增加了以下代码
typescript
<!-- 这里是为了处理一个 Uncaught ReferenceError: global is not defined 问题,-->
<!-- 出现这个的原因 在 Node.js 环境中,global 通常是一个特殊的对象,它提供了一种方法来定义全局变量或访问全局变量。但在浏览器环境或者使用 Vite 开发环境中,global 对象并不存在,因此会抛出此错误。 -->
<!-- vite 运行会导致这个问题出现 -->
<script>
// 处理 Uncaught ReferenceError: global is not defined 的问题
if (window.global === undefined) {
window.global = window;
}
</script>
- tsconfig.json文件
typescript
"moduleResolution": "node" // 增加配置
- vite.config.js文件
typescript
import vue from '@vitejs/plugin-vue2' // 使用第三方插件
import postcssPluginPx2rem from 'postcss-plugin-px2rem'
import AutoImport from 'unplugin-auto-import/vite'
import { defineConfig } from 'vite'
import { resolve } from 'path'
import { createHtmlPlugin } from 'vite-plugin-html'
import { createStyleImportPlugin, VantResolve } from 'vite-plugin-style-import'
import { viteCommonjs } from '@originjs/vite-plugin-commonjs'
const pathResolve = (dir) => {
return resolve(__dirname, '.', dir)
}
export default async ({ command, mode }) => {
const unoCSS = (await import('unocss/vite')).default
return defineConfig({
resolve: {
extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.less', '.css', '.vue', '.min.js'],
alias: {
'@': pathResolve('./src'),
'swiper/swiper-bundle.min.js': pathResolve('./node_modules/swiper/swiper-bundle.min.js') // 这个代码很重要,兼容swiper8.0.7以上版本的导入问题
}
},
plugins: [
vue(),
unoCSS(),
viteCommonjs(),
createHtmlPlugin({
minify: true,
// 注:指定entry后,不需要在index.html添加script标签,若添加了建议删除
entry: './src/main.ts',
template: './testVite.html',
inject: {
data: {
title: 'index',
injectScript: `<script src="./inject.js"></script>`
}
}
}),
AutoImport({
// 自动导入 Vue 相关函数,如:ref, reactive, toRef 等
imports: ['vue']
// dts: resolve(__dirname, './auto-imports.d.ts'),
// eslintrc: {
// // 已存在文件设置默认 false,需要更新时再打开,防止每次更新都重新生成
// enabled: false,
// // 生成文件地址和名称
// filepath: resolve(__dirname, './.eslintrc-auto-import.json'),
// globalsPropValue: true
// }
}),
createStyleImportPlugin({
resolves: [
VantResolve()
]
})
],
css: {
preprocessorOptions: {
less: {
math: 'always'
}
},
postcss: {
plugins: [
postcssPluginPx2rem({
// remUnit: 16 // 设计稿宽度/10,通常是750/10=75
rootValue: 16,
unitPrecision: 8,
mediaQuery: false
})
]
}
},
server: {
port: 9528,
proxy: {
// 选项写法
'/api': {
target: 'http://127.0.0.1:8000',
// target: 'http://172.16.111.33:9797/rpc', // ToDo开发
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '')
}
},
hmr: {
overlay: false
},
host: '0.0.0.0'
}
})
}
方案两者对比
最后其实,我是采用方案二的方式跑起来项目了,当然方案二过程中也是遇到一些问题,比如swiper的导入问题,抛出这合格错误,Pre-transform error: Missing "./swiper-bundle.min.js" specifier in "swiper" package
我并不想去降版本,或者升级版本,或者改业务逻辑代码去解决这个问题哈,所以我在配置上增加了额外的配置去解决,因为改业务场景,一来,涉及的页面可能很多,而来,需要一个一个测试比较繁琐。
第一种方案呢我并没有成功,一来,我并不知道插件转后加了那些东西,二来,我也是遇到问题解决问题,但是众所周知,很多问题,可能是因为你第一个解决的方法不完全对而引起的,当然我也看到一些大神是确实可以实现的,要不然,官方也不可能把这个插件收录了。
小结
最后,其实我转的还不是很完全,也不是很完美,后期我也发现一个瑕疵。
不完全的地方在于,我并没有处理打包的逻辑,仅仅只是开发预览转换了。
瑕疵在于,我发现热更新的时候会抛出这个问题。
我很纳闷,第一次运行是没问题的,但是更改业务代码,热更新后就会抛出这个问题,我也查询过,意思是在未初始化之前就使用了。但是我检查了main.ts文件很久,没发现那不对,后面发现我这个项目很多地方引入了实例,比如router,比如vm,这就导致了依赖循环问题,所以其实是个无解的。
最后个人建议还是不要把成熟的vue2的项目强制转成vite吧,代价挺大,同时vite个人感觉确实启动很快,但是打包的配置并没有webpack多元化,而且vite当中加载的顺序十分重要,稍微没处理好,就是失败了。
以上就是我这次转换vite的经历了,简单记录一下。