一、Vite css处理(模块module、sass less预处理、获取CSS代码字符串)

2023-11-10

一、参考

  1. vite 官网 CSS处理介绍

二、CSS 自动导入

  1. 导入 .css 文件将会把内容插入到 <style> 标签中
  2. 同时也带有 HMR 支持
  3. 也能够以字符串的形式检索处理后的、作为其模块默认导出的 CSS。

三、@import 内联和变基

Vite 通过 postcss-import 预配置支持了 CSS @import 内联,Vite 的路径别名也遵从 CSS @import。换句话说,所有 CSS url() 引用,即使导入的文件在不同的目录中,也总是自动变基,以确保正确性

Sass 和 Less 文件也支持 @import 别名和 URL 变基(具体请参阅 CSS Pre-processors)。

四、PostCSS

如果项目包含有效的 PostCSS 配置 (任何受 postcss-load-config 支持的格式,例如 postcss.config.js),它将会自动应用于所有已导入的 CSS。

请注意,CSS 最小化压缩将在 PostCSS 之后运行,并会使用 build.cssTarget 选项

五、CSS 模块化(.module.css)

任何以 .module.css 为后缀名的 CSS 文件都被认为是一个 CSS modules 文件

  1. 定义 example.module.css
/* example.module.css */
.red {
  color: red;
}
  1. 引入module css
import classes from './example.module.css'
document.getElementById('foo').className = classes.red

5.1 自定义 CSS module 导出命名规则

如果 css.modules.localsConvention 设置开启了 camelCase 格式变量名转换(例如 localsConvention: ‘camelCaseOnly’),你还可以使用按名导入。

// .apply-color -> applyColor
import { applyColor } from './example.module.css'
document.getElementById('foo').className = applyColor

5.2 为什么要有 CSS module

一句话概括:防止命名冲突

场景说明:

  • 一个组件最外层的元素类名一般取名 : wrapper
  • 一个组件最底层的元素类名我们一般取名: .footer

你取了footer这个名字, 别人因为没有看过你这个组件的源代码, 也可能去取名footer这个类名

最终可能会导致样式被覆盖(因为类名重复), 这就是我们在协同开发的时候很容易出现的问题

cssmodule就是来解决这个问题的

大概说一下原理:

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

5.3 CSS、SCSS module 案例

<template>
  <pre class>
    # 在vite中处理css

    vite天生就支持对css文件的直接处理

    1. vite在读取到main.js中引用到了Index.css
    2. 直接去使用fs模块去读取index.css中文件内容
    3. 直接创建一个style标签, 将index.css中文件内容直接copy进style标签里
    4. 将style标签插入到index.html的head中
    5. 将该css文件中的内容直接替换为js脚本(方便热更新或者css模块化), 同时设置Content-Type为js 从而让浏览器以JS脚本的形式来执行该css后缀的文件
  </pre>
</template>

<script>
import cssModule from  "./css.module.css";
import scssModule from "./sass.module.scss";

console.log("cssModule", cssModule);
debugger
console.log("scssModule", scssModule);

export  default  {
  mounted() {
    const div = document.createElement("div");
    div.innerHTML = `
      cssModule.footerContent
    `
    document.body.appendChild(div);
    div.className = cssModule['footer-content'];
  }
}
</script>

css.module.css

/*:root {*/
/*  --globalColor: red;*/
/*}*/
.footer {
  width: 200px;
  height: 200px;
  background-color: beige;
}

.footer-content {
  width: 200px;
  height: 200px;
  /*
  --globalColor 变量在 vite.config.js 中已经注入了全局文件
  additionalData: `@import "./src/assets/css/global.scss";`,
  */
  background-color: var(--globalColor);
}

sass.module.scss

