@jiayouzuo/vite-plugin-css-scope 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +52 -0
- package/dist/index.js +392 -0
- package/dist/index.js.map +1 -0
- package/package.json +54 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { Plugin } from 'vite';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file 类型定义
|
|
5
|
+
* @description 插件配置选项和内部类型定义
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* 插件配置选项
|
|
10
|
+
*/
|
|
11
|
+
interface CssScopePluginOptions {
|
|
12
|
+
/** 作用域类名,会加到 body 上,也会作为 CSS 选择器的父级 */
|
|
13
|
+
scope: string;
|
|
14
|
+
/** 要处理的目录列表(相对于项目根目录) */
|
|
15
|
+
include: string[];
|
|
16
|
+
/** 排除的目录或文件 */
|
|
17
|
+
exclude?: string[];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @file Vite CSS 作用域隔离插件
|
|
22
|
+
* @description 解决微前端和模块联邦中的样式冲突问题
|
|
23
|
+
*
|
|
24
|
+
* 核心功能:
|
|
25
|
+
* 1. CSS 选择器包裹:.btn → .appProcess .btn
|
|
26
|
+
* 2. JSX 组件注入:自动给模块联邦暴露的组件父元素添加作用域 className
|
|
27
|
+
* 3. HTML 注入:自动给 <body> 添加作用域类名
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```ts
|
|
31
|
+
* import cssScopePlugin from '@jiayouzuo/vite-plugin-css-scope';
|
|
32
|
+
*
|
|
33
|
+
* export default defineConfig({
|
|
34
|
+
* plugins: [
|
|
35
|
+
* cssScopePlugin({
|
|
36
|
+
* scope: 'appProcess',
|
|
37
|
+
* include: ['src/', 'node_modules/@designable/'],
|
|
38
|
+
* exclude: ['node_modules/antd']
|
|
39
|
+
* })
|
|
40
|
+
* ]
|
|
41
|
+
* });
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* CSS 作用域隔离插件
|
|
47
|
+
* @param options - 插件配置
|
|
48
|
+
* @returns Vite 插件
|
|
49
|
+
*/
|
|
50
|
+
declare function cssScopePlugin(options: CssScopePluginOptions): Plugin;
|
|
51
|
+
|
|
52
|
+
export { type CssScopePluginOptions, cssScopePlugin as default };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
// src/utils/path-matcher.ts
|
|
2
|
+
function createPathMatcher(include, exclude) {
|
|
3
|
+
return function shouldTransform(filePath) {
|
|
4
|
+
for (const pattern of exclude) {
|
|
5
|
+
if (filePath.includes(pattern)) {
|
|
6
|
+
return false;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
for (const pattern of include) {
|
|
10
|
+
if (filePath.includes(pattern)) {
|
|
11
|
+
return true;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
return false;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// src/utils/federation.ts
|
|
19
|
+
function extractExposedPaths(config) {
|
|
20
|
+
var _a;
|
|
21
|
+
if (!(config == null ? void 0 : config.plugins)) return [];
|
|
22
|
+
for (const plugin of config.plugins) {
|
|
23
|
+
if (!plugin || typeof plugin !== "object") continue;
|
|
24
|
+
if (plugin.exposes && typeof plugin.exposes === "object") {
|
|
25
|
+
return extractPathsFromExposes(plugin.exposes);
|
|
26
|
+
}
|
|
27
|
+
if (((_a = plugin._options) == null ? void 0 : _a.exposes) && typeof plugin._options.exposes === "object") {
|
|
28
|
+
return extractPathsFromExposes(plugin._options.exposes);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return [];
|
|
32
|
+
}
|
|
33
|
+
function extractPathsFromExposes(exposes) {
|
|
34
|
+
return Object.values(exposes).map((value) => {
|
|
35
|
+
if (typeof value === "string") return value;
|
|
36
|
+
if (value == null ? void 0 : value.import) return value.import;
|
|
37
|
+
return null;
|
|
38
|
+
}).filter((path) => typeof path === "string" && /\.(jsx|tsx)$/.test(path));
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// src/postcss/scope-plugin.ts
|
|
42
|
+
var GLOBAL_SELECTOR_PREFIXES = [
|
|
43
|
+
":root",
|
|
44
|
+
"html",
|
|
45
|
+
"body",
|
|
46
|
+
"html ",
|
|
47
|
+
"body ",
|
|
48
|
+
":root ",
|
|
49
|
+
"html.",
|
|
50
|
+
"body.",
|
|
51
|
+
"html[",
|
|
52
|
+
"body["
|
|
53
|
+
];
|
|
54
|
+
var KEYFRAME_SELECTOR_REGEX = /^(\d+%|from|to)$/;
|
|
55
|
+
function createScopePostcssPlugin(scope, shouldTransform) {
|
|
56
|
+
const plugin = () => ({
|
|
57
|
+
postcssPlugin: "css-scope-plugin",
|
|
58
|
+
Once(root, { result }) {
|
|
59
|
+
const filePath = result.opts.from || "";
|
|
60
|
+
if (!shouldTransform(filePath)) return;
|
|
61
|
+
root.walkRules((rule) => {
|
|
62
|
+
if (isInsideKeyframes(rule)) return;
|
|
63
|
+
if (KEYFRAME_SELECTOR_REGEX.test(rule.selector.trim())) return;
|
|
64
|
+
rule.selector = transformSelectors(rule.selector, scope);
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
plugin.postcss = true;
|
|
69
|
+
return plugin;
|
|
70
|
+
}
|
|
71
|
+
function isInsideKeyframes(rule) {
|
|
72
|
+
const parent = rule.parent;
|
|
73
|
+
if ((parent == null ? void 0 : parent.type) !== "atrule") return false;
|
|
74
|
+
const name = parent.name;
|
|
75
|
+
return name === "keyframes" || name === "-webkit-keyframes" || name === "-moz-keyframes";
|
|
76
|
+
}
|
|
77
|
+
function transformSelectors(selector, scope) {
|
|
78
|
+
return selector.split(",").map((sel) => {
|
|
79
|
+
const trimmed = sel.trim();
|
|
80
|
+
if (isGlobalSelector(trimmed)) return sel;
|
|
81
|
+
return `.${scope} ${sel}`;
|
|
82
|
+
}).join(", ");
|
|
83
|
+
}
|
|
84
|
+
function isGlobalSelector(selector) {
|
|
85
|
+
return GLOBAL_SELECTOR_PREFIXES.some(
|
|
86
|
+
(prefix) => selector === prefix.trim() || selector.startsWith(prefix)
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// src/babel/transform.ts
|
|
91
|
+
import { parse } from "@babel/parser";
|
|
92
|
+
import traverseModule2 from "@babel/traverse";
|
|
93
|
+
import generateModule from "@babel/generator";
|
|
94
|
+
import * as t3 from "@babel/types";
|
|
95
|
+
|
|
96
|
+
// src/babel/hoc-detector.ts
|
|
97
|
+
import * as t from "@babel/types";
|
|
98
|
+
var HOC_NAMES = ["forwardRef", "memo"];
|
|
99
|
+
function isHOCCall(node) {
|
|
100
|
+
if (!t.isCallExpression(node)) return false;
|
|
101
|
+
const callee = node.callee;
|
|
102
|
+
if (t.isIdentifier(callee)) {
|
|
103
|
+
return HOC_NAMES.includes(callee.name);
|
|
104
|
+
}
|
|
105
|
+
if (t.isMemberExpression(callee) && t.isIdentifier(callee.object, { name: "React" }) && t.isIdentifier(callee.property)) {
|
|
106
|
+
return HOC_NAMES.includes(callee.property.name);
|
|
107
|
+
}
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
function isFunctionNode(node) {
|
|
111
|
+
return t.isFunctionDeclaration(node) || t.isArrowFunctionExpression(node) || t.isFunctionExpression(node);
|
|
112
|
+
}
|
|
113
|
+
function getComponentFunctionPath(nodePath) {
|
|
114
|
+
const node = nodePath.node;
|
|
115
|
+
if (isFunctionNode(node)) {
|
|
116
|
+
return { funcPath: nodePath, isValid: true };
|
|
117
|
+
}
|
|
118
|
+
if (isHOCCall(node) && node.arguments.length > 0) {
|
|
119
|
+
return getComponentFunctionPath(nodePath.get("arguments.0"));
|
|
120
|
+
}
|
|
121
|
+
return { funcPath: null, isValid: false };
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// src/babel/scope-injector.ts
|
|
125
|
+
import * as t2 from "@babel/types";
|
|
126
|
+
import traverseModule from "@babel/traverse";
|
|
127
|
+
var traverse = traverseModule.default || traverseModule;
|
|
128
|
+
function isReactComponent(funcPath) {
|
|
129
|
+
let hasJSXReturn = false;
|
|
130
|
+
traverse(
|
|
131
|
+
funcPath.node,
|
|
132
|
+
{
|
|
133
|
+
ReturnStatement(returnPath) {
|
|
134
|
+
const argument = returnPath.node.argument;
|
|
135
|
+
if (!argument) return;
|
|
136
|
+
if (t2.isJSXElement(argument) || t2.isJSXFragment(argument)) {
|
|
137
|
+
hasJSXReturn = true;
|
|
138
|
+
returnPath.stop();
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
if (t2.isConditionalExpression(argument) && (t2.isJSXElement(argument.consequent) || t2.isJSXElement(argument.alternate))) {
|
|
142
|
+
hasJSXReturn = true;
|
|
143
|
+
returnPath.stop();
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
funcPath.scope,
|
|
148
|
+
funcPath
|
|
149
|
+
);
|
|
150
|
+
return hasJSXReturn;
|
|
151
|
+
}
|
|
152
|
+
function injectScopeLogic(path, scopeClassName) {
|
|
153
|
+
const body = path.node.body;
|
|
154
|
+
if (!t2.isBlockStatement(body)) return;
|
|
155
|
+
if (!isReactComponent(path)) return;
|
|
156
|
+
const refCallbackDeclaration = createRefCallbackDeclaration(scopeClassName);
|
|
157
|
+
body.body.unshift(refCallbackDeclaration);
|
|
158
|
+
wrapReturnStatements(path);
|
|
159
|
+
}
|
|
160
|
+
function createRefCallbackDeclaration(scopeClassName) {
|
|
161
|
+
return t2.variableDeclaration("const", [
|
|
162
|
+
t2.variableDeclarator(
|
|
163
|
+
t2.identifier("__scopeRefCallback"),
|
|
164
|
+
t2.arrowFunctionExpression(
|
|
165
|
+
[t2.identifier("__el")],
|
|
166
|
+
t2.blockStatement([
|
|
167
|
+
// if (__el) { ... }
|
|
168
|
+
t2.ifStatement(
|
|
169
|
+
t2.identifier("__el"),
|
|
170
|
+
t2.blockStatement([
|
|
171
|
+
// const __parent = __el.parentElement;
|
|
172
|
+
t2.variableDeclaration("const", [
|
|
173
|
+
t2.variableDeclarator(
|
|
174
|
+
t2.identifier("__parent"),
|
|
175
|
+
t2.memberExpression(t2.identifier("__el"), t2.identifier("parentElement"))
|
|
176
|
+
)
|
|
177
|
+
]),
|
|
178
|
+
// if (__parent) { ... }
|
|
179
|
+
t2.ifStatement(
|
|
180
|
+
t2.identifier("__parent"),
|
|
181
|
+
t2.blockStatement([
|
|
182
|
+
// __parent.classList.add("scopeClassName");
|
|
183
|
+
t2.expressionStatement(
|
|
184
|
+
t2.callExpression(
|
|
185
|
+
t2.memberExpression(
|
|
186
|
+
t2.memberExpression(t2.identifier("__parent"), t2.identifier("classList")),
|
|
187
|
+
t2.identifier("add")
|
|
188
|
+
),
|
|
189
|
+
[t2.stringLiteral(scopeClassName)]
|
|
190
|
+
)
|
|
191
|
+
),
|
|
192
|
+
// __el.remove();
|
|
193
|
+
t2.expressionStatement(
|
|
194
|
+
t2.callExpression(t2.memberExpression(t2.identifier("__el"), t2.identifier("remove")), [])
|
|
195
|
+
)
|
|
196
|
+
])
|
|
197
|
+
)
|
|
198
|
+
])
|
|
199
|
+
)
|
|
200
|
+
])
|
|
201
|
+
)
|
|
202
|
+
)
|
|
203
|
+
]);
|
|
204
|
+
}
|
|
205
|
+
function wrapReturnStatements(path) {
|
|
206
|
+
traverse(
|
|
207
|
+
path.node,
|
|
208
|
+
{
|
|
209
|
+
ReturnStatement(returnPath) {
|
|
210
|
+
if (returnPath.scope !== path.scope) return;
|
|
211
|
+
const argument = returnPath.node.argument;
|
|
212
|
+
if (!argument) return;
|
|
213
|
+
const helperDiv = createHelperDiv();
|
|
214
|
+
let wrappedArgument = argument;
|
|
215
|
+
if (!t2.isJSXElement(argument) && !t2.isJSXFragment(argument)) {
|
|
216
|
+
wrappedArgument = t2.jsxExpressionContainer(argument);
|
|
217
|
+
}
|
|
218
|
+
returnPath.node.argument = t2.jsxFragment(
|
|
219
|
+
t2.jsxOpeningFragment(),
|
|
220
|
+
t2.jsxClosingFragment(),
|
|
221
|
+
[helperDiv, wrappedArgument]
|
|
222
|
+
);
|
|
223
|
+
returnPath.stop();
|
|
224
|
+
}
|
|
225
|
+
},
|
|
226
|
+
path.scope,
|
|
227
|
+
path
|
|
228
|
+
);
|
|
229
|
+
}
|
|
230
|
+
function createHelperDiv() {
|
|
231
|
+
return t2.jsxElement(
|
|
232
|
+
t2.jsxOpeningElement(
|
|
233
|
+
t2.jsxIdentifier("div"),
|
|
234
|
+
[
|
|
235
|
+
// ref={__scopeRefCallback}
|
|
236
|
+
t2.jsxAttribute(
|
|
237
|
+
t2.jsxIdentifier("ref"),
|
|
238
|
+
t2.jsxExpressionContainer(t2.identifier("__scopeRefCallback"))
|
|
239
|
+
),
|
|
240
|
+
// style={{width: 0, height: 0, overflow: 'hidden'}}
|
|
241
|
+
t2.jsxAttribute(
|
|
242
|
+
t2.jsxIdentifier("style"),
|
|
243
|
+
t2.jsxExpressionContainer(
|
|
244
|
+
t2.objectExpression([
|
|
245
|
+
t2.objectProperty(t2.identifier("width"), t2.numericLiteral(0)),
|
|
246
|
+
t2.objectProperty(t2.identifier("height"), t2.numericLiteral(0)),
|
|
247
|
+
t2.objectProperty(t2.identifier("overflow"), t2.stringLiteral("hidden"))
|
|
248
|
+
])
|
|
249
|
+
)
|
|
250
|
+
)
|
|
251
|
+
],
|
|
252
|
+
true
|
|
253
|
+
),
|
|
254
|
+
null,
|
|
255
|
+
[],
|
|
256
|
+
true
|
|
257
|
+
);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// src/babel/transform.ts
|
|
261
|
+
var traverse2 = traverseModule2.default || traverseModule2;
|
|
262
|
+
var generate = generateModule.default || generateModule;
|
|
263
|
+
function transformComponent(code, filePath, scope) {
|
|
264
|
+
try {
|
|
265
|
+
const ast = parse(code, {
|
|
266
|
+
sourceType: "module",
|
|
267
|
+
plugins: ["jsx", "typescript"]
|
|
268
|
+
});
|
|
269
|
+
const functionsToProcess = [];
|
|
270
|
+
traverse2(ast, {
|
|
271
|
+
// export default function Component() {}
|
|
272
|
+
// export default forwardRef(...)
|
|
273
|
+
ExportDefaultDeclaration(path) {
|
|
274
|
+
const declaration = path.node.declaration;
|
|
275
|
+
const result2 = getComponentFunctionPath(path.get("declaration"));
|
|
276
|
+
if (result2.isValid && result2.funcPath) {
|
|
277
|
+
functionsToProcess.push(result2.funcPath);
|
|
278
|
+
} else if (t3.isIdentifier(declaration)) {
|
|
279
|
+
const binding = path.scope.getBinding(declaration.name);
|
|
280
|
+
if (binding == null ? void 0 : binding.path.isVariableDeclarator()) {
|
|
281
|
+
const initPath = binding.path.get("init");
|
|
282
|
+
const result3 = getComponentFunctionPath(initPath);
|
|
283
|
+
if (result3.isValid && result3.funcPath) {
|
|
284
|
+
functionsToProcess.push(result3.funcPath);
|
|
285
|
+
}
|
|
286
|
+
} else if (binding == null ? void 0 : binding.path.isFunctionDeclaration()) {
|
|
287
|
+
functionsToProcess.push(binding.path);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
},
|
|
291
|
+
// export const Component = ...
|
|
292
|
+
// export function Component() {}
|
|
293
|
+
ExportNamedDeclaration(path) {
|
|
294
|
+
const declaration = path.node.declaration;
|
|
295
|
+
if (t3.isVariableDeclaration(declaration)) {
|
|
296
|
+
declaration.declarations.forEach((_, index) => {
|
|
297
|
+
const initPath = path.get(`declaration.declarations.${index}.init`);
|
|
298
|
+
const result2 = getComponentFunctionPath(initPath);
|
|
299
|
+
if (result2.isValid && result2.funcPath) {
|
|
300
|
+
functionsToProcess.push(result2.funcPath);
|
|
301
|
+
}
|
|
302
|
+
});
|
|
303
|
+
} else if (t3.isFunctionDeclaration(declaration)) {
|
|
304
|
+
functionsToProcess.push(path.get("declaration"));
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
});
|
|
308
|
+
functionsToProcess.forEach((funcPath) => {
|
|
309
|
+
injectScopeLogic(funcPath, scope);
|
|
310
|
+
});
|
|
311
|
+
const result = generate(ast, {
|
|
312
|
+
retainLines: false,
|
|
313
|
+
comments: true
|
|
314
|
+
});
|
|
315
|
+
return result.code;
|
|
316
|
+
} catch (error) {
|
|
317
|
+
console.error(`[css-scope-plugin] \u8F6C\u6362\u7EC4\u4EF6\u5931\u8D25: ${filePath}`, error);
|
|
318
|
+
return code;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// src/html/transformer.ts
|
|
323
|
+
function transformHtml(html, scope) {
|
|
324
|
+
if (/<body[^>]*\sclass\s*=\s*["']/.test(html)) {
|
|
325
|
+
return html.replace(/(<body[^>]*\sclass\s*=\s*["'])([^"']*)/, `$1${scope} $2`);
|
|
326
|
+
}
|
|
327
|
+
if (/<body\s+[^>]*>/.test(html)) {
|
|
328
|
+
return html.replace(/(<body)(\s+[^>]*>)/, `$1 class="${scope}"$2`);
|
|
329
|
+
}
|
|
330
|
+
return html.replace("<body>", `<body class="${scope}">`);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// src/index.ts
|
|
334
|
+
function cssScopePlugin(options) {
|
|
335
|
+
const { scope, include, exclude = [] } = options;
|
|
336
|
+
let exposedComponentPaths = [];
|
|
337
|
+
if (!scope) {
|
|
338
|
+
throw new Error("[css-scope-plugin] scope \u914D\u7F6E\u4E0D\u80FD\u4E3A\u7A7A");
|
|
339
|
+
}
|
|
340
|
+
if (!include || include.length === 0) {
|
|
341
|
+
throw new Error("[css-scope-plugin] include \u914D\u7F6E\u4E0D\u80FD\u4E3A\u7A7A");
|
|
342
|
+
}
|
|
343
|
+
const shouldTransform = createPathMatcher(include, exclude);
|
|
344
|
+
return {
|
|
345
|
+
name: "css-scope-plugin",
|
|
346
|
+
enforce: "pre",
|
|
347
|
+
// 在 React 插件之前执行
|
|
348
|
+
/**
|
|
349
|
+
* 配置解析完成后,提取模块联邦 exposes 路径
|
|
350
|
+
*/
|
|
351
|
+
configResolved(resolvedConfig) {
|
|
352
|
+
exposedComponentPaths = extractExposedPaths(resolvedConfig);
|
|
353
|
+
},
|
|
354
|
+
/**
|
|
355
|
+
* 注入 PostCSS 插件
|
|
356
|
+
*/
|
|
357
|
+
config() {
|
|
358
|
+
return {
|
|
359
|
+
css: {
|
|
360
|
+
postcss: {
|
|
361
|
+
plugins: [createScopePostcssPlugin(scope, shouldTransform)()]
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
};
|
|
365
|
+
},
|
|
366
|
+
/**
|
|
367
|
+
* 转换模块联邦暴露的 JSX/TSX 组件
|
|
368
|
+
*/
|
|
369
|
+
transform(code, id) {
|
|
370
|
+
if (!/\.(jsx|tsx)$/.test(id)) return null;
|
|
371
|
+
const isExposed = exposedComponentPaths.some((exposedPath) => {
|
|
372
|
+
const normalizedPath = exposedPath.replace(/^\.\//, "");
|
|
373
|
+
return id.includes(normalizedPath);
|
|
374
|
+
});
|
|
375
|
+
if (!isExposed) return null;
|
|
376
|
+
return {
|
|
377
|
+
code: transformComponent(code, id, scope),
|
|
378
|
+
map: null
|
|
379
|
+
};
|
|
380
|
+
},
|
|
381
|
+
/**
|
|
382
|
+
* 给 index.html 的 <body> 添加作用域类名
|
|
383
|
+
*/
|
|
384
|
+
transformIndexHtml(html) {
|
|
385
|
+
return transformHtml(html, scope);
|
|
386
|
+
}
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
export {
|
|
390
|
+
cssScopePlugin as default
|
|
391
|
+
};
|
|
392
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/path-matcher.ts","../src/utils/federation.ts","../src/postcss/scope-plugin.ts","../src/babel/transform.ts","../src/babel/hoc-detector.ts","../src/babel/scope-injector.ts","../src/html/transformer.ts","../src/index.ts"],"sourcesContent":["/**\n * @file 路径匹配工具\n * @description 判断文件路径是否需要处理\n */\n\n/**\n * 创建路径匹配器\n * @param include - 包含的路径模式\n * @param exclude - 排除的路径模式\n * @returns 匹配函数\n */\nexport function createPathMatcher(include: string[], exclude: string[]) {\n /**\n * 检查文件是否需要处理\n * @param filePath - 文件路径\n * @returns 是否需要处理\n */\n return function shouldTransform(filePath: string): boolean {\n // 优先检查排除列表\n for (const pattern of exclude) {\n if (filePath.includes(pattern)) {\n return false;\n }\n }\n\n // 检查包含列表\n for (const pattern of include) {\n if (filePath.includes(pattern)) {\n return true;\n }\n }\n\n return false;\n };\n}\n","/**\n * @file 模块联邦工具\n * @description 提取模块联邦配置中的 exposes 路径\n */\n\nimport type { FederationExposeValue } from '../types';\n\n/**\n * 从 Vite 配置中提取模块联邦暴露的组件路径\n * 支持 @originjs/vite-plugin-federation 和 @module-federation/vite\n * @param config - Vite 解析后的配置\n * @returns JSX/TSX 组件路径列表\n */\nexport function extractExposedPaths(config: any): string[] {\n if (!config?.plugins) return [];\n\n for (const plugin of config.plugins) {\n if (!plugin || typeof plugin !== 'object') continue;\n\n // 方式1:@originjs/vite-plugin-federation(直接 exposes 属性)\n if (plugin.exposes && typeof plugin.exposes === 'object') {\n return extractPathsFromExposes(plugin.exposes);\n }\n\n // 方式2:@module-federation/vite(_options.exposes 属性)\n if (plugin._options?.exposes && typeof plugin._options.exposes === 'object') {\n return extractPathsFromExposes(plugin._options.exposes);\n }\n }\n\n return [];\n}\n\n/**\n * 从 exposes 配置中提取 JSX/TSX 路径\n * @param exposes - exposes 配置对象\n * @returns 路径列表\n */\nfunction extractPathsFromExposes(exposes: Record<string, string | FederationExposeValue>): string[] {\n return Object.values(exposes)\n .map((value) => {\n // 字符串格式:'./src/xxx.jsx'\n if (typeof value === 'string') return value;\n // 对象格式:{ import: './src/xxx.jsx' }\n if (value?.import) return value.import;\n return null;\n })\n .filter((path): path is string => typeof path === 'string' && /\\.(jsx|tsx)$/.test(path));\n}\n","/**\n * @file PostCSS 作用域插件\n * @description 给 CSS 选择器添加作用域前缀\n */\n\n/** 需要跳过的全局选择器前缀 */\nconst GLOBAL_SELECTOR_PREFIXES = [\n ':root',\n 'html',\n 'body',\n 'html ',\n 'body ',\n ':root ',\n 'html.',\n 'body.',\n 'html[',\n 'body['\n];\n\n/** 关键帧选择器正则(0%, 100%, from, to) */\nconst KEYFRAME_SELECTOR_REGEX = /^(\\d+%|from|to)$/;\n\n/**\n * 创建 PostCSS 作用域插件\n * @param scope - 作用域类名\n * @param shouldTransform - 路径匹配函数\n * @returns PostCSS 插件\n */\nexport function createScopePostcssPlugin(scope: string, shouldTransform: (path: string) => boolean) {\n const plugin = (): any => ({\n postcssPlugin: 'css-scope-plugin',\n\n Once(root: any, { result }: any) {\n const filePath = result.opts.from || '';\n\n // 检查文件是否需要处理\n if (!shouldTransform(filePath)) return;\n\n root.walkRules((rule: any) => {\n // 跳过 @keyframes 内部规则\n if (isInsideKeyframes(rule)) return;\n\n // 跳过关键帧选择器\n if (KEYFRAME_SELECTOR_REGEX.test(rule.selector.trim())) return;\n\n // 转换选择器\n rule.selector = transformSelectors(rule.selector, scope);\n });\n }\n });\n\n // 标记为 PostCSS 插件\n (plugin as any).postcss = true;\n\n return plugin;\n}\n\n/**\n * 检查规则是否在 @keyframes 内部\n */\nfunction isInsideKeyframes(rule: any): boolean {\n const parent = rule.parent;\n if (parent?.type !== 'atrule') return false;\n\n const name = parent.name;\n return name === 'keyframes' || name === '-webkit-keyframes' || name === '-moz-keyframes';\n}\n\n/**\n * 转换选择器,添加作用域前缀\n * @param selector - 原始选择器\n * @param scope - 作用域类名\n * @returns 转换后的选择器\n */\nfunction transformSelectors(selector: string, scope: string): string {\n return selector\n .split(',')\n .map((sel) => {\n const trimmed = sel.trim();\n\n // 全局选择器不包裹\n if (isGlobalSelector(trimmed)) return sel;\n\n return `.${scope} ${sel}`;\n })\n .join(', ');\n}\n\n/**\n * 检查是否为全局选择器\n */\nfunction isGlobalSelector(selector: string): boolean {\n return GLOBAL_SELECTOR_PREFIXES.some(\n (prefix) => selector === prefix.trim() || selector.startsWith(prefix)\n );\n}\n","/**\n * @file Babel 转换器\n * @description 转换 JSX/TSX 组件,注入作用域逻辑\n */\n\nimport { parse } from '@babel/parser';\nimport traverseModule from '@babel/traverse';\nimport generateModule from '@babel/generator';\nimport * as t from '@babel/types';\nimport type { NodePath } from '@babel/traverse';\nimport { getComponentFunctionPath } from './hoc-detector';\nimport { injectScopeLogic } from './scope-injector';\n\n// 处理 ES Module 和 CommonJS 的兼容性\nconst traverse = (traverseModule as any).default || traverseModule;\nconst generate = (generateModule as any).default || generateModule;\n\n/**\n * 转换组件代码,注入作用域逻辑\n * @param code - 源代码\n * @param filePath - 文件路径(用于错误提示)\n * @param scope - 作用域类名\n * @returns 转换后的代码\n */\nexport function transformComponent(code: string, filePath: string, scope: string): string {\n try {\n // 解析 AST\n const ast = parse(code, {\n sourceType: 'module',\n plugins: ['jsx', 'typescript']\n });\n\n // 收集需要处理的函数\n const functionsToProcess: NodePath<any>[] = [];\n\n // 遍历 AST,找到所有 export 的组件\n traverse(ast, {\n // export default function Component() {}\n // export default forwardRef(...)\n ExportDefaultDeclaration(path: NodePath<any>) {\n const declaration = path.node.declaration;\n const result = getComponentFunctionPath(path.get('declaration'));\n\n if (result.isValid && result.funcPath) {\n functionsToProcess.push(result.funcPath);\n }\n // export default Component(标识符引用)\n else if (t.isIdentifier(declaration)) {\n const binding = path.scope.getBinding(declaration.name);\n if (binding?.path.isVariableDeclarator()) {\n const initPath = binding.path.get('init');\n const result = getComponentFunctionPath(initPath as NodePath<any>);\n if (result.isValid && result.funcPath) {\n functionsToProcess.push(result.funcPath);\n }\n } else if (binding?.path.isFunctionDeclaration()) {\n functionsToProcess.push(binding.path);\n }\n }\n },\n\n // export const Component = ...\n // export function Component() {}\n ExportNamedDeclaration(path: NodePath<any>) {\n const declaration = path.node.declaration;\n\n if (t.isVariableDeclaration(declaration)) {\n declaration.declarations.forEach((_: any, index: number) => {\n const initPath = path.get(`declaration.declarations.${index}.init`);\n const result = getComponentFunctionPath(initPath as NodePath<any>);\n if (result.isValid && result.funcPath) {\n functionsToProcess.push(result.funcPath);\n }\n });\n } else if (t.isFunctionDeclaration(declaration)) {\n functionsToProcess.push(path.get('declaration'));\n }\n }\n });\n\n // 处理所有收集到的函数\n functionsToProcess.forEach((funcPath) => {\n injectScopeLogic(funcPath, scope);\n });\n\n // 生成代码\n const result = generate(ast, {\n retainLines: false,\n comments: true\n });\n\n return result.code;\n } catch (error) {\n console.error(`[css-scope-plugin] 转换组件失败: ${filePath}`, error);\n return code;\n }\n}\n","/**\n * @file HOC 检测器\n * @description 检测和提取高阶组件(forwardRef、memo)中的真实组件函数\n */\n\nimport * as t from '@babel/types';\nimport type { NodePath } from '@babel/traverse';\nimport type { ComponentFunctionResult } from '../types';\n\n/** 支持的 HOC 名称 */\nconst HOC_NAMES = ['forwardRef', 'memo'];\n\n/**\n * 检查节点是否是 HOC 调用\n * 支持:forwardRef(...)、memo(...)、React.forwardRef(...)、React.memo(...)\n */\nexport function isHOCCall(node: any): boolean {\n if (!t.isCallExpression(node)) return false;\n\n const callee = node.callee;\n\n // 直接调用:forwardRef(...) 或 memo(...)\n if (t.isIdentifier(callee)) {\n return HOC_NAMES.includes(callee.name);\n }\n\n // 成员调用:React.forwardRef(...) 或 React.memo(...)\n if (\n t.isMemberExpression(callee) &&\n t.isIdentifier(callee.object, { name: 'React' }) &&\n t.isIdentifier(callee.property)\n ) {\n return HOC_NAMES.includes(callee.property.name);\n }\n\n return false;\n}\n\n/**\n * 检查节点是否是函数(声明、表达式、箭头函数)\n */\nexport function isFunctionNode(node: any): boolean {\n return (\n t.isFunctionDeclaration(node) ||\n t.isArrowFunctionExpression(node) ||\n t.isFunctionExpression(node)\n );\n}\n\n/**\n * 从 NodePath 中提取组件函数路径\n * 递归处理 HOC 包裹,直到找到真实的函数\n * @param nodePath - AST 节点路径\n * @returns 提取结果\n */\nexport function getComponentFunctionPath(nodePath: NodePath<any>): ComponentFunctionResult {\n const node = nodePath.node;\n\n // 直接是函数 → 返回\n if (isFunctionNode(node)) {\n return { funcPath: nodePath, isValid: true };\n }\n\n // 是 HOC 调用 → 递归提取第一个参数\n if (isHOCCall(node) && node.arguments.length > 0) {\n return getComponentFunctionPath(nodePath.get('arguments.0') as NodePath<any>);\n }\n\n return { funcPath: null, isValid: false };\n}\n","/**\n * @file 作用域注入器\n * @description 向 React 组件注入作用域逻辑(回调 ref + 辅助 div)\n */\n\nimport * as t from '@babel/types';\nimport type { NodePath } from '@babel/traverse';\nimport traverseModule from '@babel/traverse';\n\nconst traverse = (traverseModule as any).default || traverseModule;\n\n/**\n * 检查函数是否是 React 组件(返回 JSX)\n */\nexport function isReactComponent(funcPath: NodePath<any>): boolean {\n let hasJSXReturn = false;\n\n traverse(\n funcPath.node,\n {\n ReturnStatement(returnPath: NodePath<any>) {\n const argument = returnPath.node.argument;\n if (!argument) return;\n\n // 直接返回 JSX\n if (t.isJSXElement(argument) || t.isJSXFragment(argument)) {\n hasJSXReturn = true;\n returnPath.stop();\n return;\n }\n\n // 条件表达式返回 JSX\n if (\n t.isConditionalExpression(argument) &&\n (t.isJSXElement(argument.consequent) || t.isJSXElement(argument.alternate))\n ) {\n hasJSXReturn = true;\n returnPath.stop();\n }\n }\n },\n funcPath.scope,\n funcPath\n );\n\n return hasJSXReturn;\n}\n\n/**\n * 向组件函数注入作用域逻辑\n * @param path - 函数节点路径\n * @param scopeClassName - 作用域类名\n */\nexport function injectScopeLogic(path: NodePath<any>, scopeClassName: string): void {\n const body = path.node.body;\n\n // 确保函数体是 BlockStatement\n if (!t.isBlockStatement(body)) return;\n\n // 只处理 React 组件\n if (!isReactComponent(path)) return;\n\n // 1. 创建回调 ref 声明\n const refCallbackDeclaration = createRefCallbackDeclaration(scopeClassName);\n\n // 2. 在函数体开头注入\n body.body.unshift(refCallbackDeclaration);\n\n // 3. 包裹 return 语句\n wrapReturnStatements(path);\n}\n\n/**\n * 创建回调 ref 函数声明\n * 生成代码:\n * const __scopeRefCallback = (__el) => {\n * if (__el) {\n * const __parent = __el.parentElement;\n * if (__parent) {\n * __parent.classList.add(\"scopeClassName\");\n * __el.remove();\n * }\n * }\n * };\n */\nfunction createRefCallbackDeclaration(scopeClassName: string): t.VariableDeclaration {\n return t.variableDeclaration('const', [\n t.variableDeclarator(\n t.identifier('__scopeRefCallback'),\n t.arrowFunctionExpression(\n [t.identifier('__el')],\n t.blockStatement([\n // if (__el) { ... }\n t.ifStatement(\n t.identifier('__el'),\n t.blockStatement([\n // const __parent = __el.parentElement;\n t.variableDeclaration('const', [\n t.variableDeclarator(\n t.identifier('__parent'),\n t.memberExpression(t.identifier('__el'), t.identifier('parentElement'))\n )\n ]),\n // if (__parent) { ... }\n t.ifStatement(\n t.identifier('__parent'),\n t.blockStatement([\n // __parent.classList.add(\"scopeClassName\");\n t.expressionStatement(\n t.callExpression(\n t.memberExpression(\n t.memberExpression(t.identifier('__parent'), t.identifier('classList')),\n t.identifier('add')\n ),\n [t.stringLiteral(scopeClassName)]\n )\n ),\n // __el.remove();\n t.expressionStatement(\n t.callExpression(t.memberExpression(t.identifier('__el'), t.identifier('remove')), [])\n )\n ])\n )\n ])\n )\n ])\n )\n )\n ]);\n}\n\n/**\n * 包裹 return 语句,添加辅助 div\n */\nfunction wrapReturnStatements(path: NodePath<any>): void {\n traverse(\n path.node,\n {\n ReturnStatement(returnPath: NodePath<any>) {\n // 只处理当前函数的 return,跳过嵌套函数\n if (returnPath.scope !== path.scope) return;\n\n const argument = returnPath.node.argument;\n if (!argument) return;\n\n // 创建辅助 div\n const helperDiv = createHelperDiv();\n\n // 包裹原始返回值\n let wrappedArgument = argument;\n if (!t.isJSXElement(argument) && !t.isJSXFragment(argument)) {\n wrappedArgument = t.jsxExpressionContainer(argument);\n }\n\n // 用 Fragment 包裹\n returnPath.node.argument = t.jsxFragment(\n t.jsxOpeningFragment(),\n t.jsxClosingFragment(),\n [helperDiv, wrappedArgument]\n );\n\n returnPath.stop();\n }\n },\n path.scope,\n path\n );\n}\n\n/**\n * 创建辅助 div 元素\n * 生成代码:<div ref={__scopeRefCallback} style={{width: 0, height: 0, overflow: 'hidden'}}></div>\n */\nfunction createHelperDiv(): t.JSXElement {\n return t.jsxElement(\n t.jsxOpeningElement(\n t.jsxIdentifier('div'),\n [\n // ref={__scopeRefCallback}\n t.jsxAttribute(\n t.jsxIdentifier('ref'),\n t.jsxExpressionContainer(t.identifier('__scopeRefCallback'))\n ),\n // style={{width: 0, height: 0, overflow: 'hidden'}}\n t.jsxAttribute(\n t.jsxIdentifier('style'),\n t.jsxExpressionContainer(\n t.objectExpression([\n t.objectProperty(t.identifier('width'), t.numericLiteral(0)),\n t.objectProperty(t.identifier('height'), t.numericLiteral(0)),\n t.objectProperty(t.identifier('overflow'), t.stringLiteral('hidden'))\n ])\n )\n )\n ],\n true\n ),\n null,\n [],\n true\n );\n}\n","/**\n * @file HTML 转换器\n * @description 给 index.html 的 <body> 标签添加作用域类名\n */\n\n/**\n * 转换 HTML,给 body 添加作用域类名\n * @param html - 原始 HTML\n * @param scope - 作用域类名\n * @returns 转换后的 HTML\n */\nexport function transformHtml(html: string, scope: string): string {\n // 情况1: <body class=\"xxx\"> - 已有 class,追加作用域类名\n if (/<body[^>]*\\sclass\\s*=\\s*[\"']/.test(html)) {\n return html.replace(/(<body[^>]*\\sclass\\s*=\\s*[\"'])([^\"']*)/, `$1${scope} $2`);\n }\n\n // 情况2: <body ...> - 有其他属性但无 class,插入 class 属性\n if (/<body\\s+[^>]*>/.test(html)) {\n return html.replace(/(<body)(\\s+[^>]*>)/, `$1 class=\"${scope}\"$2`);\n }\n\n // 情况3: <body> - 纯净的 body 标签\n return html.replace('<body>', `<body class=\"${scope}\">`);\n}\n","/**\n * @file Vite CSS 作用域隔离插件\n * @description 解决微前端和模块联邦中的样式冲突问题\n *\n * 核心功能:\n * 1. CSS 选择器包裹:.btn → .appProcess .btn\n * 2. JSX 组件注入:自动给模块联邦暴露的组件父元素添加作用域 className\n * 3. HTML 注入:自动给 <body> 添加作用域类名\n *\n * @example\n * ```ts\n * import cssScopePlugin from '@jiayouzuo/vite-plugin-css-scope';\n *\n * export default defineConfig({\n * plugins: [\n * cssScopePlugin({\n * scope: 'appProcess',\n * include: ['src/', 'node_modules/@designable/'],\n * exclude: ['node_modules/antd']\n * })\n * ]\n * });\n * ```\n */\n\nimport type { Plugin } from 'vite';\nimport type { CssScopePluginOptions } from './types';\nimport { createPathMatcher } from './utils/path-matcher';\nimport { extractExposedPaths } from './utils/federation';\nimport { createScopePostcssPlugin } from './postcss/scope-plugin';\nimport { transformComponent } from './babel/transform';\nimport { transformHtml } from './html/transformer';\n\n/**\n * CSS 作用域隔离插件\n * @param options - 插件配置\n * @returns Vite 插件\n */\nexport default function cssScopePlugin(options: CssScopePluginOptions): Plugin {\n const { scope, include, exclude = [] } = options;\n\n // 存储模块联邦暴露的组件路径\n let exposedComponentPaths: string[] = [];\n\n // 验证配置\n if (!scope) {\n throw new Error('[css-scope-plugin] scope 配置不能为空');\n }\n if (!include || include.length === 0) {\n throw new Error('[css-scope-plugin] include 配置不能为空');\n }\n\n // 创建路径匹配器\n const shouldTransform = createPathMatcher(include, exclude);\n\n return {\n name: 'css-scope-plugin',\n enforce: 'pre', // 在 React 插件之前执行\n\n /**\n * 配置解析完成后,提取模块联邦 exposes 路径\n */\n configResolved(resolvedConfig) {\n exposedComponentPaths = extractExposedPaths(resolvedConfig);\n },\n\n /**\n * 注入 PostCSS 插件\n */\n config() {\n return {\n css: {\n postcss: {\n plugins: [createScopePostcssPlugin(scope, shouldTransform)()]\n }\n }\n };\n },\n\n /**\n * 转换模块联邦暴露的 JSX/TSX 组件\n */\n transform(code, id) {\n // 只处理 JSX/TSX 文件\n if (!/\\.(jsx|tsx)$/.test(id)) return null;\n\n // 检查是否是暴露的组件\n const isExposed = exposedComponentPaths.some((exposedPath) => {\n const normalizedPath = exposedPath.replace(/^\\.\\//, '');\n return id.includes(normalizedPath);\n });\n\n if (!isExposed) return null;\n\n // 转换组件\n return {\n code: transformComponent(code, id, scope),\n map: null\n };\n },\n\n /**\n * 给 index.html 的 <body> 添加作用域类名\n */\n transformIndexHtml(html) {\n return transformHtml(html, scope);\n }\n };\n}\n\n// 导出类型\nexport type { CssScopePluginOptions };\n"],"mappings":"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","names":["traverseModule","t","t","traverse","traverseModule","result"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@jiayouzuo/vite-plugin-css-scope",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Vite 插件:CSS 作用域隔离,解决微前端和模块联邦中的样式冲突问题",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"module": "dist/index.js",
|
|
8
|
+
"types": "dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js",
|
|
13
|
+
"default": "./dist/index.js"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "tsup",
|
|
18
|
+
"dev": "tsup --watch"
|
|
19
|
+
},
|
|
20
|
+
"keywords": [
|
|
21
|
+
"vite",
|
|
22
|
+
"vite-plugin",
|
|
23
|
+
"css",
|
|
24
|
+
"scope",
|
|
25
|
+
"style-isolation",
|
|
26
|
+
"micro-frontend",
|
|
27
|
+
"module-federation"
|
|
28
|
+
],
|
|
29
|
+
"author": "jiayouzuo",
|
|
30
|
+
"license": "MIT",
|
|
31
|
+
"peerDependencies": {
|
|
32
|
+
"postcss": "^8.0.0",
|
|
33
|
+
"vite": "^5.0.0 || ^6.0.0"
|
|
34
|
+
},
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"@babel/generator": "^7.28.0",
|
|
37
|
+
"@babel/parser": "^7.28.0",
|
|
38
|
+
"@babel/traverse": "^7.28.0",
|
|
39
|
+
"@babel/types": "^7.28.0"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@types/babel__generator": "^7.27.0",
|
|
43
|
+
"@types/babel__traverse": "^7.28.0",
|
|
44
|
+
"@types/node": "^20.0.0",
|
|
45
|
+
"tsup": "^8.0.0",
|
|
46
|
+
"typescript": "^5.0.0"
|
|
47
|
+
},
|
|
48
|
+
"files": [
|
|
49
|
+
"dist"
|
|
50
|
+
],
|
|
51
|
+
"engines": {
|
|
52
|
+
"node": ">=16.0.0"
|
|
53
|
+
}
|
|
54
|
+
}
|