Vite中css模块化的处理

这些全都是在node端实现的。

  1. vite在读取到main.js中引用到的css文件
  2. 使用fs模块去读取css文件的内容
  3. 然后创建一个style标签,文件的内容注入到这个标签里面
  4. 将这个style标签插入到index.html的head标签里面
  5. 原本的css内容会被替换成js脚本,方便后续的热更新
1
2
3
4
5
html, body {
width: 100%;
height: 100%;
background: #646cff;
}

以上便是vite处理css文件的流程

为什么要进行模块化的处理,因为在实际开发中,对于一些样式类的命名,在团队中可能你开发了一个组件,写了一个样式类名叫
.content
在协同开发中,另一个人也写了一个样式类名叫.content。这样就造成了样式冲突。

下面来介绍模块化的处理,在vue模板文件中,我们常常会这样写

1
2
3
<template></template>
<script></script>
<style scope></style>

这个scope就是限制了样式的作用域,只在当前组件中生效,这样就不会影响到其他组件的样式。
就是利用cssModule这个特性来实现的。

  1. module.css是一种约定,给样式文件带上一个module就说明开启了css模块化。
  2. 开启之后,vite会将这个文件里面的所有类名通过一个hash算法生成一个唯一的类名,比如.content会被转换成.content_1q2w3e4r5t6y7u8i9o0p这样的类名。
  3. 并且会创建一个映射对象{content: content_1q2w3e4r5t6y7u8i9o0p}
  4. 同样的,这些个module.css、module.less、module.scss里面的内容都会被替换成js脚本,方便后续的热更新。
  5. 3 中所创建的映射对象会被js脚本默认导出,这样我们就可以在vue模板文件中使用这个对象了。

示例工程实践

在项目根目录下的src文件夹中创建一个component_test文件夹。
目录结构如下

1
2
3
4
5
6
7
src
├── component_test
│ ├── styles
│ │ └── componentACSS.module.css
│ │ └── componentBCSS.module.css
│ └── ComponentA.js
│ └── ComponentB.js

内容如下

1
2
3
4
5
6
7
8
9
.card{
background-color: #f4f4f4;
width: 400px;
margin: 20px auto;
padding: 20px;
border-radius: 10px;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
height: 100px;
}
1
2
3
4
5
6
7
8
9
.card{
background-color: darkred;
width: 400px;
margin: 20px auto;
padding: 20px;
border-radius: 10px;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
height: 100px;
}
1
2
3
4
5
import componentACSS from './styles/componentACSS.module.css';
const div = document.createElement('div');
console.log(componentACSS);
document.body.appendChild(div);
div.className = componentACSS.card;
1
2
3
4
5
import componentBCSS from './styles/componentBCSS.module.css';
const div = document.createElement('div');
console.log(componentBCSS)
document.body.appendChild(div);
div.className = componentBCSS.card

别忘记在main.js中引入这两个组件

检验

在下面可以看到,两个组件的样式都是独立的,不会互相影响,这就是css模块化的处理。并且可以看到,这个被哈希化的css样式类名
被映射到js脚本中并被默认导出了。

vite中css模块化的处理

这里直接把一个基础的示例配置文件放出来,这个基础配置是vite环境变量的配置那片文章延申出来的

具体的github项目地址在这里,对应目录下的是test-vite这个工程,后续学习我应该会继续扩展这个工程。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// 基础配置
import {defineConfig} from 'vite'

export default defineConfig({
optimizeDeps: {
exclude: [],
},
// 环境变量前缀
envPrefix: 'ENV_',
// 对css的行为进行配置
css: {
modules: {
localsConvention: "camelCaseOnly", // 修改生成的配置对象的key的展示形式,是中划线还是驼峰命名
scopeBehaviour: "local", // 修改生成的类名的行为,是局部的还是全局的global代表关闭css模块化
// generateScopedName:"[name]_[local]_[hash:5]", // 修改生成的类名的格式
// 这个属性可以配置成函数,也可以配置成字符串规则
// generateScopedName: (name, filename, css) =>{
// console.log("name",name,"filename",filename,"css",css)
// return `${name}_${Math.random().toString(36).substring(3,8)}`
// }
hashPrefix: "hello", // 生成的hash会根据css的类名 + 一些其他的字符串去生成hash串,这个配置会参与到hash生成算法中,简而言之提高hash的复杂度
globalModulePaths: [], //代表不参与到css模块化的路径
},
preprocessorOptions: { // key + config key代表预处理器的名
less: {
math: "always", // 是否开启数学运算
globalVars: {
primaryColor: "#1890ff",
successColor: "#52c41a",
warningColor: "#faad14",
errorColor: "#f5222d",
defaultColor: "#d9d9d9",
}, // 全局变量
}
},
devSourcemap: true //开启css的sourceMap(文件索引)
}
})