diff --git a/README.ZH-CN.md b/README.ZH-CN.md index fd7628d..e1f04cf 100644 --- a/README.ZH-CN.md +++ b/README.ZH-CN.md @@ -10,6 +10,21 @@ * 🌊 TODO * ⛰ TODO +## Core Process + +```mermaid +graph LR +A[vite] -- plugin --> B((unplugin-vue-cssvars)) +B -- 1.预处理项目中css文件 --> C(生成CSS Module Map获得包含 v-bind 的 css 代码等信息) +C --> D +B -- 2.基于步骤1与vue编译器 --> D(根据 SFC 组件信息获得其引用的 CSS Module) +D --> E +B -- 3.基于vue编译器 --> E(提取 SFC 组件变量) +E --> F +B -- 4.注入提升代码 --> F(匹配CSS Module 与 SFC 变量注入代码) +F --> G((vitejs/plugin-vue)) +``` + ## Install ```bash @@ -108,31 +123,142 @@ build({ ```typescript export interface Options { /** - * Provide path which will be transformed - * + * 需要转换的路径,默认是项目根目录 * @default process.cwd() */ rootDir?: string /** - * RegExp or glob to match files to be transformed + * 需要转换的文件名后缀列表(目前只支持.vue)RegExp or glob */ include?: FilterPattern /** - * RegExp or glob to match files to NOT be transformed + * 不需要转换的文件名后缀列表(目前只支持.vue)RegExp or glob */ exclude?: FilterPattern /** - * unplugin-vue-cssvars depends on the vue compiler, - * there may be duplicate css after packaging, here we clear it + * `unplugin-vue-cssvars` 只是做了样式提升注入,其编译依旧依赖于 `@vue/compiler-dom` + * 在某些时候可能会生成重复的 `css` 代码(一般不会,因为打包时会将重复代码删除),例如 `vite` 中关闭构建 + * 时压缩选项,`revoke` 则可以在打包时将注入的代码删除 */ revoke?: boolean } ``` -## Tips TODO -### 转换分析时的约定规则 -1. sfc 中,如果 @import 指定了后缀,则根据后缀的文件进行转换分析,否则根据当前 script 标签的 lang 属性(默认css)进行转换分析。 -2. css中规则:css文件只能引用 css 文件,只会解析 css 后缀的文件 -3. scss、less、stylus 中规则:scss、less、stylus文件可以引用 css 文件、以及对应的scss或less文件或stylus文件,则对同名文件的css文件和对应的预处理器后缀文件进行转换分析 -## Thanks TODO +### 关于 revoke 详细说明 +有如下两个文件 `App.vue` 和 `test.css` +```` + + + + + + +```` +```` +/** test.css **/ +div { + color: v-bind(color); +} +```` +当未使用 `unplugin-vue-cssvars` 使用 `vite` 构建后 +```` +/** test.css **/ +div[data-v-2e7c9788] { + color: var(--8bcabd20); +} +```` +其中 `color: var(--8bcabd20);` 的哈希并不会出现在组件打包产物中,因为 `vue` 不支持在文件中使用 `v-bind`。 +当使用 `unplugin-vue-cssvars` 使用 `vite` 构建后(`minify: false`) +```` +/** test.css **/ +div[data-v-1dfefb04] { + color: var(--516b0d4a); +} + +/* created by @unplugin-vue-cssvars */ +/* */ +div[data-v-1dfefb04]{color:var(--516b0d4a)} +/* */ +```` +可以看到通过 `unplugin-vue-cssvars` 会生成注入代码,并且依赖于 `@vue/compiler-dom`,其哈希值能够出现在组件打包产物中。 +但是观察发现,这段代码是重复的。因此,开启 `revoke` 选项,将移除重复代码 +```` +/** test.css **/ +div[data-v-1dfefb04] { + color: var(--516b0d4a); +} +```` + +## Tips + +### ● 转换分析时的约定规则 +1. `sfc` 中,如果 `@import` 指定了后缀,则根据后缀的文件进行转换分析,否则根据当前 `script` 标签的 `lang` 属性(默认 `css` )进行转换分析 +2. `css` 中规则:`css` 文件只能引用 `css` 文件,只会解析 `css` 后缀的文件。 +3. `scss`、`less`、`stylus` 中规则:`scss`、`less`、`stylus文件可以引用` `css` 文件、以及对应的 `scss` 或 `less` 文件或 `stylus` 文件, +则对同名文件的 `css` 文件和对应的预处理器后缀文件进行转换分析。 + +### ● sfc 中变量提取规则 +1. 对于 `script setup`, `unplugin-vue-cssvars` 会提取所有变量进行匹配。 +```` + +```` +2. 对于 `composition api`, `unplugin-vue-cssvars` 会提取 `setup` 函数返回变量进行匹配。 +```` + +```` +3. 对于 `options api`, `unplugin-vue-cssvars` 会提取 `data` 函数返回变量进行匹配。 +```` + +```` +4. 对于普通的 `script`, `unplugin-vue-cssvars` 会提取所有变量进行匹配。 +```` + +```` + +### ● sfc 中变量冲突规则 +1. `sfc` 中有 `options api` 与 `composition api`, 所有变量会进行合并 +变量出现冲突以后面出现的(比如先写了 `options api`,后写 `composition api`,以 `composition api` 优先)优先 +2. `sfc` 中有 `script setup`、`options api` 与 `composition api`, 所有变量会进行合并,变量出现冲突以`script setup`优先 +3. `sfc` 中普通的 `script`,不会与`options api` 、 `composition api`同时存在 +4. `sfc` 中普通的 `script`若存在,则必存在`script setup` +5. `sfc` 中普通的 `script`与 `script setup` 所有变量会进行合并,变量出现冲突以`script setup`优先 + +### ● 样式提升后的优先级 +1. 从 `sfc` 开始,分析 `style` 标签中引用的 `css` 文件,按照 `css` 文件中的引用顺序,深度优先依次提升并注入到 `sfc` 中。 +2. 注入到 `sfc` 后,其优先级完全由 `@vue/compiler-dom` 的编译器决定。 + +## Thanks +* [vue](https://github.com/vuejs/core) +* [vite](https://github.com/vitejs/vite) +* [unplugin](https://github.com/unjs/unplugin) \ No newline at end of file diff --git a/README.md b/README.md index 2b4d4f3..ead8355 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # unplugin-vue-cssvars 🌀 A vue plugin that allows you to use vue's CSSVars feature in css files -English | [中文](https://github.com/baiwusanyu-c/unplugin-vue-cssvars/blob/master/README.ZH-CN.md) +[English](https://github.com/baiwusanyu-c/unplugin-vue-cssvars/blob/master/README.md) | 中文 ## Feature (TODO) @@ -10,6 +10,21 @@ English | [中文](https://github.com/baiwusanyu-c/unplugin-vue-cssvars/blob/mas * 🌊 TODO * ⛰ TODO +## Core Process + +```mermaid +graph LR +A[vite] -- plugin --> B((unplugin-vue-cssvars)) +B -- 1.预处理项目中css文件 --> C(生成CSS Module Map获得包含 v-bind 的 css 代码等信息) +C --> D +B -- 2.基于步骤1与vue编译器 --> D(根据 SFC 组件信息获得其引用的 CSS Module) +D --> E +B -- 3.基于vue编译器 --> E(提取 SFC 组件变量) +E --> F +B -- 4.注入提升代码 --> F(匹配CSS Module 与 SFC 变量注入代码) +F --> G((vitejs/plugin-vue)) +``` + ## Install ```bash @@ -90,7 +105,7 @@ module.exports = {
-Esbuild +esbuild ```ts // esbuild.config.js @@ -108,27 +123,142 @@ build({ ```typescript export interface Options { /** - * Provide path which will be transformed - * + * 需要转换的路径,默认是项目根目录 * @default process.cwd() */ rootDir?: string /** - * RegExp or glob to match files to be transformed + * 需要转换的文件名后缀列表(目前只支持.vue)RegExp or glob */ include?: FilterPattern /** - * RegExp or glob to match files to NOT be transformed + * 不需要转换的文件名后缀列表(目前只支持.vue)RegExp or glob */ exclude?: FilterPattern /** - * unplugin-vue-cssvars depends on the vue compiler, - * there may be duplicate css after packaging, here we clear it + * `unplugin-vue-cssvars` 只是做了样式提升注入,其编译依旧依赖于 `@vue/compiler-dom` + * 在某些时候可能会生成重复的 `css` 代码(一般不会,因为打包时会将重复代码删除),例如 `vite` 中关闭构建 + * 时压缩选项,`revoke` 则可以在打包时将注入的代码删除 */ revoke?: boolean } ``` +### 关于 revoke 详细说明 +有如下两个文件 `App.vue` 和 `test.css` +```` + + + + + + +```` +```` +/** test.css **/ +div { + color: v-bind(color); +} +```` +当未使用 `unplugin-vue-cssvars` 使用 `vite` 构建后 +```` +/** test.css **/ +div[data-v-2e7c9788] { + color: var(--8bcabd20); +} +```` +其中 `color: var(--8bcabd20);` 的哈希并不会出现在组件打包产物中,因为 `vue` 不支持在文件中使用 `v-bind`。 +当使用 `unplugin-vue-cssvars` 使用 `vite` 构建后(`minify: false`) +```` +/** test.css **/ +div[data-v-1dfefb04] { + color: var(--516b0d4a); +} + +/* created by @unplugin-vue-cssvars */ +/* */ +div[data-v-1dfefb04]{color:var(--516b0d4a)} +/* */ +```` +可以看到通过 `unplugin-vue-cssvars` 会生成注入代码,并且依赖于 `@vue/compiler-dom`,其哈希值能够出现在组件打包产物中。 +但是观察发现,这段代码是重复的。因此,开启 `revoke` 选项,将移除重复代码 +```` +/** test.css **/ +div[data-v-1dfefb04] { + color: var(--516b0d4a); +} +```` + +## Tips + +### ● 转换分析时的约定规则 +1. `sfc` 中,如果 `@import` 指定了后缀,则根据后缀的文件进行转换分析,否则根据当前 `script` 标签的 `lang` 属性(默认 `css` )进行转换分析 +2. `css` 中规则:`css` 文件只能引用 `css` 文件,只会解析 `css` 后缀的文件。 +3. `scss`、`less`、`stylus` 中规则:`scss`、`less`、`stylus文件可以引用` `css` 文件、以及对应的 `scss` 或 `less` 文件或 `stylus` 文件, + 则对同名文件的 `css` 文件和对应的预处理器后缀文件进行转换分析。 + +### ● sfc 中变量提取规则 +1. 对于 `script setup`, `unplugin-vue-cssvars` 会提取所有变量进行匹配。 +```` + +```` +2. 对于 `composition api`, `unplugin-vue-cssvars` 会提取 `setup` 函数返回变量进行匹配。 +```` + +```` +3. 对于 `options api`, `unplugin-vue-cssvars` 会提取 `data` 函数返回变量进行匹配。 +```` + +```` +4. 对于普通的 `script`, `unplugin-vue-cssvars` 会提取所有变量进行匹配。 +```` + +```` + +### ● sfc 中变量冲突规则 +1. `sfc` 中有 `options api` 与 `composition api`, 所有变量会进行合并 + 变量出现冲突以后面出现的(比如先写了 `options api`,后写 `composition api`,以 `composition api` 优先)优先 +2. `sfc` 中有 `script setup`、`options api` 与 `composition api`, 所有变量会进行合并,变量出现冲突以`script setup`优先 +3. `sfc` 中普通的 `script`,不会与`options api` 、 `composition api`同时存在 +4. `sfc` 中普通的 `script`若存在,则必存在`script setup` +5. `sfc` 中普通的 `script`与 `script setup` 所有变量会进行合并,变量出现冲突以`script setup`优先 + +### ● 样式提升后的优先级 +1. 从 `sfc` 开始,分析 `style` 标签中引用的 `css` 文件,按照 `css` 文件中的引用顺序,深度优先依次提升并注入到 `sfc` 中。 +2. 注入到 `sfc` 后,其优先级完全由 `@vue/compiler-dom` 的编译器决定。 -## Thanks TODO +## Thanks +* [vue](https://github.com/vuejs/core) +* [vite](https://github.com/vitejs/vite) +* [unplugin](https://github.com/unjs/unplugin) \ No newline at end of file diff --git a/packages/core/get-variable/index.ts b/packages/core/get-variable/index.ts index e6bc8f9..c5cb747 100644 --- a/packages/core/get-variable/index.ts +++ b/packages/core/get-variable/index.ts @@ -19,7 +19,7 @@ import type { Node } from 'estree-walker' * @param descriptor */ -export const index = (descriptor: SFCDescriptor) => { +export const getVariable = (descriptor: SFCDescriptor) => { let variableName = {} as VariableName // get variable name form setup script variableName = getVariableNameBySetup(setScriptContent(descriptor, 'setup')) diff --git a/packages/core/index.ts b/packages/core/index.ts index 770bcdc..ac5bb96 100644 --- a/packages/core/index.ts +++ b/packages/core/index.ts @@ -5,7 +5,7 @@ import { parse } from '@vue/compiler-sfc' import { preProcessCSS } from './css/pre-process-css' import { createCSSModule } from './css/process-css' import { initOption } from './option' -import { index } from './get-variable' +import { getVariable } from './get-variable' import { injectCSSVars } from './inject/inject-cssvars' import { revokeCSSVars } from './inject/revoke-cssvars' import type { IBundle, Options } from './types' @@ -35,7 +35,7 @@ const unplugin = createUnplugin( if (id.endsWith('.vue')) { const { descriptor } = parse(code) const importCSSModule = createCSSModule(descriptor, id, preProcessCSSRes) - const variableName = index(descriptor) + const variableName = getVariable(descriptor) code = injectCSSVars(code, importCSSModule, variableName) console.log(code) } diff --git a/play/src/App.vue b/play/src/App.vue index 92059b6..b600fbe 100644 --- a/play/src/App.vue +++ b/play/src/App.vue @@ -66,7 +66,7 @@ export default { -