.content {
  width: 800px;
  .main {
      background: green;
      padding: (100px / 2);
      margin: 100px / 2;
      background-color: red;
      filter: blur(100px);
      // 响应式布局, 左侧一个菜单栏 宽度自适应根据屏幕 30%
      // 400px ---> 父容器
      // 120px  200 * 0.3 -> 60  100px 240px 200px; preset-env会帮助我们做语法降级  vite内部会有一个主流浏览器的支持表
      width: clamp(100px, 30%, 200px);
      user-select: none; // 他在其他浏览器上不支持
  }
}
.main{
  color: blue;
}

六、CSS 预处理器 (sass less stylus)

Vite 也同时提供了对 .scss, .sass, .less, .styl 和 .stylus 文件的内置支持。没有必要为它们安装特定的 Vite 插件,但必须安装相应的预处理器依赖:(开箱即用)

# .scss and .sass
npm add -D sass

# .less
npm add -D less

# .styl and .stylus
npm add -D stylus
  1. 如果使用的是单文件组件,可以通过 <style lang=“sass”>(或其他预处理器)自动开启

  2. Vite 为 Sass 和 Less 改进了 @import 解析,以保证 Vite 别名也能被使用。另外,url() 中的相对路径引用的,与根文件不同目录中的 Sass/Less 文件会自动变基以保证正确性。

七、禁用 CSS 注入页面

自动注入 CSS 内容的行为可以通过 ?inline 参数来关闭。在关闭时,被处理过的 CSS 字符串将会作为该模块的默认导出,但样式并没有被注入到页面中。

import './foo.css' // 样式将会注入页面
import otherStyles from './bar.css?inline' // 样式不会注入页面

八、css sourcemap 配置

开发中,为了能快速定位到 CSS的源码位置,可以开启 CSS 的 sourcemap, 修改vite.config.js配置

import { fileURLToPath, URL } from 'node:url';

import { defineConfig, loadEnv } from 'vite';
import vue from '@vitejs/plugin-vue';
import basicSsl from '@vitejs/plugin-basic-ssl';
// https://github.com/antfu/unplugin-auto-import
import AutoImport from 'unplugin-auto-import/vite';
/* 
  https://github.com/antfu/unplugin-vue-components
  On-demand components auto importing for Vue.(自动将组件引入到Vue中,不用明确代码引入了)
*/
import Components from 'unplugin-vue-components/vite';
// https://www.npmjs.com/package/vite-plugin-pages
import Pages from 'vite-plugin-pages';
import Unocss from 'unocss/vite';
/* 
  https://www.npmjs.com/package/vite-plugin-vue-devtools
  提高Vue 的调试工具
*/
import VueDevTools from 'vite-plugin-vue-devtools';
/* 
  https://github.com/xxholly32/vite-plugin-custom-attr#readme
  Set default values for tags.(设置标签的默认值)
*/
import CustomProps from 'vite-plugin-custom-attr';

import { ElementPlusResolver } from 'unplugin-vue-components/resolvers';

// https://vitejs.dev/config/
// export default defineConfig({
//   plugins: [vue()],
// })

