Vite 加 Tailwindcss 开发会有啥体验?

banner.jpg
Vite2记得是在2021春节左右推出的,我是公众号里看到一篇文章才知道有这么个东西。
那时就在感叹:我在过节,别人却在推动技术!所以年后上班趁各线项目还没从节日的气氛中缓过来时,我就抓紧摸鱼研究起来。摸鱼的目的…呸!研究目的主要2个:

  1. 之前有搭过基于Vue-Cli的多页面脚手架,然后也在实战项目中用了,那热更新速度够我刷会微博了,那时为了加快热更新速度,都事先在脚手架里把未涉及到的或者比较稳定的模块入口先过滤掉,只保留当前开发所要用到模块,可想而知当时是有多慢了。
  2. 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我就默认大家都已经装好了。

whoagree.gif

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-viewportpostcss-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不就行了?

模式和环境变量 | Vue CLI

但是如果前端页面想用这些变量是无法通过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(求大佬拍醒)。所以应该怎么处理呢?

自己查百度.png

百度不行谷歌.png

还好还好,文档里都有。
Env Variables and Modes | Vite
import.meta – JavaScript | MDN

嗯,问题不大。import.meta + .env,稍微配置下就能解决页面中需要用到环境变量的问题(记得变量前缀加上VITE_)。
但是我还想在vite.config.js中使用变量怎么办呢,直接写process么?虽然可行,但是不优雅,因为已经用了.env,就不要把变量散落在项目各个文件中,那还是在.env文件里写吧。啥?.env的变量在vite.config.js里读不到!咋解决?

百度查不到.png

谷歌不行砸电脑.png

还好还好,谷歌查到了,不用砸电脑了。

env variables not accessible in vite.config.js · Issue #1930 · vitejs/vite

祖师爷说无法用,因为这是个

先有鸡还是先有蛋的问题

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享