🍎 系列文章
在系列中,将从零学习Vite,系统梳理 Vite 本身的知识,也包括 Vite 底层所使用的 Esbuild、Rollup 双引擎、Babel 编译工具链、模块规范标准等等构建生态。
前言
CSS 方案是前端工程化必不可缺的,在最原始的开发阶段都是手写原生的 CSS,但原生 CSS 存在浏览器兼容问题、开发体验差、样式污染、打包产物体积过大等诸多问题,因此社区出现了不少 CSS 工程化解决方案,有CSS 预处理器、CSS Modules、PostCSS 、CSS in JS 和 CSS 原子化框架,下面我们将在 Vite 中落地这些 CSS 工程化方案。
CSS 预处理器
这种方案自定义了一套语法来生成 CSS 的程序,让 CSS 可以像编程语言一样定义变量、写条件判断,代码混合,嵌套以及代码模块化。
Vite 本身对 CSS 各种预处理器(Sass、Less、Stylus)做了内置支持,我们无需做任何的配置就可以直接使用Sass、Less和Stylus,但是 Vite 为了实现按需加载,并没有内置这些工具库,需要我们根据自己的需求安装。这里我们以 Sass 预处理器为例,其他预处理器(Less、Stylus)如果有需要你可以去官方文档中查阅更多的配置项,安装 Sass 的官方库:
pnpm add -D sass
现在我们封装一个全局的主题色,新建 src/styles/variable.scss 文件,内容如下:
$theme-color: blue;
接着在 Vite 中进行自定义配置实现自动引入 variable.scss文件,在vite.config.ts 文件中增加如下的内容:
import path from 'path';
import { normalizePath } from 'vite';
// 全局scss文件的路径
// 用normalizePath 解决window下的路径问题
const variablePath = normalizePath(path.resolve('./src/styles/variable.scss'));
export default defineConfig({
// css相关的配置
css: {
preprocessorOptions: {
scss: {
// additionalData 的内容会在每个scss文件的开头自动注入
additionalData: `@import "${variablePath}";`
}
}
},
plugins: [react()],
})
新建 src/App.scss 文件,并在App.tsx 文件引用,内容如下:
// App.scss
.scss {
color: $theme-color;
}
// App.tsx
import './App.scss'
<h3 className='scss'> Sass 预处理器 </h3>
执行pnpm run dev
,然后到浏览器上查看效果:
CSS Modules
CSS Modules能将所有的类名和动画名称默认都有各自的作用域的 CSS 文件,这样就可以避免同名的情况下样式污染的问题。
CSS Modules 在 Vite 也是一个开箱即用的能力,Vite 会对后缀带有 .module
样式文件自动应用 CSS Modules。接下来我们来使用这个功能,新建 src/App.module.scss 文件,并在App.tsx 文件引用,内容如下:
// App.module.scss
.cssModules {
color: $theme-color;
}
// App.tsx
import styles from './App.module.scss';
<h3 className={styles.cssModules}> CSS Modules </h3>
到浏览器上查看效果,说明现在 CSS Modules 已经正式生效了,但语义化不友好,可以在配置文件中的css.modules选项来配置 CSS Modules 的功能,添加:
// vite.config.ts
export default {
css: {
modules: {
//其中,name表示当前文件名,local表示类名
generateScopedName: "[name]__[local]___[hash:base64:5]",
preprocessorOptions: {
//省略预处理器配置
}
},
}
}
再次访问页面,类名已经变成了我们自定义的形式:
PostCSS
PostCSS 是 CSS 后处理器,一个用 JavaScript 工具和插件转换 CSS 代码的工具,可以实现的功能非常丰富,比如将 px 转换为 rem,根据目标浏览器情况自动加上类似于-webkit-、-moz-、-o-的属性前缀等。
我们可以通过postcss.config.js来配置 postcss,也可以直接在 Vite 配置文件中进行操作。我们以安装 autoprefixer
这个常用的 PostCSS 插件为例,这个插件主要用来自动为不同的目标浏览器添加样式前缀,从而解决浏览器兼容性问题:
pnpm add -D autoprefixer
// vite.config.ts 增加下面的配置
import autoprefixer from'autoprefixer';
export default {
css: {
// PostCSS配置
postcss: {
plugins: [
autoprefixer({
// 指定目标浏览器
overrideBrowserslist: [
'Android 4.1',
'iOS 7.1',
'Chrome > 31',
'ff > 31',
'ie >= 11',
'last 2 versions',
],
grid: true,
})
]
}
}
}
配置完成后,我们在 App.scss 样式文件中添加一个新的 CSS 属性:
display: grid;
再次访问页面,自动添加了浏览器样式前缀:
除了 autoprefixer
插件,社区有不少的 PostCSS 插件,常见的插件有:
postcss-pxtorem
:用来将 px 转换为 rem 单位
postcss-preset-env
:解决最新的 CSS 语法兼容性问题
cssnano
:用来压缩 CSS 代码,跟常规的代码压缩工具不一样,它更加智能,比如提取一些公共样式进行复用、缩短一些常见的属性值等
关于 PostCSS 插件,这里给大家推荐一个站点:www.postcss.parts
CSS in JS
CSS in JS方案,顾名思义,这类方案可以实现直接在 JS 中写样式代码,基本包含 CSS 预处理器和CSS Modules 的各项优点,解决了开发体验和全局样式污染的问题。社区中有两款主流的CSS In JS方案 styled-components
和 emotion
,这里我们以为例进行配置使用:
plugins: [
react({
babel: {
// 加入babel插件
// 以下插件包都需要提前安装
// 当然,通过这个配置你也可以添加其它的Babel插件
plugins: [
// 适配styled-component
"babel-plugin-styled-components"
// 适配emotion
"@emotion/babel-plugin"
]},
// 注意:对于emotion,需要单独加上这个配置
// 通过`@emotion/react`包编译emotion中的特殊jsx语法
jsxImportSource: "@emotion/react"
}
)]
新建src/components/Button目录,并且新建 index.tsx 文件,代码如下:
// index.tsx
import styled from 'styled-components';
const Button = styled.button`
background: palevioletred;
color: white;
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border: 2px solid palevioletred;
border-radius: 3px;
`;
export default Button;
接着我们在 App.tsx 应用这个组件:
// App.tsx
import Button from './components/Button'
function App() {
return (
<Button>Primary</Button>
)
}
export default App
现在你可以执行 pnpm run dev
,然后到浏览器上查看效果:
CSS 原子化框架
CSS 原子化框架,如TailwindCSS、WindiCSS UnoCSS,通过类名来指定样式,将这些 class 样式简单化、单一化,大大简化了样式写法,提高了样式开发的效率,主要解决了原生 CSS开发体验的问题。
WindiCSS、UnoCSS可以作为 TailwindCSS 的替换方案,支持所有的 TailwindCSS 属性,实现了按需生成 CSS 类名的功能,属性化模式,变体组等等,但 WindiCSS 不再被积极维护了。这里我们以 UnoCSS 接入为例
首先安装 UnoCSS
pnpm add -D unocss
接着在配置文件中使用它:
// vite.config.ts
import UnoCSS from 'unocss/vite'
import { defineConfig } from 'vite'
export default defineConfig({
plugins: [
UnoCSS(),
],
})
创建 uno.config.ts
文件:
// uno.config.ts
import { defineConfig } from 'unocss'
export default defineConfig({
// ...UnoCSS options
})
将 virtual:uno.css
添加到你的主入口中:
// main.tsx
import 'virtual:uno.css'
这样我们就完成了 UnoCSS 在 Vite 中的接入,接下来我们在 App.tsx 中使用,添加代码如下:
<div className="m-1 color-blue">Hello UnoCSS</div>
当你启动项目之后可以看到 UnoCSS 的样式已经正常生效了。
后续
下一篇 学习Vite 第三章:如何处理各种静态资源的?