文章目录
一、参考
二、CSS 自动导入
- 导入 .css 文件将会把内容插入到 <style> 标签中
- 同时也带有 HMR 支持
- 也能够以字符串的形式检索处理后的、作为其模块默认导出的 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 文件
- 定义 example.module.css
/* example.module.css */
.red {
color: red;
}
- 引入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就是来解决这个问题的
大概说一下原理:
- module.css (module是一种约定, 表示需要开启css模块化)
- 他会将你的所有类名进行一定规则的替换(将footer 替换成 _footer_i22st_1)
- 同时创建一个映射对象{ footer: “_footer_i22st_1” }
- 将替换过后的内容塞进style标签里然后放入到head标签中 (能够读到index.html的文件内容)
- 将componentA.module.css内容进行全部抹除, 替换成JS脚本
- 将创建的映射对象在脚本中进行默认导出
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
-
如果使用的是单文件组件,可以通过 <style lang=“sass”>(或其他预处理器)自动开启。
-
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>
*/
],
};
});