前端构建工具【免费下载链接】purgecssRemove unused CSS项目地址https://gitcode.com/gh_mirrors/pu/purgecss点击查看免费下载PurgeCSS 通过一组可配置的 Options 来控制移除未使用 CSS的行为合理的配置能显著提升清理精度与处理效率。本文以官方 Configuration 文档 为骨架结合本仓库packages/purgecss的源码实现与测试用例逐一讲解配置文件加载机制、每个选项的用法、默认值与底层原理帮助你写出可复现、可运行的生产级配置。配置文件purgecss.config.js 与加载机制配置文件本质上是一个简单的 JavaScript 文件。按照官方文档默认情况下 JavaScript API 会自动查找purgecss.config.js其最小可用形态如下module.exports { content: [index.html], css: [style.css] }随后有两种调用方式不传参数自动加载默认配置文件名或显式传入配置文件路径// 自动查找当前目录下的 purgecss.config.js const purgecss await new PurgeCSS().purge() // 或使用配置文件路径作为唯一参数 const purgecss await new PurgeCSS().purge(./purgecss.config.js)从源码来看配置文件加载逻辑位于 packages/purgecss/src/index.ts 的setOptions函数默认文件名由常量CONFIG_FILENAME purgecss.config.js定义见 packages/purgecss/src/constants.tssetOptions会先path.resolve(process.cwd(), configFile)解析为绝对路径再通过动态import()加载加载失败会抛出Error loading the config file异常加载后的配置会与defaultOptions合并{ ...defaultOptions, ...options }并对safelist做一次standardizeSafelist标准化因此未显式声明的选项都会落到源码中的默认值上见 packages/purgecss/src/options.ts。setOptions同样被 CLI 复用在 packages/purgecss/src/bin.ts 中purgecss --config path会调用setOptions(config)加载配置再允许命令行参数覆盖其中的字段——这是配置文件 CLI 覆盖两级配置模型的底层实现。Options 一览类型定义与默认值官方文档给出的用户可定义选项类型如下interface UserDefinedOptions { content: Arraystring | RawContent; css: Arraystring | RawCSS; defaultExtractor?: ExtractorFunction; extractors?: ArrayExtractors; fontFace?: boolean; keyframes?: boolean; output?: string; rejected?: boolean; rejectedCss?: boolean; stdin?: boolean; stdout?: boolean; variables?: boolean; safelist?: UserDefinedSafelist; blocklist?: StringRegExpArray; } interface RawContent { extension: string raw: string } interface RawCSS { raw: string } type StringRegExpArray ArrayRegExp | string; type ComplexSafelist { standard?: StringRegExpArray; deep?: RegExp[]; greedy?: RegExp[]; variables?: StringRegExpArray; keyframes?: StringRegExpArray; }; type UserDefinedSafelist StringRegExpArray | ComplexSafelist;该类型定义在仓库中对应 packages/purgecss/src/types/index.ts 的UserDefinedOptions接口。需要注意的是仓库中的接口还包含文档未展开的sourceMap?: boolean | (postcss.SourceMapOptions { to?: string })选项并且内部使用的Options接口将content、css、defaultExtractor、extractors等字段标记为必填因为它们会被默认值填充。各个布尔选项的默认值都可以在 packages/purgecss/src/options.ts 的defaultOptions中找到fontFace: false、keyframes: false、rejected: false、rejectedCss: false、stdin: false、stdout: false、variables: false同时safelist的默认形态是一个含standard、deep、greedy、variables、keyframes五个空数组的完整对象。content指定待分析的内容来源content用于指定 PurgeCSS 需要分析的文件接受文件名或 glob 模式的数组。文件可以是 HTML、Pug、Blade 等任何包含选择器引用的文本文件await new PurgeCSS().purge({ content: [index.html, **/*.js, **/*.html, **/*.vue], css: [css/app.css] })PurgeCSS 同样支持原始字符串内容raw content。此时需要传入包含raw属性的对象以替代文件名若要配合自定义 extractor 正常工作还需要同时传入extension属性await new PurgeCSS().purge({ content: [ { raw: htmlbodydiv classapp/div/body/html, extension: html }, **/*.js, **/*.html, **/*.vue ], css: [ { raw: body { margin: 0 } }, css/app.css ] })底层处理路径在 packages/purgecss/src/index.ts 的purge方法中content数组会被拆分为字符串形式的文件路径与对象形式的RawContent分别交给extractSelectorsFromFiles与extractSelectorsFromString最后用mergeExtractorSelectors合并两组提取结果。extractSelectorsFromFilespackages/purgecss/src/index.ts会先尝试把每个条目当作真实文件访问访问失败则用glob.sync展开为文件列表如果提供了skippedContentGlobs展开时会用其过滤文件。注意当content非空但最终一个文件都没匹配到时会输出警告No files found from the passed PurgeCSS option content.。extractSelectorsFromStringpackages/purgecss/src/index.ts则会用getFileExtractor根据extension为每段 raw 内容挑选对应的 extractor内部通过filename.endsWith(ext)匹配见 packages/purgecss/src/index.ts——这正是 raw 内容需要带extension的原因。css指定待清理的样式文件css与content类似接受文件名或 glob 模式的数组指定需要被 PurgeCSS 处理的 CSS 文件await new PurgeCSS().purge({ content: [index.html, **/*.js, **/*.html, **/*.vue], css: [css/app.css] })同样支持原始 CSS 字符串只需传入带raw属性的对象await new PurgeCSS().purge({ content: [ { raw: htmlbodydiv classapp/div/body/html, extension: html }, **/*.js, **/*.html, **/*.vue ], css: [ { raw: body { margin: 0 } } ] })在 packages/purgecss/src/index.ts 的getPurgedCSS中css条目同样先经glob.sync展开nodir: true并应用skippedContentGlobs随后每个源会被postcss.parse解析为 AST经过walkThroughCSS清理后由root.toResult()输出RawCSS接口在仓库中还支持可选的name属性见 packages/purgecss/src/types/index.ts该值会作为结果对象的file字段返回。defaultExtractor全局默认选择器提取器如果发现大量未使用的 CSS 没有被移除通常说明默认提取器未能从内容中识别出这些选择器此时可以自定义 extractor。extractor 可以按文件扩展名分别指定见下节extractors如果希望所有类型的文件都使用同一个提取逻辑就把它放进defaultExtractorawait new PurgeCSS().purge({ // ... defaultExtractor: content content.match(/[\w-/:](?!:)/g) || [] })内置默认值为content.match(/[A-Za-z0-9_-]/g) || []见 packages/purgecss/src/options.ts。当某个文件没有匹配到专用 extractor 时getFileExtractor会回退到this.options.defaultExtractor见 packages/purgecss/src/index.ts。extractor 的返回值既可以是字符串数组也可以是包含attributes、classes、ids、tags、undetermined的详细结构ExtractorResultDetailed定义见 packages/purgecss/src/types/index.ts后者能带来更高的识别精度。extractors按扩展名定制的提取器extractors允许按文件扩展名绑定不同的 extractor从而获得更高的准确度与更好的优化效果但代价是各 extractor 行为各异可能让结果更难以预测。官方文档建议把自定义 extractors 视作一种高级优化手段不一定必要。import purgeFromHTML from purge-from-html await new PurgeCSS().purge({ content: [index.html, **/*.js, **/*.html, **/*.vue], css: [css/app.css], extractors: [ { extractor: purgeFromHTML, extensions: [html] }, { extractor: content content.match(/[\w-/:](?!:)/g) || [], extensions: [vue, js] } ] })每个 extractor 条目由extractor函数与extensions扩展名列表组成类型定义见 packages/purgecss/src/types/index.ts。匹配逻辑为扩展名后缀匹配filename.endsWith(ext)因此同一扩展名只命中第一个匹配项。关于 extractor 的更多细节可继续阅读 Extractors 专题文档。fontFace默认 false清理未使用的 font-face如果 CSS 中存在未被使用的font-face规则设置fontFace: true即可将其移除await new PurgeCSS().purge({ content: [index.html, **/*.js, **/*.html, **/*.vue], css: [css/app.css], fontFace: true })底层实现分为两步evaluateAtRule在遍历 AST 时收集所有font-face节点及其font-family声明见 packages/purgecss/src/index.ts同时collectDeclarationsData在遇到font-family声明时把值按逗号拆分、去引号后记入usedFontFaces集合见 packages/purgecss/src/index.ts。最终removeUnusedFontFaces会删除所有未被使用的font-face节点见 packages/purgecss/src/index.ts。keyframes默认 false清理未使用的动画关键帧如果项目引入 animate.css 之类的 CSS 动画库往往只有少量动画被真正使用设置keyframes: true可以移除未使用的keyframesawait new PurgeCSS().purge({ content: [index.html, **/*.js, **/*.html, **/*.vue], css: [css/app.css], keyframes: true })源码中evaluateAtRule会收集所有以keyframes结尾的 at-rulenode.name.endsWith(keyframes)同时覆盖keyframes与-webkit-keyframes等collectDeclarationsData则从animation/animation-name属性中拆分出被使用的动画名见 packages/purgecss/src/index.ts。removeUnusedKeyframes删除未被使用且未被 safelist 保护的动画见 packages/purgecss/src/index.tssafelist 判定逻辑见后文。variables默认 false清理未使用的 CSS 变量如果项目使用 CSS 自定义属性Custom Properties或引入 Bootstrap 这类重度依赖 CSS 变量的库设置variables: true可以移除未被引用的变量await new PurgeCSS().purge({ content: [index.html, **/*.js, **/*.html, **/*.vue], css: [css/app.css], variables: true })该功能的实现独立于主清理流程purge启动时会把safelist.variables注入VariablesStructure见 packages/purgecss/src/index.tscollectDeclarationsData通过var(...)的正则匹配记录变量定义与引用关系见 packages/purgecss/src/index.ts最终removeUnusedCSSVariables调用variablesStructure.removeUnused()完成清理。数据结构与算法细节位于 packages/purgecss/src/VariablesStructure.ts。rejected默认 false输出被移除的选择器列表逐条扫视被删除的选择器有助于发现是否存在误杀。设置rejected: true后清理结果对象的rejected字段会包含被移除的选择器数组await new PurgeCSS().purge({ content: [index.html, **/*.js, **/*.html, **/*.vue], css: [css/app.css], rejected: true })源码中evaluateRule判定某个 selector 不应保留时会把它加入this.selectorsRemoved见 packages/purgecss/src/index.tsgetPurgedCSS在结果构建阶段将其转换为result.rejected数组并清空集合见 packages/purgecss/src/index.ts。测试用例 packages/purgecss/tests/rejected.test.ts 验证了默认返回undefined、无删除时返回空数组、以及链式选择器如.parent1 p、[href^#]被逐条记录的行为。rejectedCss默认 false保留被丢弃的 CSS如果希望把被移除的 CSS 保留下来另作他用例如生成单独的废弃样式文件使用rejectedCss: trueawait new PurgeCSS().purge({ content: [index.html, **/*.js, **/*.html, **/*.vue], css: [css/app.css], rejectedCss: true })实现上evaluateRule会把同一规则内被删除的 selectors 收集起来克隆节点并重组为一个只含被移除选择器的规则推入this.removedNodes见 packages/purgecss/src/index.tsgetPurgedCSS再用postcss.root({ nodes: this.removedNodes })序列化出完整的被删 CSS 字符串见 packages/purgecss/src/index.ts。测试 packages/purgecss/tests/rejectedCss.test.ts 还覆盖了media内部分规则被删时父节点结构保持正确的边界情况。rejected与rejectedCss可同时开启此时rejectedCss中会包含rejected列表对应的选择器。safelist让指定选择器安全保留safelist用于指示哪些选择器应留在最终 CSS 中即使内容中并未出现它们。该选项有两种形式。数组形式简单形式可同时混用字符串与正则safelist: [random, yep, button, /^nav-/]复杂对象形式safelist: { standard: [random, yep, button, /^nav-/], deep: [], greedy: [], keyframes: [], variables: [] }具体示例数组形式的standard条目按字符串完全匹配.random、#yep、button都会被保留const purgecss await new PurgeCSS().purge({ content: [], css: [], safelist: [random, yep, button] })而正则条目按test()匹配例如/red$/会保留.bg-red这类以red结尾的选择器const purgecss await new PurgeCSS().purge({ content: [], css: [], safelist: [/red$/] })从源码看purge与setOptions都会调用standardizeSafelist把用户输入统一成含standard、deep、greedy、keyframes、variables五字段的完整对象见 packages/purgecss/src/index.ts。判定保留的核心逻辑在shouldKeepSelectorpackages/purgecss/src/index.ts字符串条目与 selector 全量相等才保留正则条目调用test()命中即保留见isSelectorSafelistedpackages/purgecss/src/index.ts。另外内部安全列表CSS_SAFELISTpackages/purgecss/src/internal-safelist.ts以及::开头的伪元素会无条件保留。测试用例 packages/purgecss/tests/safelist.test.ts 验证了字符串 safelist 与正则 safelist 的实际效果。safelist.deep按正则保留选择器及其后代safelist.deep基于正则匹配保留匹配到的选择器及其所有子选择器const purgecss await new PurgeCSS().purge({ content: [], css: [], safelist: { deep: [/red$/] } })例如.bg-red .child-of-bg会被整体保留即使child-of-bg从未在内容中出现。原因是shouldKeepSelector会遍历 selector 的每个组成部分只要某一节命中了deep正则便立即返回true见 packages/purgecss/src/index.ts 与isSelectorSafelistedDeeppackages/purgecss/src/index.ts。测试 packages/purgecss/tests/safelist.test.ts 使用deep: [/^card$/]验证了.card .content、.card .btn .yellow等后代选择器全部保留。safelist.greedy按正则整条保留选择器safelist.greedy更激进只要 selector 的任意一部分命中正则整条 selector 就原样保留const purgecss await new PurgeCSS().purge({ content: [], css: [], safelist: { greedy: [/red$/] } })例如button.bg-red.nonexistent-class会被完整保留即便button与nonexistent-class都未在内容中出现。实现上shouldKeepSelector会先把 selector 拆成各个组成部分selector.nodes.map(this.getSelectorValue)任一部件命中 greedy 正则即返回true见 packages/purgecss/src/index.ts。测试 packages/purgecss/tests/safelist.test.ts 使用greedy: [/data-v-.*/]验证了.card[data-v-test].card--large这类组合选择器被整条保留而未命中的.card.card--large则被移除。blocklist强制移除指定选择器blocklist与safelist相反会强制把指定选择器从最终输出中移除——即使 PurgeCSS 判定它们被使用blocklist: [usedClass, /^nav-/]即使nav-links与usedClass都被 extractor 提取到了它们仍会被删除。字符串按 selector 完全相等匹配正则按test()匹配判定逻辑见isSelectorBlocklistedpackages/purgecss/src/index.ts且在shouldKeepSelector中 blocklist 的优先级高于 safelist命中 blocklist 会直接返回false见 packages/purgecss/src/index.ts。测试 packages/purgecss/tests/safelist.test.ts 验证了blocklist: [h1, yep, button, /nav-/]会把nav-blue、nav-red一并删除而未列入 blocklist 的.random正常保留。skippedContentGlobs排除部分 content 扫描范围当content使用 glob 时skippedContentGlobs可以排除其中某些文件或目录。注意当content不是 glob即全为真实文件路径时该选项不生效。skippedContentGlobs: [node_modules/**, components/**]上例中PurgeCSS 不会扫描node_modules与components目录下的任何内容。在源码里extractSelectorsFromFiles与getPurgedCSS的glob.sync调用都传入ignore: this.options.skippedContentGlobs见 packages/purgecss/src/index.ts 与 packages/purgecss/src/index.ts。测试 packages/purgecss/tests/skipped-content.test.ts 验证了排除skippedFolder/**后该目录内 HTML 引用的.green被判定为未使用并从 CSS 中移除。dynamicAttributes补充动态属性选择器白名单dynamicAttributes用于追加自定义的属性选择器名称例如aria-selected、data-selected等让 PurgeCSS 在判定属性选择器时将其视为动态存在dynamicAttributes: [aria-selected]实现上shouldKeepSelector处理attribute类型节点时会把dynamicAttributes与内置的value、checked、selected、open合并成一个白名单命中即认为属性存在见 packages/purgecss/src/index.ts。其原因是这些属性的取值会随用户交互动态变化无法仅凭静态内容判断因此默认就予以保留如果你的应用使用了其他动态属性可通过该选项加入白名单。配置合并顺序与默认值速查综合 packages/purgecss/src/options.ts 与purge/setOptions/getOptions的实现配置生效顺序为内置defaultOptions提供全部默认值若传入配置文件或 CLI--config用setOptions加载并覆盖默认值若以对象形式调用purge(userOptions)对象字段覆盖默认值CLI 场景下命令行参数再覆盖配置文件。常用选项默认值速查表选项默认值说明content/css[]必填的分析内容与待清理样式defaultExtractor/\[A-Za-z0-9_-\]/g兜底提取器extractors[]按扩展名定制的提取器fontFacefalse是否移除未使用的font-facekeyframesfalse是否移除未使用的keyframesvariablesfalse是否移除未使用的 CSS 变量rejectedfalse是否返回被移除选择器列表rejectedCssfalse是否返回被丢弃的 CSSstdin/stdoutfalseCLI 管道输入/输出模式safelist五字段空对象保留选择器白名单blocklist[]强制删除黑名单skippedContentGlobs[]跳过扫描的 globdynamicAttributes[]动态属性白名单CLI 与配置文件的对应关系配置文件的每个选项几乎都能在 CLI 上找到对应参数定义见 packages/purgecss/src/bin.ts--content files...、--css files...、--config path、--output path、--font-face、--keyframes、--variables、--rejected、--rejected-css、--safelist list...、--blocklist list...、--skippedContentGlobs list...。CLI 还支持-作为--content/--css的值从标准输入读取原始内容见 packages/purgecss/src/bin.ts。两种典型用法对比# 方式一纯命令行参数 purgecss --css css/app.css --content index.html **/*.js --keyframes --font-face # 方式二配置文件 命令行覆盖 purgecss --config ./purgecss.config.js --variables注意 CLI 的--safelist只接受字符串列表内部通过standardizeSafelist转为standard字段复杂形式的deep、greedy、keyframes、variablessafelist 只能写在配置文件中。小结PurgeCSS 的配置体系围绕内容提取 样式清理 保留/排除控制三条主线展开content/css定义输入extractors/defaultExtractor决定提取精度fontFace/keyframes/variables控制三类特殊语法的清理safelist含deep/greedy与blocklist提供保留与删除的精确控制rejected/rejectedCss则服务于调试与结果审计。理解这些选项与源码中shouldKeepSelector、getPurgedCSS等核心方法的对应关系你就能针对具体项目写出既安全又高压缩率的 PurgeCSS 配置。赞分享前端构建工具【免费下载链接】purgecssRemove unused CSS项目地址https://gitcode.com/gh_mirrors/pu/purgecss点击查看免费下载相关推荐Gatsby Source WordPress 插件配置完全指南gatsby-source-wordpress 全部 Plugin Options 详解与实战调优Gatsby Source WordPress 插件配置完全指南gatsby source wordpress 全部 Plugin Options 详解与实战前端静态站点Web框架rqlite 配置完全指南rqlited 全部命令行参数详解与集群实战rqlite 配置完全指南rqlited 全部命令行参数详解与集群实战 rqlite 是一个以 SQLite 为存储引擎的轻量级、容错的分布式关系数据库。本文数据库分布式数据库关系型数据库osquery 部署配置完全指南从 options、Schedule 到 Query Packs 与配置规范详解osquery 部署配置完全指南从 options、Schedule 到 Query Packs 与配置规范详解 本指南以 osquery 官方部署文档 do观测代理网络安全上一篇终极解决方案sguard_limit让你的腾讯游戏告别卡顿性能飙升50%下一篇WarcraftHelper让经典魔兽争霸3在现代电脑上焕发新生的3大秘诀创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
