介绍
之前在vue3+vite中使用部分组件库,支持了antdv
等组件库(antd支持vite-plugin-components记录),大多数同学都在使用vue2生态,为了方便vue2生态更好迁移到vite2,这周搞了一下vite2+vue2,将带我启蒙的element-ui
和iview(view-design)
支持vite-plugin-components
自动按需加载,为开源社区贡献自己一点微薄的力量,顺便踩踩坑~~
使用vite2+vue2搭建基础项目
准备依赖包
vite 依赖
"vite-plugin-vue2": "^1.7.2",
vue 依赖
"@vue/compiler-sfc": "^3.1.4",
"vue": "2.6.11",
"vue-template-compiler": "2.6.11",
配置vite.config.js
import { createVuePlugin } from 'vite-plugin-vue2';
import { defineConfig } from 'vite';
export default defineConfig({
plugins: [
createVuePlugin()
]
})
很简单就配置完成了,下面就可以开始玩耍了
支持Element-UI
缘由
这个是我之前工作中用的最多的组件库,虽然现在不维护了,但依然老当益壮,对他有独特的情怀,即使挂也要让他挂的体面 ~
踩坑之旅
基本没有什么大坑,不得不赞一下作者的优秀设计!
注意的是需要引入基础样式base.css
,要不input-number
组件的按钮就会没有,
组件库分包还是比较规整的,只需要将组件名成转换为 烤肉串(kababCase) 形式即可,
子组件,比如menu-item
和menu
都分别定义成了两个包,打包之后在lib
包下也分为两个文件,menu
和menu-item.js
按需加载无需再关注他们的包含关系,直接导入对应的组件文件即可
return {
path: `element-ui/lib/${partialName}`,
sideEffects: getSideEffects(partialName, options),
}
所有样式都放在theme-chalk
下,引入对应组件样式和基础样式 如下:
if (importStyle === 'sass') {
return [
'element-ui/packages/theme-chalk/src/base.scss',
`element-ui/packages/theme-chalk/src/${partialName}.scss`,
]
}
else if (importStyle === 'css') {
return [
'element-ui/lib/theme-chalk/base.css',
`element-ui/lib/theme-chalk/${partialName}.css`,
]
}
备注:antfu大佬建议合并配置参数,因为之前是分别定义了,importStyle,importCss,importSass
三个参数,确实感觉没太大必要,用一个参数importStyle
不同的值完全可以满足三种状态开关,这样更易用。
PR:element-ui support
支持View-UI(iView)
缘由
这个是我接触vue2最开始的启蒙的组件库,当时的render
函数就是通过这个组件库学会的,感觉他体内流淌着一些antd
的血,虽然只用了一周,但是当时它确实显得更精致一些,但是由于后来工作中还是寻求稳定,没有选择它,更新频率有点慢。但是现在作者全职维护后更新快一些了,还改了名字,感觉不如iview好记。支持这个组件库也是因为有种独特的情怀吧~
踩坑之旅
这个坑就比较多了
1. 引入Select等依赖popover.js的组件时候,会报一个错误 require is not defined
解决:查看代码发现select的dropdown中是通过require这种commonjs语法导入popoverjs的 源码是这样写的:
const Popper = isServer ? function() {} : require('popper.js/dist/umd/popper.js'); // eslint-disable-line
应该是vite默认不支持coomonjs语法导入所以报错,于是我就在vite-awesome中查找相关插件,找到一个插件可以支持coomonjs导入,插件是@originjs/vite-plugin-commonjs
,使用方式也很简单,如下:
import { viteCommonjs } from '@originjs/vite-plugin-commonjs';
export default defineConfig({
plugins: [
viteCommonjs({}),
]
})
至此,这个问题解决了.
2. 引入viteCommonjs
之后报vue.runtime.esm.js:619 [Vue warn]: Error in nextTick: "TypeError: Popper is not a constructor"
解决:查询popover相关的issue,解决方式是需要在main函数中import一下,我觉得这样增加了用户的负担,于是直接在副作用sideEffects中引入这个库 至此这个问题解决。
3. table依赖的'element-resize-detector'
,date-picker组件依赖js-calendar
也需要通过副作用的方式引入
因为这俩依赖库也采用的commonJS的module.export写法,es6的import引入不进来
wiki: commonjs和es6模块化的使用
4. select下拉如果通过slot传入option,会报如下的错误
vue.runtime.esm.js:619 [Vue warn]: Error in getter for watcher "dropVisible": "TypeError: Cannot read property 'match' of undefined"
解决: 通过查看源代码,发现在select中有个匹配option
还是optionGroup
的正则,是用opts.tag.match
的方式进行判断的,此时如果tag
为undefined
则会报上面的错误
tag的作用 官网描述如下:
更改如下:
if (opts && optionRegexp.test(opts.tag)) return [node];
经过测试并不影响原有功能,兼容undefined
情况。
view-ui PR: github.com/view-design…
5. view-ui下拉框选中,值不回显的问题(暂未解决)
解: 经过在源码中打log,发现当点击option的时候触发了两遍,第一遍正常调用将选中的选项传过去,第二遍值变成undefined,暂时没有查清楚是哪里导致的重复调用,在vue-cli中是正常的
6. scroll组件无法正常解析,vue uses lang html for template, however it is not installed.
(暂未解决,不清楚设计目的,可手动解决)
解:这个问题很明显,是vite无法解析模板语法,因为scroll/loading-component
这个组件用了一个模板语法是<template lang="html">
view-ui 使用webpack相关的loader(html-loader)
进行解析,但是vite暂时还没有类似的loader所以无法解析,我尝试将lang=”html“
去掉发现就正常了,暂时不知为什么设计成这样,这个组件内部就是普通的vue语法,并没有什么特别的。
7. list下的子组件(list-item,list-item-meta)需要特别处理,都放在list目录下,否则找不到
至此组件库迁移,绝大多数没有问题了,把官网文档的demo都跑了一遍
核心代码:
export const ViewUiResolver = (): ComponentResolver => (name: string) => {
if (name.match(/^I[A-Z]/)) {
const compName = name.slice(1)
return {
path: `view-design/src/components/${getCompDir(compName)}`,
sideEffects: getSideEffects(compName),
}
}
}
const getSideEffects: (
compName: string,
) => string[] = (compName) => {
const sideEffects = [
'view-design/dist/styles/iview.css',
'popper.js/dist/umd/popper.js',
]
if (/^Table/.test(compName))
sideEffects.push('element-resize-detector')
if (/^Date/.test(compName))
sideEffects.push('js-calendar')
return sideEffects
}
PR: view-ui support
迁移Vuesax(alpha版本)
缘由
主要就是因为好看,这个组件库现在从版本3升级到了4,但是依然是只支持vue2,特效很炫,组件不是很多,搞他的目的就是因为他好看,没有别的原因,哈哈,不过路途也挺艰辛。
踩坑之旅
按需加载可以加载源码或者直接加载dist目录
1. 加载源码需要在项目安装 vue-class-component,vue-property-decorator,sass
,否则报错
因为源码都是采用ts decorator的形式写的,vue2时代写ts一般都采用这种,安装上面依赖以便解析对应的class语法和装饰器语法,这种语法看上去很不好看,代码量还多
2. 匹配组件目录
- 源码:如果引入的是源码则需要匹配到真实的组件目录,比如
VsSidebarGroup
的真实目录是vsSidebar/Group
, 源码中并没有单独为子组件创建一个包 - 编译代码:但是如果引入编译之后的文件就不必匹配了,编译之后dist目录会单独创建一个
VsSidebarGroup
的目录,里面有index.js
和style.css
,组件目录的首字母为小写,转换对了即可。
3. 引入layout
子组件row,col
的路径问题
- 源码:
layout
下的组件是放到了与components
同级目录,所以匹配的时候需要到上一级查找,可以正常引入 - 编译代码:
dist
目录并没有打出layout
的包,导致这俩layout
相关的子组件无法引入,但是全量包中存在
核心代码:
return {
path: getPath(name, options),
sideEffects: [
'vuesax/dist/vuesax.css'],
}
if (importSass) {
const dir = getCompDir(compName)
return `vuesax/src/components/${dir}`
}
else {
const dir = `${compName[0].toLowerCase()}${compName.slice(1)}`
return `vuesax/dist/${dir}`
}
暂时没有提交PR,这个组件库V4处于alpha阶段,组件不太完善,改动可能还会很大,等稍微稳定一些再说
结语
经过周末的几天研究,感觉还是很有收获的,起码用vite可以跑vue2的受众很广的组件库,不用再一遍遍写无用的注册代码,确实更爽了,其实这个插件还是有一些问题的,比如tsx/jsx的组件无法按需加载,此时就需要在单独引入别的按需插件,这个插件就失去了意义,对于template开发者还是很友好的。 总的来说,一个周末迁移了这三个组件库到vite生态,达到可用的状态,感觉还是挺爽的,能为开源社区贡献一份微薄之力,心满意足了~