export default defineConfig(function (options) {
  // console.log(arguments) // 只有一个参数值
  // console.log(options) //{ mode: 'development', command: 'serve', ssrBuild: false }
  const { mode, command, ssrBuild } = options;
  const env = loadEnv(mode, process.cwd(), '');

  // process.env = { ...process.env, ...loadEnv(mode, process.cwd()) };
  // const publicPath = process.env.VITE_BASE_URL;

  return {
    /**
     * 在生产中服务时的基本公共路径。
     * @default '/'
     */
    // base: '/huangbiao/', // 默认是 '/'
    // publicDir: 'public',
    // cacheDir: 'node_modules/.vite',
    // envDir: 'root', // 用于加载 .env 文件的目录。可以是一个绝对路径,也可以是相对于项目根的路径。
    // envPrefix: 'VITE_', // 以 envPrefix 开头的环境变量会通过 import.meta.env 暴露在你的客户端源码中
    resolve: {
      /* 路径使用别名 */
      alias: {
        '@': fileURLToPath(new URL('./src', import.meta.url)),
      },
      /* 
      引入文件的后缀名称,可以省略
      如果出现同名,按照数组加载的优先顺序
      */
      extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue'],
    },
    // 服务配置
    server: {
      host: '0.0.0.0',
      port: 3333, // 端口号
      open: true, // 自动在浏览器打开
      // https: true,// 是否开启 https
      // http2: true,// 建议使用 http2, 是否开启 https
      fs: {
        // 可以为项目根目录的上一级提供服务
        allow: ['..'],
      },
      proxy: {
        '^/mockapi': {
          target: 'http://10.32.38.100:3000/',
          changeOrigin: true,
        },
        '^/ctm05zjaefs/': {
          target: 'http://localhost:39696',
          changeOrigin: true,
        },
        // 带选项写法:http://localhost:5173/api/bar -> http://jsonplaceholder.typicode.com/bar
        '/api': {
          target: 'http://jsonplaceholder.typicode.com',
          changeOrigin: true,
          rewrite: (path) => path.replace(/^\/api/, ''),
        },
      },
    },
    // css 处理
    css: {
      preprocessorOptions: {
        scss: {
          /* .scss全局预定义变量,引入多个文件 以;(分号分割)*/
          additionalData: `@import "./src/assets/css/global.scss";`,
        },
      },
      // 可以查看 CSS 的源码
      devSourcemap: true,
    },
    //  生产环境
    build: {
      //指定输出路径
      assetsDir: './static',
      // 指定输出文件路径
      outDir: 'dist',
      sourcemap: true, // 构建后是否生成 source map 文件。如果为 true,将会创建一个独立的 source map 文件。
      // 代码压缩配置
      terserOptions: {
        // 生产环境移除console
        compress: {
          drop_console: true,
          drop_debugger: true,
        },
      },
    },
    plugins: [
      VueDevTools(),
      vue(),
      basicSsl(),
      // Pages({
      //   extensions: ['vue', 'md'],
      //   dirs: [
      //     // basic
      //     { dir: 'src/pages/**', baseRoute: '.' },
      //     // // features dir for pages
      //     // { dir: 'src/features/**/pages', baseRoute: 'features' },
      //     // // with custom file pattern
      //     // { dir: 'src/admin/pages', baseRoute: 'admin', filePattern: '**/*.page.*' },
      //   ],
      // }),
      // Pages({
      //   extensions: ['vue', 'md'],
      // }),

      // https://github.com/JohnCampionJr/vite-plugin-vue-layouts
      Pages({
        dirs: 'src/pages',
        exclude: ['**/comp/*.vue'],
        extensions: ['vue'], // ['vue', 'ts', 'js'],
        extendRoute(route, parent) {
          console.log('route, parent', route, parent);
          /* 
          打印的内容如下
          route, parent {
            name: 'Welcome',
            path: '/welcome',
            component: '/src/pages/Welcome.vue',
            customBlock: undefined,
            props: true
          }
          */
          if (route.path === '/') {
            //给默认路由加一个redirect,默认为index.vue
            return {
              ...route,
              redirect: 'page1',
              meta: {
                auth: true,
              },
            };
          } else {
            return route;
          }
        },
      }),
      Unocss({
        // mode: 'shadow-dom',
        shortcuts: [ // 自定义组合样式,即 样式 cool-blue 代表`bg-blue-500 text-white` 的组合
          { 'cool-blue': 'bg-blue-500 text-white' }, 
          { 'cool-green': 'bg-green-500 text-black' }
        ],
      }),
      AutoImport({
        imports: [
          // 需要自动导入的插件,自定义导入的API
          'vue',
          'vue-router',
          'pinia',
        ],
        dts: 'src/types/auto-import.d.ts', // 指明 .d.ts 文件的位置和文件名
        resolvers: [ElementPlusResolver()],
      }),
      Components({
        resolvers: [ElementPlusResolver()],
      }),
      /* 
      // Set default values for tags.
      CustomProps({
        tags: {
          "h1" : {
            style: "font-size: 2rem;"
          },
          "el-button" : {
            type: "success",
            plain: true,
          }, 
        }
      })
      
      <template>
        <h1>change style</h1>
        <el-button>no type</el-button>
        <el-button type="primary">type primay</el-button>
      </template>
      转为
      <template>
        <h1 style="font-size: 2rem;">change style</h1>
        <el-button type="success" plain>no type</el-button>
        <el-button type="primary" plain>type primay</el-button>
      </template>
      */
    ],
  };
});

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

