Vite学习笔记03 - 配置高级CSS方案

803 阅读5分钟

样式方案的意义

对于初学者来说,谈到开发前端的样式,首先想到的就是原生CSS。但是时间一长,难免会发现原生CSS开发的各种问题。那么,如果我们不使用任何CSS工程方案,又会出现哪些问题呢?

  1. 开发体验不好,比如原生的CSS不支持浏览器的嵌套:
// 选择器只能平铺,不能嵌套
.container .header .nav .title .text {
  color: blue;
}

.container .header .nav .box {
  color: blue;
  border: 1px solid grey;
}
  1. 样式污染问题。如果出现同样的类名,很容易造成不同的样式污染和覆盖。
// a.css
.container {
  color: red;
}

// b.css
// 很有可能覆盖 a.css 的样式!
.container {
  color: blue;
}
  1. 浏览器兼容问题。为了兼容不同的浏览器,我们需要对一些属性(如transition)加上不同的浏览器前缀。比如-webkit-、-moz-、-ms-、-o-,意味着开发一个样式我们要写很多代码。

  2. 打包后的代码体积的问题,如果不适用任何的CSS工程方案,所有的CSS代码都将被打包到产物中。即使有部分样式并没有在代码中进行使用。导致产物体积过大。

针对以上原生CSS的痛点,社区中诞生了不少的解决方案,常见的有5类。

  1. CSS预处理器:主流的包括SASS/Scss.less和stylus。这些方案各自定义了一套语法,让CSS也能够使用嵌套规则,甚至能够像编程语言一样定义变量、写条件判断和循环语句。大大增加了样式语言的灵活性,解决原生CSS开发的体验问题。
  2. CSS Modules:能够将CSS类名处理成hash值,这样就可以避免同名的情况下的样式污染问题。
  3. CSS 后处理器PostCSS:用来解析和处理CSS代码。可以实现的功能非常的丰富,比如将px转换成rem。根据目标浏览器的情况自动加上类似于--moz--,-o-的属性前缀等。
  4. CSS in JS方案,主流的包括emotion、styled-components等等。顾名思义,这类方案可以实现直接在CSS中写样式代码。基本包含CSS预处理器和CSS Modules的各项优点,非常的灵活,解决了开发体验和全局样式污染的问题。
  5. CSS原子化框架,比如TailwindCSS、Windi CSS,通过类名来指定样式。大大简化了样式写法。提高了样式开发的效率。主要解决了原生CSS开发体验的问题。

Vite配置tailwindCSS

安装依赖

pnpm install -D tailwindcss postcss autoprefixer

新建两个配置文件:

// tailwind.config.cjs
module.exports = {
  content: [
    "./index.html",
    "./src/**/*.{vue,js,ts,jsx,tsx}",
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}

// postcss.config.cjs
// 从中你可以看到,Tailwind CSS 的编译能力是通过 PostCSS 插件实现的
// 而 Vite 本身内置了 PostCSS,因此可以通过 PostCSS 配置接入 Tailwind CSS 
// 注意: Vite 配置文件中如果有 PostCSS 配置的情况下会覆盖掉 post.config.js 的内容!
module.exports = {
  plugins: {
    tailwindcss: {},
    autoprefixer: {},
  },
}

在项目的入口CSS文件中添加代码

@tailwind base;
@tailwind components;
@tailwind utilities;

修改APP.jsx文件

<h1 className='bg-red-400'>Vite + React</h1>

效果:

图片.png

Vite项目配置CSS预处理器

Vite 本身对 CSS 各种预处理器语言(Sass/ScssLessStylus)做了内置支持。也就是说,即使你不经过任何的配置也可以直接使用各种 CSS 预处理器。我们以 Sass/Scss 为例,来具体感受一下 Vite 的零配置给我们带来的便利。

由于 Vite 底层会调用 CSS 预处理器的官方库进行编译,而 Vite 为了实现按需加载,并没有内置这些工具库,而是让用户根据需要安装。因此,我们首先安装 Sass 的官方库,安装命令如下:

pnpm i sass -D

安装好了之后,我们就可以直接用了

Sass配置全局变量

  1. 新建一个文件,命名为variable.scss文件。然后在vite.config.ts中进行如下修改
// vite.config.ts
import { normalizePath } from 'vite';
// 如果类型报错,需要安装 @types/node: pnpm i @types/node -D
import path from 'path';

// 全局 scss 文件的路径
// 用 normalizePath 解决 window 下的路径问题
const variablePath = normalizePath(path.resolve('./src/variable.scss'));


export default defineConfig({
  // css 相关的配置
  css: {
    preprocessorOptions: {
      scss: {
        // additionalData 的内容会在每个 scss 文件的开头自动注入
        additionalData: `@import "${variablePath}";`
      }
    }
  }
})

这样你就可以使用scss的全局变量了。相比手动引入方便很多

Vite配置CSS Module

CSS Modules 在 Vite 也是一个开箱即用的能力,Vite 会对后缀带有.module的样式文件自动应用 CSS Modules。接下来我们通过一个简单的例子来使用这个功能。

假设我们有一个scss文件为index.scss,现在我们将其命名为index.module.scss。然后我们修改下tsx中的文件的内容。

// index.tsx
import styles from './index.module.scss';
export function Header() {
  return <p className={styles.header}>This is Header</p>
};

可以看到,我们的CSS样式就已经生效了。p标签的类名就被处理成了哈希值的形式。

图片.png

我们可以在配置文件中的css.modules选项来配置CSS Modules的功能。

// vite.config.ts
export default {
  css: {
    modules: {
      // 一般我们可以通过 generateScopedName 属性来对生成的类名进行自定义
      // 其中,name 表示当前文件名,local 表示类名
      generateScopedName: "[name]__[local]___[hash:base64:5]"
    },
    preprocessorOptions: {
      // 省略预处理器配置
    }

  }
}

Vite配置PostCSS多浏览器适配方案

一般你可以通过 postcss.config.js 来配置 postcss ,不过在 Vite 配置文件中已经提供了 PostCSS 的配置入口,我们可以直接在 Vite 配置文件中进行操作。

首先,我们来安装一个常用的 PostCSS 插件——autoprefixer:

pnpm i autoprefixer -D

这个插件主要用来自动为不同的目标浏览器添加样式前缀,解决的是浏览器兼容性的问题。接下来让我们在 Vite 中接入这个插件:

// vite.config.ts 增加如下的配置
import autoprefixer from 'autoprefixer';

export default {
  css: {
    // 进行 PostCSS 配置
    postcss: {
      plugins: [
        autoprefixer({
          // 指定目标浏览器
          overrideBrowserslist: ['Chrome > 40', 'ff > 31', 'ie 11']
        })
      ]
    }
  }
}

配置完成之后,我们回到组件内部新增一个样式属性

.header{
    text-decoration:dashed;
}

你可以执行pnpm run build命令进行打包,可以看到产物中自动补上了浏览器前缀,如:

._header_kcvt0_1 {
  -webkit-text-decoration: dashed;
  -moz-text-decoration: dashed;
  text-decoration: dashed;
}