Vite2记得是在2021春节左右推出的,我是公众号里看到一篇文章才知道有这么个东西。
那时就在感叹:我在过节,别人却在推动技术!所以年后上班趁各线项目还没从节日的气氛中缓过来时,我就抓紧摸鱼研究起来。摸鱼的目的…呸!研究目的主要2个:
- 之前有搭过基于Vue-Cli的多页面脚手架,然后也在实战项目中用了,那热更新速度够我刷会微博了,那时为了加快热更新速度,都事先在脚手架里把未涉及到的或者比较稳定的模块入口先过滤掉,只保留当前开发所要用到模块,可想而知当时是有多慢了。
- React脚手架摸索不多想试试,umijs太重不太喜欢,create-react-app如需定制化需要装额外暴露接口的包,有种官方血统被污染的感觉。而其他的又比较杂乱,看到vite可以用搭建基于react技术栈的脚手架就有点跃跃欲试。
稍微体验了下后就放在一边了。
敲过
yarn or npm install
就相当于这个脚手架我会了
后来看到一篇文章,文章题目我忘了,只记得大致内容:
作者跟领导提议想用Vue,领导回复说“你想吃屎?”。
就这样一篇文章带我尝试了下react + antD + vite,随后我又捡起vite将我之前基于Vue-Cli多页面的重新搭了下,并尝试加入了tailwindcss。
基于这些尝试性工作,在最近的混合开发H5中果断上了vite + vue3 + tailwindcss 进行实战。
结果…..还行,坑踩过了,我终于懂点皮毛了,下面就是实战总结。
vite 和 tailwindcss我就默认大家都已经装好了。
Tailwindcss
Tailwindcss 基于原子化理念,将样式重复性代码降到最小,原本开发最大限度基于类名的声明块不重复,现在Tailwindcss基于单独一句声明不重复。
开发体验:
- 不用一直想着如何取类名
- 少写了很多样式
- 需要额外心智去记住TW中的类名(不过装了VScode插件后有所改善)
- HTML中的class太多导致HTML整体较为拥挤
遇到的问题:
- 对于设计稿中如长宽在tailwindcss中没有对应值如何处理 ?
- 设计稿中是px,如何优雅的转换成rem或vw和vh呢?
- 颜色字体等如何扩展?
- 如何解决HTML中class较为拥挤的感官?
解决方式:
对于设计稿中如长宽等属性在tailwindcss中没有对应值如何处理 ?
tailwindcss 2.1之后加入一个中括号的特性,允许用户可以自定义值,这个特性对于书写样式的灵活度大大提高。
/* 如高度是22px的,就可以写成,同理z-index也可以,还有各种颜色等属性也可以这样 */
.example {
@apply h-[22px];
}
.example {
@apply z-[-1];
}
复制代码
设计稿中是px,如何优雅的转换成rem或vw和vh呢?
移动端的适配是开发过程比较要关注的点,而适配方式除了媒体查询断点之外,基本就是rem + html字体动态设置,以及通过 vw(vh)来处理。
tailwindcss默认就是以rem来处理,但是设计稿中是以px来显示,不可能每个值都通过人工算来处理转换成rem吧,用过sass或者less的同学基本想到了预处理器中的function。
虽然tailwindcss可以结合sass或者less,但是有种舍近求远的感觉,tailwindcss自身就是基于postcss,可以通过postcss的两个扩展来处理:postcss-px-to-viewport
和postcss-pxtorem
'postcss-px-to-viewport': {
unitToConvert: 'px', // 要转化的单位
viewportWidth: 375, // UI设计稿的宽度
unitPrecision: 6, // 转换后的精度,即小数点位数
propList: ['width, height'], // 指定转换的css属性的单位,*代表全部css属性的单位都进行转换
viewportUnit: 'vw', // 指定需要转换成的视窗单位,默认vw
fontViewportUnit: 'vw', // 指定字体需要转换成的视窗单位,默认vw
selectorBlackList: ['wrap'], // 指定不转换为视窗单位的类名,
minPixelValue: 4, // 默认值1,小于或等于4px则不进行转换
mediaQuery: true, // 是否在媒体查询的css代码中也进行转换,默认false
replace: true, // 是否转换后直接更换属性值
exclude: [/node_modules/], // 设置忽略文件,用正则做目录名匹配
landscape: false // 是否处理横屏情况
},
'postcss-pxtorem': {
rootValue: 16,
unitPrecision: 6,
propList: ['font', 'font-size', 'line-height', 'letter-spacing'],
selectorBlackList: [],
replace: true,
mediaQuery: true,
minPixelValue: 4,
exclude: /node_modules/i
}
复制代码
我这边rem主要用在字体上,vw用在width, height, padding, margin, border上,再加上媒体查询断点处理,移动端的自适应完全满足了。
颜色字体等如何扩展?
这个tailwindcss官方也有说明,我这边只说一点,要覆盖的直接写在theme
下,要扩展的直接写theme.extend
下。
直接看代码,注意下面2个fontFamily位置,sans字体是覆盖tailwindcss的默认值,bebasNeue是扩展字体(当然也别忘了在总入口处引入字体文件)
theme: {
fontFamily: {
sans: ['PingFang-SC-Bold', 'PingFang-SC', 'Microsoft YaHei', 'Microsoft Jhenghei', 'sans-serif']
},
extend: {
fontFamily: {
bebasNeue: ['BebasNeue Bold']
},
colors: {
'custom-blue': '#0088FF',
'custom-black': '#333333',
'custom-gray1': '#666666',
'custom-gray2': '#999999',
'custom-gray3': '#B2B2B2'
},
screens: {
'2xsm': '250px',
xsm: '320px'
}
}
}
复制代码
如何解决HTML中class较为拥挤的感官?
开发中你可能看到是这样的:
<span class="text-[30px] leading-[37px] text-white align-middle ml-[12px] mr-[4px] font-bebasNeue"></span>
复制代码
特别是遇到设计稿修改的,在调整样式的过程中可能又写了些类名,由于视觉上比较拥挤就有可能出现重复或者覆盖的情况。我这边后是这么处理的:
- 对于较长的,比如超过5个class的就设定个自定义class, 然后用这个class apply你要写的tailwindcss类名。
- 对于有hover,media-query的,可以多写几行区分,如:
<span class="custom"></span>
<style lang="postcss">
.custom {
@apply text-[30px] leading-[37px] text-white align-middle ml-[12px] mr-[4px] font-bebasNeue;
@apply md:text-[40px] md:leading-[50px];
@apply hover:text-red;
}
</style>
复制代码
对于简单的项目可以这样,对于复杂点的项目(如果设计稿是组件化标准设计的话)个人建议直接加一层全局自定义class(计算机相关问题中,万事不决加一层),每个class中apply tailwindcss的class。换个角度理解就是自己写UI框架,然后框架里每个类的声明块都替换为tailwindcss的类名。
Vite
遇到的问题
- 如何像Webpack那样拆包?
- 如何优雅增加环境变量?
- 打包时如何替换本地静态资源为CDN(OSS)资源?
- 对于有二级目录的线上环境,如何设置?
解决方式:
如何像Webpack那样拆包?
这个直观体验,rollup配置比webpack清晰太多了
// rollup的拆包配置
build: {
rollupOptions: {
output: {
manualChunks(id) {
if (id.includes('html2canvas')) {
return 'html2canvas'
} else if (id.includes('AMapLoader')) {
return 'AMapLoader'
} else if (id.includes('echarts')) {
return 'echarts'
} else if (id.includes('node_modules')) {
return 'vendor'
}
}
}
}
}
复制代码
如何优雅增加环境变量?
这个接触过vue-cli的同学可能会说,这不是很简单么,直接在vite.config.js里写process.env.your_variable不就行了?
但是如果前端页面想用这些变量是无法通过process访问到的,因为前端的模块是基于ESModule的规范,process是基于commonJS的规范。BTW,process可以在vite.config.js和postcss.config.js中能被访问到。
这是为什么呢?查看了下Vite依赖构建相关描述:
CommonJS 和 UMD 兼容性:开发阶段中,Vite 的开发服务器将所有代码视为原生 ES 模块。因此,Vite 必须先将作为 CommonJS 或 UMD 发布的依赖项转换为 ESM
所以我大胆猜测了下,vite.config.js和postcss.config.js的处理应该是在“依赖预构建
”前,那时还处在nodejs环境中,所以可以访问到process(求大佬拍醒)。所以应该怎么处理呢?
还好还好,文档里都有。
Env Variables and Modes | Vite
import.meta – JavaScript | MDN
嗯,问题不大。import.meta
+ .env
,稍微配置下就能解决页面中需要用到环境变量的问题(记得变量前缀加上VITE_
)。
但是我还想在vite.config.js中使用变量怎么办呢,直接写process么?虽然可行,但是不优雅,因为已经用了.env,就不要把变量散落在项目各个文件中,那还是在.env文件里写吧。啥?.env的变量在vite.config.js里读不到!咋解决?
还好还好,谷歌查到了,不用砸电脑了。
env variables not accessible in vite.config.js · Issue #1930 · vitejs/vite
祖师爷说无法用,因为这是个
先有鸡还是先有蛋的问题