一、Vite css处理(模块module、sass less预处理、获取CSS代码字符串) 的相关文章

  • 我们可以在displaytag中使用rowspan和colspan吗?

    我必须创建一个表 其结构是这样的 col1 col2 col3 col4 col3 1 col3 2 是否可以使用显示标签创建这样的数据网格 查看装饰器示例 http displaytag sourceforge net 1 2 tut d
  • ckeditor 数据未通过 jQuery 验证进行验证

    我知道有很多关于此的问题 但我无法让它在我的一生中发挥作用 我尝试了几种解决方案 包括this http devlog waltercruz com usando ckeditor e jquery validate juntos 第二个答
  • SVG 内部跨度与文本不在同一行

    我在一个跨度内有一个 SVG 文件 同时包含文本 文本和 SVG 的高度相同 但是 SVG 与文本不在同一行 相关jsfiddle https jsfiddle net tcrnjd53 https jsfiddle net tcrnjd5
  • 您可以使用 CSS 或 JavaScript 创建渐变为不透明的渐变吗?

    WebKit 引入了创建 CSS 渐变的功能 例如 使用以下代码 webkit gradient linear left top left bottom from fff to 000 但是 是否可以使用 CSS 实现不透明度渐变 我希望渐
  • 导航栏是垂直的而不是水平的

    div div
  • 超大图像缩小后变得模糊

    这是我第一次尝试响应式设计 所以如果这是一个愚蠢的简单问题 请原谅 我创建了一个图像并将其最大宽度设置为不大于图像的实际宽度 因为我知道放大图像会导致模糊不清 我有点困惑的是 当我缩小窗口并且图像开始缩小时 它也变得模糊 这是正确的行为吗
  • 当您点击外部时,Bootstrap 3 Mobile 导航不会崩溃

    当我单击 触摸菜单外部时 我的 Bootstrap 3 移动菜单确实会折叠 我可以想出一个解决问题的方法 document on touchstart click html not nav function navbar collapse
  • Bootstrap 居中 div 内的文本左对齐

    我有一段 4 行诗 位于居中的 div 中 因为它是诗歌 所以我需要将 4 行左对齐 但不要对齐到 div 的左侧 这是它的居中方式 Lorem ipsum dolor sit amet onsectetur adipisicin Dolo
  • 更改 Angular 对话框的背景颜色

    我正在尝试更改对话框背景 无需触摸style css file 正如其他一些答案所说 有很多方法可以设置对话框样式 1 此解决方案适用于宽度和高度 但透明背景被 忽略 this dialog open DialogComponent dis
  • 为什么table-layout:fixed会影响父元素的宽度?

    有人可以解释为什么我的div with table layout fixed正在改变其父元素的宽度 body在本例中 使其在不应该是 100 的情况下达到 100 因为它已经定位了 body border 2px solid red hei
  • 如何使用固定宽度的卡片制作卡片组?

    我想做一个响应式的卡牌 https getbootstrap com docs 4 0 components card card decks使用引导4固定宽度卡片 https getbootstrap com docs 4 0 compon
  • Bootstrap 按钮的检查状态

    我想在 Bootstrap 3 0 2 中设置组复选框的选中状态 docs http getbootstrap com javascript buttons html div class btn group div
  • 如何为平板电脑和 iPhone 制作样式表

    我认为样式表上的链接目标将使我的 css 文件仅在平板电脑或 iPhone 上加载时加载 但我试图隐藏的元素仍然存在 我目前正在使用 media handheld 有太多的移动设备型号需要为其编写样式表 你最好根据以下内容调整你的CSS屏幕
  • 动画和过渡的组合无法正常工作

    我一直在尝试添加一些基本的 CSS3 动画 目标是在按钮的单击事件上切换类 并根据添加的类对 div 进行动画处理 该代码对于 Firefox 中切换的第一次迭代完美运行 但对于 Chrome 等其他浏览器以及 Firefox 中的下一次迭
  • 设置绝对仓位和保证金

    我想设置一个元素的position to absolute并有一个margin bottom 但似乎margin bottom没有效果 HTML div div CSS container border 1px solid red posi
  • Ace Editor 自动完成和多种语言

    如何为 Ace 编辑器创建自动完成功能以及如何突出显示 php 中的 html javascript 和 csshttp ace ajax org http ace ajax org
  • 如何使弹出窗口溢出:在溢出内可见:自动上下文

    我有一个 div 列表 如果超过父框 overflow x 应该滚动 并且在悬停时 我想看到一个弹出窗口 我的问题是 如果我将鼠标悬停在任何子 div 上 弹出窗口将被考虑用于溢出计算 但我只想让它在所有内容之上可见 而不是使其扩展滚动区域
  • IE8 - 隐藏 div 内的表单,返回键不再起作用

    我有一个登录表单 位于带有 display none 的 div 中 然后我使用 jquery 淡入表单 但 Enter Return 键不再提交表单 如果我将显示更改为阻止 则效果很好 此问题仅存在于 IE 中 有任何想法吗 这是一个不起
  • JQuery 设置动态最大宽度

    我不太擅长 jQuery 因此完整的代码解决方案将是理想的选择 该函数将 获取浏览器屏幕的 70 宽度 将该宽度转换为其相应的 px 值 设置最大宽度 mainContainer使用从转换 计算中获得的值 这是我要设置的容器的 CSS 样式
  • IE10 中的弹性盒

    我试图让弹性框在 IE10 中工作 但它不起作用 Safari Chrome 和 Firefox 工作正常 但 IE10 不工作 有人知道答案吗 代码笔 http codepen io anon pen vcEGH http codepen

