webpack迁移vite⼩结
下⾯分享 Webpack 项⽬(vue-cli项⽬)迁移⾄ Vite 的过程步骤、遇到的问题及解决⽅式。
⼀、项⽬背景
⾸先不建议做同时⽀持webpack和vite,这种只适合⾃⼰玩玩,实际项⽬中要考虑多⼈开发时的协作和维护成本,只⽤⼀种最好。
原项⽬主技术栈及版本:
Vue@3.2.3
typescript@4.3.5
element-plus@1.0.2-beta.70
基于vue-cli@4.5.13
迁移⾄vite@2.6.4
⼆、引⼊Vite
1、package.json
scripts⾥替换命令:
"dev":"vite",
"serve":"vite preview",
"build":"vue-tsc --noEmit && vite build"
devDependencies移除依赖:
添加依赖:
npm i @vitejs/plugin-vue@1.9.3 vite@2.6.4 vue-tsc@0.3.0 -D
2、vite配置⽂件
移除fig.js,
添加fig.ts:
import{ defineConfig }from'vite'
import vue from'@vitejs/plugin-vue'
import path from'path'
// vitejs.dev/config/
export default defineConfig({
plugins:[
vue(),
],
resolve:{
alias:{
'@': solve(__dirname,'./src')
}
},
server:{
host:'0.0.0.0',
port:9000,
proxy:{},
},
svg和h5的关系})
3、index.html
4、TS相关
+ 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、启动
尝试npm run dev运⾏:
(⼗有⼋九跑不起来,问题往下翻。)
三、不兼容点
1、环境变量
webpack⾥的构建时环境变量默认存储在v⾥,
⽽vite是存储在v⾥,
所以项⽬⾥⽤到的相关地⽅需要修改,例如v.NODE_ENV应替换为v.MODE。
2、.env⽂件
vue-cli项⽬的.env⽂件⾃定义变量名都是以VUE_APP_开头,
vite⾥需要改成以VITE_开头
3、路由history模式
vue-cli项⽬如果是部署在服务器⼦⽬录下,需要配置fig.js⾥的publicPath字段为⼦⽬录路径,例如 /h5⽽vite⾥需要配置fig.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
import vueJsx from'@vitejs/plugin-vue-jsx'
plugins:[
...,
vueJsx(),
],
6、t
require context 是 webpack 提供的特有的模块⽅法,⽤于导⼊⼀个⽬录下的所有⽂件
const routes = t('./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⾥需要使⽤使⽤ a.globEager
const routesModules =a.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
改⽤
main.ts⾥配置全局注册:
import SvgIcon from'@/components/SvgIcon/index.vue'
const app =createApp(App)
appponent('SvgIcon', SvgIcon)
plugins:[
...,
svgIcons({
iconDirs:[solve(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也能⾃动读取fig.js配置:
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⽂件的<style>标签⾥直接使⽤定义的less变量或less混⼊等。
vite⾥可以配置fig.ts:
css:{
preprocessorOptions:{
less:{
additionalData:`@import "${solve(__dirname,'src/styles/variable.less')}";`,
javascriptEnabled:true,
}
}
},
另外,less定义的变量在定义路径时不能使⽤alias快捷标识,需要改⽤绝对路径:
// 原⽅式
@imgPath:'~@/assets/images';
/
/ vite⾥
@imgPath:'/src/assets/images';
五、其他报错问题
1、打包时@charset警告
这个和element-plus使⽤的@charset配置有关,也可能是其他第三⽅依赖使⽤的,总之vite对@charset的使⽤做了更严格的校验。
解决⽅法:配置让vite忽略警告。
plugins:[
require('autoprefixer'),
// 移除打包element时的@charset警告
{
postcssPlugin:'internal:charset-removal',
AtRule:{
charset:(atRule)=>{
if(atRule.name ==='charset'){
}
}
}
},
]
}
2、pre-commit失效问题
项⽬配置husky + pre-commit 钩⼦,在git commit时进⾏代码lint校验,迁移vite后竟然失效了。
原项⽬⽤的是typescript@4.3.5 husky@4.3.8,解决步骤:
⾃定义lint命令
vue-cli项⽬的lint是直接运⾏vue-cli-service lint --fix就⾏
vite⾥就得⾃⼰写了,
"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"
]
},
锁定依赖版本
最终发现是依赖版本问题,package.json⾥的依赖版本在npm i后被覆盖了,可能是vite相关依赖覆盖掉了,查
package.lock.json⽂件可以验证。
解决⽅式就是⼿动再单独安装⼀次依赖:
npm i typescript@4.3.5 husky@4.3.8 -D
注意package.lock.json不要配置.gitignore忽略,这是版本锁定⽂件,具体就不再赘述。
yorkie相关报错
yorkie是配合husky使⽤的模块,遇到报错时需要⼿动安装依赖:
bash npm i yorkie -D
六、结语
本来迁移不太复杂的,但由于项⽬使⽤了ts和eslint,代码校验⽐较严格,这使迁移⼯作⾄少增加了⼀倍的⼯作量,但时间花费是值得的,严谨的代码和规范才能保证项⽬持续稳定的运⾏和维护。