Vite 学习笔记(四):css模块化与静态资源处理与路径处理

css 模块化处理

vite 处理 css 的方式

webpack中,是通过 css-loaderstyle-loader 来处理css文件,那在 vite 中没有实现 loader机制,那它是如何处理 css 的呢?

我们先来举个例子:

js 复制代码
// index.css
body {
  background-color: aliceblue;
}


//main.js
import './index.css';

然后我们启动 vite 服务器:

我们发现了在head标签里面新建了一个style标签,.css文件里里面的内容,都被写到了标签里面。 大概我们能猜到,vitecss文件的处理,也是通过创建一个style标签,在页面引入样式文件这样子处理的。所以vite 天生就支持对 css 的直接处理。

但需要注意的是:vite 会把 css 转化为 js,设置 Content-Type:"text/javascript" 来告知浏览器应该以 JavaScript 的方式来解析 css

这样做的好处有三点:

  • 用于热更新
  • 用于css模块化。
  • 去除了第三方工具对css的处理,提高了编译性能

vite 对 css 的模块化处理

  • 为什么模块化?
    • 其根本原因就是为了解决协同开发,类名id等冲突引起样式覆盖的问题。
  • 如何解决?
    • 让每一个 css 文件为单独的一个模块,具有单独模块的作用域,这样能够保证我使用的类名的唯一性,独立性。

比如:我们创建两个模块化的css:a.module.cssb.module.css

js 复制代码
// a.module.css
.wrapper {
  font-size: 20px; 
  color: blue
}

// b.module.css
.wrapper {
  font-size: 100px; 
  color: red
}

//main.js
import AModuleCss from './a.module.css'
import BModuleCss from './b.module.css'

const ele1 = document.createElement('div');
ele1.className = AModuleCss.wrapper;
ele1.innerHTML = 'aaaaaa';
document.body.append(ele1)

const ele2 = document.createElement('div');
ele2.className = BModuleCss.wrapper;
ele2.innerHTML = 'bbbbb';
document.body.append(ele2)

我们看页面:

我们发现,同样的类名,却只对自己作用域下的元素生效

并且,样式会被处理成 key: value 的形式,以类名作为键名,处理后的类名作为键值

真实的类名会被替换成被处理后的类名:

css 模块化的原理

  1. 对 css 文件取名为 xxx.module.css (module是一种约定, 表示需要开启css模块化)
  2. 他会将你的所有类名进行一定规则的替换(将footer 替换成 _footer_i22st_1)
  3. 同时创建一个映射对象 { footer: "_footer_i22st_1" }
  4. 将替换过后的内容塞进 style 标签里然后放入到 head 标签中 (能够读到index.html的文件内容)
  5. 将 xx.module.css 内容进行全部抹除, 替换成JS脚本
  6. 将创建的映射对象在脚本中进行默认导出

vite 配置 css (模块化处理)