随机推荐

  • 【100%通过率 】【华为OD机试 c++ 】不含 101 的数【2023 Q1

    华为OD机试 题目列表 2023Q1 点这里 2023华为OD机试 刷题指南 点这里 题目描述 小明在学习二进制时 发现了一类不含 101的数 也就是 将数字用二进制表示 不能出现 101 现在给定一个整数区间 l r 请问这个区间包含了多
  • 【python 多线程存数据lock(锁)】

    多线程存数据不会数据丢失 案例一 这里只是简单的线程池 import os from concurrent futures import ThreadPoolExecutor from time import perf counter im
  • PTA-计算工资

    计算工资 某公司员工的工资计算方法如下 一周内工作时间不超过40小时 按正常工作时间计酬 超出40小时的工作时间部分 按正常工作时间报酬的1 5倍计酬 员工按进公司时间分为新职工和老职工 进公司不少于5年的员工为老职工 5年以下的为新职工
  • TypeScript 之类型判断

    在使用 Angular 做项目的时候 对 TypeScript 的类型判断不太熟练 为了方便查找 特意对 TypeScript 的类型判断做了简单梳理 文章只是 TS 官网的内容摘要 没有高深的知识 想要深入学习 TS 还要看官网文档 基础
  • 18M 超轻量系统开源

    图像识别作为深度学习算法的主流实践应用方向 早已在生活的各个领域发挥作用 如安全检查和身份核验时的人脸识别 无人货架和智能零售柜中的商品识别 这些任务背后的关键技术都在于此 图1 PP ShiTu应用于商品识别效果示意 开发者应用展示 然而
  • JMeter压测原则之独立部署监控

    无论是用哪种压测工具 我们都会比较关心压测工具所在机器的的系统资源占用情况 毕竟很多人压着压着 压力机出现性能瓶颈了还不知道 并且还错误的评估成是被测系统的性能问题 很多初学者好像都犯过这种尴尬的错误 文章分成三个部分说明 为什么说Perf
  • a &a &a[0]之间的区别和联系

    数组中 a为数组的首地址 a 0 为数组第一个元素的地址 所以 a a 0 但是 a又是什么东西呢 我们来做下面的代码测试 include
  • Binary operator ‘==‘ cannot be applied to operands of type ‘Int‘ and ‘[Int]‘

    等号两边数据类型不一致进行比较报错 Binary operator cannot be applied to operands of type Int and Int 这个提示也挺明确 二元运算符 两边不能使用 Int 和 Int 写代码时
  • c++ socket、 listen、accept、recv 、send、 connect函数记录

    文章目录 socket bind 和connect 函数 listen 和accept 函数 send recv read 和write 函数 TCP客户端 Tcp服务端 socket int socket int domain int t
  • 如何进行代码审查?

    如何review开发人员的代码 前置的一些概念 review级别 参与人身份和方式不同划分 相关开发自己看代码 非正式会议 开发人员组内 相关开发 直接上级 相关开发 直接上级 总监 1 团队review制度 团队内根据实际情况规定流程 在
  • 与机器学习相关的数学家,你认识几个?

    机器学习 需要一定的数学基础 也需要一定的代码能力 我们发布了一篇 机器学习的数学基础 里面有很多数学公式是数学家的名字命名的 然而 好多人不知道那些数学家长什么样子 于是 我们搜集了十位数学家的资料 排名不分先后 看看大家能从图片中叫出几
  • Vue_test

    文章目录 vue test笔记 1 脚手架文件结构 2 关于不同版本的Vue 3 vue config js配置文件 4 ref属性 5 配置项props 6 mixin 混入 7 插件 8 scoped样式 9 总结TodoList案例
  • Neo4js安装报错:未能加载指定的模块“\Neo4j-Management.psd1”

    情形如下 解决方法 更改bin neo4j ps1文件里Import Module PSScriptRoot Neo4j Management psd1 为绝对路径
  • Mybatis-generator代码自动生成(包含swagger注解,bean中文注释,service接口,serviceImpl实现类)

    Mybatis generator代码自动生成 包含swagger注解 bean中文注释 service接口 serviceImpl实现类 Dao接口是继承tkmybatis 简介 项目地址 代码生成步骤 代码生成图示 简介 由于平时老是需
  • 公众号上传临时素材获取media_id

    公众号上传临时素材获取media id java语言 更新于2018 01 15 public class Util private static final String UPLOAD URL https api weixin qq co
  • Linux驱动系列-PWM驱动

    转自 嵌入式系统研发 1 概述 本文主要讲述了Linux的PWM驱动框架 实现方法 驱动添加方法和调试方法 示例Linux内核版本 6 2 8 2 原理 PWM是Pulse Width Modulation的简称 中文译作脉冲宽度调制 作为
  • Vue实现底部对话框

    效果 手机上的效果 电脑上的效果 代码 App vue
  • 手写一个简化版 vuepress 需要知道什么?

    自实现 vuepress 效果图如下 首先我们来看看 vuepress 是怎么工作的 1 全局安装 vuepress npm install g vuepress 2 运行编写好的 docs 文件 编译后的浏览器显示文档网页 vuepres
  • 谭浩强C++课后习题20——找二维数组的鞍点

    谭浩强C 课后习题20 找二维数组的鞍点 题目描述 找出一个二维数组中的鞍点 即该位置上的元素在该行上最大 在该列上最小 也有可能没有鞍点 一个二维数组最多只有一个鞍点 也有可能没有 算法思路 先找出一行中值最大的元素 然后检查它是否是该列
  • 一、Vite css处理(模块module、sass less预处理、获取CSS代码字符串)

    文章目录 一 参考 二 CSS 自动导入 三 import 内联和变基 四 PostCSS 五 CSS 模块化 module css 5 1 自定义 CSS module 导出命名规则 5 2 为什么要有 CSS module 5 3 CS