-
Notifications
You must be signed in to change notification settings - Fork 190
fix(XSender): 用 @layer 隔离 x-sender CSS,修复污染 ant-design-vue 样式问题 (#458) #463
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
SmartBigFeng
wants to merge
1
commit into
element-plus-x:main
Choose a base branch
from
SmartBigFeng:ant-css
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| import type { Plugin } from 'vite'; | ||
|
|
||
| /** | ||
| * 将 x-sender 的 CSS 包裹进 @layer,避免其内部的 .ant 等样式污染用户项目中 ant-design-vue 的全局样式。 | ||
| * | ||
| * @layer 内的样式优先级低于任何非 @layer 的普通样式,因此 ant-design-vue 的样式天然优先,互不干扰。 | ||
| */ | ||
| export default function xSenderCssLayerPlugin(): Plugin { | ||
| return { | ||
| name: 'vite-plugin-x-sender-css-layer', | ||
| transform(code, id) { | ||
| if (id.includes('x-sender') && id.endsWith('.css')) { | ||
| return { | ||
| code: `@layer element-plus-x-third-party { | ||
| ${code} | ||
| }`, | ||
| map: null | ||
| }; | ||
| } | ||
| } | ||
| }; | ||
| } | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🌐 Web query:
In Vite plugintransform(code, id), can CSS moduleidvalues include query suffixes (for example?used,?inline, or other query parameters)? What is the recommended pattern for reliably matching.cssfiles from a specific package?💡 Result:
Web search failed: Server error: no LLM provider could handle the message
🏁 Script executed:
Repository: element-plus-x/Element-Plus-X
Length of output: 1909
🏁 Script executed:
Repository: element-plus-x/Element-Plus-X
Length of output: 1909
🏁 Script executed:
Repository: element-plus-x/Element-Plus-X
Length of output: 1909
🏁 Script executed:
Repository: element-plus-x/Element-Plus-X
Length of output: 1909
🌐 Web query:
Vite plugin transform hook CSS module id query parameters ?used ?inline💡 Result:
In Vite's CSS plugin, the module ID for CSS files (including CSS modules) can include specific query parameters during the transform hook: - ?used: Internal query parameter automatically appended by Vite's import analysis plugin to CSS imports that use the default export. It signals that the CSS string content should be exported (e.g., export default "css content"), enabling tree-shaking of unused CSS strings by esbuild/Rollup. Without ?used, the module may export an empty string or nothing to avoid unnecessary CSS inclusion. This is used in scenarios like import.meta.glob for CSS or default imports needing the content. Note: Vite 5+ removed default CSS exports, making ?inline required for string access. - ?inline: User-specified query to return processed CSS as a string default export instead of injecting via <style> tag (disables automatic injection). Commonly used for manual CSS handling, e.g., import css from './styles.module.css?inline'. Works with CSS modules but returns the CSS string (losing class exports unless combined with plugins). These appear in the id string in the transform hook filter/handler: transform: [{ filter: /?.(used|inline)/ }, handler(src, id) { / id includes ?used or ?inline */ } ]. They help plugins detect/respond to CSS handling modes, e.g., custom inlining or optimization. ?used is internal (not for direct user use; auto-managed), while ?inline is public. For CSS modules with both needs (classes + inline CSS), use plugins like vite-plugin-css-injected-by-js or vite-css-modules.
Citations:
🌐 Web query:
Vite plugin reliable pattern match CSS files id endsWith💡 Result:
In Vite plugins, the reliable pattern to match CSS files by their module ID (where the ID ends with '.css') uses the transform hook's filter option with a RegExp. Use this structure: export default function myPlugin { return { name: 'my-css-plugin', transform(code, id) { if (id.endsWith('.css')) { // Your transform logic for CSS files return { code: transformedCode, map: null // or source map } } } } } For newer Vite versions (5+), use the structured transform filter: import { regexFilter } from '@rolldown/pluginutils' // or similar utility export default function myPlugin { return { name: 'my-css-plugin', transform: { filter: regexFilter(/.css$/), handler(code, id) { // Transform logic return { code: transformedCode, map: null } } } } } This matches any module ID ending with '.css'. The id is the full resolved module path/identifier, so endsWith('.css') reliably identifies CSS files. id.endsWith('.css') is safe as id is always a string in Vite plugin hooks.
Citations:
🌐 Web query:
best practice Vite plugin id.split('?') CSS matching third party packages💡 Result:
In Vite plugins, particularly for handling CSS processing or CSS modules in third-party packages from node_modules, a common best practice is to use conditional filtering in plugin options like include or exclude functions. These functions receive the module id (full path) and parse it using id.split('?') to get the base filename without Vite's internal query parameters (like ?direct or ?html-proxy-cache), then check properties like id.includes('node_modules') to selectively apply transformations. Example from vite-plugin-for-load-css-module for third-party SCSS modules (source 1): include: (id) => (id.endsWith('less') && !id.includes('node_modules')) || (id.endsWith('scss') && id.includes('node_modules')) This pattern ensures: - App CSS (non-node_modules) gets standard processing. - Third-party CSS (node_modules) gets special handling only when needed, avoiding conflicts with relative paths or PostCSS. Vite's CSS pipeline adds query params during processing (sources 14, 19, 22), so splitting isolates the source path for reliable matching. Use enforce: 'pre' for custom CSS plugins to run before Vite's vite:css (source 18). For CSS modules specifically, plugins like vite-css-modules (sources 2,4,27) integrate better with Vite's module graph. Official Vite docs recommend css.modules.include/exclude for scoped processing (vitejs.dev/config/#css-modules-include). Custom plugins follow Rollup/Vite plugin conventions: parse id cleanly before path checks.
Citations:
?directin id for postcss process vitejs/vite#10514Handle Vite CSS query suffixes in the matcher.
On line 12,
id.endsWith('.css')will miss CSS module IDs with query parameters (e.g.,...XSender.css?used,...XSender.css?inline), preventing the layer wrapper from applying and reintroducing style pollution. Also,includes('x-sender')is overly broad and can match unrelated paths.Split the ID on the query string separator first, then apply precise path matching:
🔧 Proposed fix
transform(code, id) { - if (id.includes('x-sender') && id.endsWith('.css')) { + const [path] = id.split('?', 1); + if (/(^|[\\/])x-sender([\\/]|$)/.test(path) && path.endsWith('.css')) { return { code: `@layer element-plus-x-third-party { ${code} }`, map: null }; } }📝 Committable suggestion
🤖 Prompt for AI Agents