全网最硬核的Ant-Design-Vue从Vue-cli迁移至Vite
一、前言
众所周知,Vite作为下一代前端开发与构建工具,就是一个字:快。并且Vite已经作为Vue3默认的构建工具。通过实验表明,项目迁移后,从Vue-cli的近2分钟,到Vite的5秒(项目大小不同,时间也不同),提升了几十倍甚至上百倍的速度。
本文针对老项目从Vue-cli迁移到Vite,提供了全网最全的方案。下面以ant-design-vue-pro为例进行迁移,ant-design-vue版本为1.7.8。
同时,提供了迁移后的仓库,欢迎Star~
GitHub - Seals-Studio/ant-design-vue-pro-vite
迁移前后对比(参考)
构建工具 | 服务器启动耗时 | 页面首次加载速度 (无缓存) | 第二次加载速度 (有缓存) | 热更新 HMR | 打包 |
---|---|---|---|---|---|
Webpack | 83s | 4.78s | 3.35s | 4.78s | 3mins 37s |
Vite | 4.72s (第二次 0.72s) | 1.71s | 1.33s | 瞬间 | 51.45s |
- 删除@vue和babel相关
{ "@vue/babel-helper-vue-jsx-merge-props": "^1.2.1", "@vue/cli-plugin-babel": "^4.5.17", "@vue/cli-plugin-eslint": "^4.5.17", "@vue/cli-plugin-router": "^4.5.17", "@vue/cli-plugin-unit-jest": "^4.5.17", "@vue/cli-plugin-vuex": "^4.5.17", "@vue/cli-service": "^4.5.17", "@vue/eslint-config-standard": "^4.0.0", "@vue/test-utils": "^1.3.0", "babel-eslint": "^10.1.0", "babel-plugin-import": "^1.13.3", "babel-plugin-transform-remove-console": "^6.9.4", }
- 删除loader(webpack插件)和webpack
{ "file-loader": "^6.2.0", "less-loader": "^5.0.0", "vue-svg-icon-loader": "^2.1.1", "git-revision-webpack-plugin": "^3.0.6", "webpack-theme-color-replacer": "^1.3.26", }
- 删除babel.conf.js和jsconfig.json
- 安装pnpm工具
pnpm是快速的,节省磁盘空间的包管理工具
npm i -g pnpm
# 淘宝源
pnpm config set registry https://registry.npm.taobao.org
pnpm config set disturl https://npm.taobao.org/dist
pnpm config set NVM_NODEJS_ORG_MIRROR http://npm.taobao.org/mirrors/node
pnpm config set NVM_IOJS_ORG_MIRROR http://npm.taobao.org/mirrors/iojs
pnpm config set PHANTOMJS_CDNURL https://npm.taobao.org/dist/phantomjs
pnpm config set ELECTRON_MIRROR http://npm.taobao.org/mirrors/electron/
pnpm config set SASS_BINARY_SITE http://npm.taobao.org/mirrors/node-sass
pnpm config set SQLITE3_BINARY_SITE http://npm.taobao.org/mirrors/sqlite3
pnpm config set PYTHON_MIRROR http://npm.taobao.org/mirrors/python
三、安装最新版vite和vite-plugin-vue2
pnpm add vite vite-plugin-vue2 -D
四、在根目录下新建vite.conf.js
import { defineConfig } from 'vite'
// vue2的vite插件
import { createVuePlugin } from 'vite-plugin-vue2'export default ({ mode }) => {
return defineConfig({
plugins: [
createVuePlugin({
jsx: true
})
]
})
})
五、index.html修改
- 移动public/index.html到代码根目录(和package.json同级)
- 在body标签中新增如下:
- 替换htmlWebpackPlugin插件注入的变量
htmlWebpackPlugin是webpack插件,所以不能再使用了,vite提供了vite-plugin-html插件来向index.html注入变量
- 安装vite-plugin-html
pnpm add vite-plugin-html -D
- 修改vite.config.js,添加配置
plugins: [ // ... createHtmlPlugin({ minify: true, inject: { data: { title: 'Ant Design Pro', cdn: { css: [], js: [ '//cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.min.js', '//cdn.jsdelivr.net/npm/vue-router@3.5.1/dist/vue-router.min.js', '//cdn.jsdelivr.net/npm/vuex@3.1.1/dist/vuex.min.js', '//cdn.jsdelivr.net/npm/axios@0.21.1/dist/axios.min.js' ] } } } }), // ... ]
- 修改index.html
- 修改title
- 锐客网
- 修改css和js引入
- 修改title
- 安装vite-plugin-html
出于安全考虑,vite只能识别以VITE_
开头的环境变量了,原VUE_环境变量不生效了,同时,也不能使用process.env.xxx
来读取环境变量了。需要修改vite.conf.js配置,手动添加process.env.xxx
环境变量
- 修改vite.conf.js配置,添加环境变量
import { defineConfig, loadEnv } from 'vite'export default ({ mode }) => { const env = loadEnv(mode, process.cwd()) return defineConfig({ define: { 'process.env': { ...env } }, }) })
- 将所有开头的
VUE_
环境变量全部替换为VITE_
- 将所有的
process.env.NODE_ENV
更改为import.meta.env.MODE
- 将所有开头为
process.env.
全部更改为import.meta.env.
- 安装vite-plugin-style-import插件
# 注意本插件必须采用1.4.1版本,不能采用最新版2.0.0
pnpm add vite-plugin-style-import@^1.4.1 -D
- 增加vite.conf.js配置
plugins: [ // ... styleImport({ libs: [ { libraryName: 'ant-design-vue', esModule: true, resolveStyle: (name) => { return `ant-design-vue/es/${name}/style/index` }, } ], }), // ... ]
原因是antdv底层引入采用:本文参考[]插件,写了一个vite插件,去修改antdv底层引入moment方式,改为:import * as moment from "moment";
未兼容ESM写法,参考 github issue: chore: v1 support vite
import moment from moment
- 安装依赖包
pnpm add rollup@">=1.20.0 <2.0.0 || >=2.0.0 <3.0.0" -D pnpm add @rollup/plugin-replace -D
- 修改vite.conf.js配置
import path from 'path-browserify'
import fs from 'fs'
import replace from '@rollup/plugin-replace'// 参考vite-plugin-antdv1-momentjs-resolver插件,修改正则表达式,兼容Windows路径
// https://github.com/carl-jin/vite-plugin-antdv1-momentjs-resolver/blob/main/src/index.js
// 将moment_util.js中import * as moment from moment修改import moment from moment
// 原正则表达式
// const antdvDefaultReg = /ant-design-vue\/[\w-\\\/]*\.js$/
// 修改后正则表达式
// const antdvDefaultReg = /ant-design-vue[\/|\\][\w-\\\/]*\.js$/
const AntdMomentResolver = (reg = /ant-design-vue[\/|\\][\w-\\\/]*\.js$/) => {
return {
name: 'vite-plugin-antdv1-momentjs-resolver',
configResolved(config) {
//以来预构建时候替换 esbuild
config.optimizeDeps.esbuildOptions.plugins = config.optimizeDeps.esbuildOptions.plugins
? config.optimizeDeps.esbuildOptions.plugins
: []
config.optimizeDeps.esbuildOptions.plugins.push({
name: 'replace-code',
setup(build) {
build.onLoad(
{
filter: reg,
},
(args) => {
// 首先获取源代码内容
let source = fs.readFileSync(args.path, 'utf8')
if (source.indexOf('import * as moment from')) {
source = source.replace(/import\s\*\sas\smoment\sfrom/g, 'import moment from')
}
return {
contents: source,
}
}
)
},
})//添加打包时的替换 rollup
config.plugins.push(
replace({
values: {
'import * as moment from': (id) => {
return 'import moment from'
},
},
include: [reg],
preventAssignment: true,
})
)
},
}
}// 引入插件
export default ({ mode }) => {
return defineConfig({
plugins: [
// ...
AntdMomentResolver(),
// ...
]
})
}
九、添加代理
- 安装path-browserify
pnpm add path-browserify -D
- 添加vite.conf.js配置
plugin: [], // ... server: { port: 8000, //proxy: { //'/api': { //target: 'https://mock.ihx.me/mock/5baf3052f7da7e07e04a5116/antd-pro', //changeOrigin: true, //ws: false, //rewrite: (path) => path.replace(/^\/api/, ''), //} //}, },
将脚本命令修改为如下:
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
十一、postcss配置
- 【全网最硬核的Ant-Design-Vue从Vue-cli迁移至Vite】安装插件
pnpm add postcss autoprefixer -D
- 安装插件
pnpm remove eslint eslint-plugin-html eslint-plugin-vue pnpm add eslint eslint-plugin-html eslint-plugin-vue eslint-config-prettier eslint-plugin-prettier prettier -D # vite-eslint插件 pnpm add vite-plugin-eslint -D
- 添加vite.conf.js配置
import eslintPlugin from 'vite-plugin-eslint'export default ({ mode }) => { return defineConfig({ plugins: [ // ... eslintPlugin(), // ... ] }) }
十四、添加@别名
修改vite.conf.js配置
export default ({ mode }) => {
return defineConfig({
resolve: {
// ...
alias: [
{
find: /@\/.+/,
replacement: (val) => {
return val.replace(/^@/, path.resolve(__dirname, './src/'))
},
},
]
},
)
}
十五、静态文件引入
- 动态组件引入
const modules = import.meta.glob('../views/**/*.vue')const currentRouter { ... // component: constantRouterComponents[item.component || item.key] || (() => import(`/src/views/${item.component}`)), component: constantRouterComponents[item.component || item.key] || modules[`../views/${item.component}.vue`], ... }
- 静态图片引入
- 直接
import
图片
文章图片
- 采用
import.meta.globEager
文章图片
### 十六、其他
- 直接
- 问题:fim.js依赖包引用问题
解决:删除viser-vue依赖包,可以改用官方G2的封装库@antv/g2plot
pnpm remove viser-vue pnpm add @antv/g2plot
- 问题:ant-design-vue组件List引用问题,List.Item为undefined
解决一:替换代码
// 替换List组件代码,List.Item为undefined if (source.indexOf('Vue.component(List.Item.name, List.Item); ')) { source = source.replace( 'Vue.component(List.Item.name, List.Item); ', 'Vue.component("AListItem", Item); ' ) } if (source.indexOf('Vue.component(List.Item.Meta.name, List.Item.Meta); ')) { source = source.replace( 'Vue.component(List.Item.Meta.name, List.Item.Meta); ', 'Vue.component("AListItemMeta", Item.Meta); ' ) }
解决二:单独引用List.Item
推荐阅读
- quartus|利用quartus ii进行IP核的调用
- 投稿|养老产业的两大核心赛道
- 产品策略(核心概念和流程指南)
- Redis核心技术与实践 03 | 高性能IO模型(为什么单线程Redis能那么快())
- Spring核心容器 - 简介 BeanFactoryApplicationContext
- 国内linux内核名人,世界10大IT技术伟人 Linux之父居首
- 让你的网站由真实人审核
- 「技术干货」Linux内核中的互斥量——Mutex锁
- FinClip|FinClip 前端之 VUE 核心原理总结
- 大健康|核酸采样员岗位火了,机器人的机会也来了