js 复制代码
import { defineConfig } from 'vite';
import postcssPresetEnv from 'postcss-preset-env';
export default defineConfig({
  ...
  envPrefix:'ENV_', // 配置环境变量前缀
  css:{
    modules:{
      // 展示模块化处理之后的key的展示形式,
      localsConvention:"camelCase",
      // 配置当前的模块化行为是模块化还是全局化
      // (有hash就是开启了模块化的一个标志, 因为他可以保证产生不同的hash值来控制我们的样式类名不被覆盖)
      scopeBehaviour:'local',
      // 生成的类名的规则(可以配置为函数, 也可以配置成字符串规则: <https://github.com/webpack/loader-utils#interpolatename>)
      generateScopedName:'[name]_[local]_[hash:5]'
      // 根据哈希加老类名生成文件新类名
      hashPrefix:'xxxxx',
      // 不想参与 css 模块化的文件路径
      globalModulePaths:[]
    }
})

vite 配置 css (预处理器配置)

js 复制代码
import { defineConfig } from 'vite';
import postcssPresetEnv from 'postcss-preset-env';
export default defineConfig({
  ...
  envPrefix:'ENV_', // 配置环境变量前缀
  css:{
    // 模块化处理配置
    modules:{},
    // 预处理器配置
    preprocessorOptions: {
        // 处理 less 
        less: { 
            math: "always",
            // 全局变量
            globalVars:{ 
                mainColor:"red"
            }
            // 更多请查看 https://lesscss.org/usage/#less-options-include-paths
        },
        // 处理 sass
        scss: {
        
        },
        // 开启css文件索引,以便于报错的时候能够找到源码位置
        devSourcemap:true, 
        postcss: {
            // postcssPresetEnv插件可以帮我们实现自动补全,语法降级等功能
            plugins:[postcssPresetEnv()]
        }
    }
})

静态资源处理

vite对静态资源是开箱即用的

处理图片

关于图片,我们只需要像往常一样写就可以了。比如我们生成一个img标签:

js 复制代码
// a.js
import indexImg from './assets/index.jpg'
const loadImg = ()=>{
  const img = document.createElement('img');
  img.src = indexImg
  img.setAttribute('width','80%')
  document.body.append(img)
}

export default loadImg // 在index.js中引入执行


//index.js
import loadImg from "./counter";
loadImg();

结果如下:

处理 svg

svg可以按照普通图片那样加载没问题,也可以按照svg方式加载。

  • 按照普通图片加载,即在 import 时,直接引入或者后面带上?url
js 复制代码
// a.js
import indexSvg from './assets/about.svg?url'
//或者
// import indexSvg from './assets/about.svg'
const loadImg = ()=>{
  const img = document.createElement('img');
  img.src = indexSvg
  img.setAttribute('width','80%')
  document.body.append(img)
}

export default loadImg // 在index.js中引入执行

// index.js
import loadImg from "./a";
loadImg();

结果如下:

但是以图片方式加载 svg 的缺点在于:不能修改它的颜色,所以 svg一般以下面这种方式使用

  • 按照 svg 加载,后面带上?raw
js 复制代码
// a.js
import indexSvg from './assets/about.svg?raw'
const loadImg = ()=>{
  document.body.innerHTML = indexSvg
}
export default loadImg // 在index.js中引入执行

// index.js
import loadImg from "./a";
loadImg();

结果如下:

变成了svg,我们就可以去改变颜色等属性了

路径处理

  • vite.base.config.js里面配置resolve.alias属性。和webpack很像
js 复制代码
export default defineConfig({
  ...
  resolve:{
    alias:{
      "@":path.resolve(__dirname, './src'),
      "@assets":path.resolve(__dirname, './src/assets'),
      "@component":path.resolve(__dirname, './src/component')
    }
  }
})
  • resolve.alias的原理:

比如在导入资源(比如图片)时,对于后端来说就是要去请求和加载这个静态资源文件,所以 Vite 服务器在后端路由中,先将请求的路径结合 vite.config.js 配置,将请求路径进行字符串替换,也就是将 @ 替换成 path.resolve 方法生成后的绝对路径,通过这个绝对路径找到对应的资源再将结果返回到浏览器。

相关推荐
小许_.5 天前
vite+vue3快速构建项目+router、vuex、scss安装
前端·css·vue3·vite·scss
唯之为之8 天前
vue3项目部署到Github
vue·github·pnpm·vue3·vite
williamdsy11 天前
【vite-plugin-vuetify】自动导入 vuetify 组件和指令
vite·plugin·vuetify·自动导入
whyfail16 天前
在 Vite 项目中自动为每个 Vue 文件导入 base.less
前端·less·vite
har01d18 天前
vue3,扫雷
开发语言·javascript·vue·ecmascript·vite
Vgbire25 天前
我把前端部署用户提醒做成了一个npm包
前端·webpack·性能优化·npm·vite·打包优化·webpack优化
威哥爱编程1 个月前
为什么用Vite框架?来看它的核心组件案例详解
前端·javascript·vite
站在顶峰看星星1 个月前
React + Vite项目别名配置
前端·webpack·typescript·vue·react·vite·angular
奶昔不会射手1 个月前
nuxt3学习
前端·vite·nuxt3
泡泡码客2 个月前
vite instanceof 失效
前端·javascript·webpack·vite