# @freddy38510/dropcss 中文文档

规范地址：https://npmcn.com/package/%40freddy38510/dropcss/

版本：2\.5\.0
npm 元数据更新时间：2023-02-23T15:57:35.273Z
中文译文更新时间：2026-11-15T16:07:20.922Z
软件包许可：MIT

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40freddy38510/dropcss
原文对照：https://npmcn.com/package/%40freddy38510/dropcss/?lang=original
项目主页：https://github.com/leeoniya/dropcss
源码仓库：https://github.com/leeoniya/dropcss

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：81.1 kB，10 个文件
- 模块格式：ESM + CJS
- TypeScript 类型：包内自带
- 运行依赖：0 个
- 首次发布：2021-06-29T16:18:15.064Z
- 最新版本发布：2023-02-23T15:57:35.149Z
- 近 30 天下载量：2420（2026-10-16 至 2026-11-14，npm 官方下载统计）
- 已发布版本数：7（近 12 个月 0 个）

## 中文简介

一个特别快、彻底和微小的未使用CSS清洁器

## 安装

```sh
npm install @freddy38510/dropcss
```

也可以使用：`pnpm add @freddy38510/dropcss`、`yarn add @freddy38510/dropcss`、`bun add @freddy38510/dropcss`

## README

## 空投控制系统

一个 [特别快](https://npmcn.com/package/%40freddy38510/dropcss/#readme-performance)彻底而微小([~10 KB 分钟](https://github.com/leeoniya/dropcss/tree/master/dist/dropcss.iife.min.js)(未使用的CSS清洁剂) _(麻省理工学院许可)_

* * *

### 导言

DropCSS 将您的 HTML 和 CSS 作为输入, 只返回使用的 CSS 作为输出 。 它的自定义 HTML 和 CSS 解析器高度优化了99%的使用大小写,从而避免了处理错误的标记或样式表的间接费用,因此需要很好的输入. 对复杂的逃逸规则的处理很少,因此总是会有无法由DropCSS处理的有效输入的情况;对于这些不常见的情况,请 [开始讨论](https://github.com/leeoniya/dropcss/issues)。当 HTML 特性允许时 `html`, (中文(简体) ), `head`, (中文(简体) ), `body` 财务报告和审定财务报表 `tbody` dropCSS 将不作这样的假设; 选择器将只保留给可从提供的标记中解析的标记.

通过一个结构优化器来运行你的CSS也是个好主意 [干净](https://github.com/jakubpawlowicz/clean-css), (中文(简体) ), [顺位](https://github.com/css/csso), (中文(简体) ), [克斯纳诺](https://github.com/cssnano/cssnano) 或者说 [疯子](https://github.com/mattbasta/crass) 以重新分组选择者,合并冗余规则等。 在DropCSS之后这样做也许有道理,因为DropCSS会留下多余的块,例如. `.foo, .bar { color: red; } .bar { width: 50%; }` - > (中文) `.bar { color: red; } .bar { width: 50%; }` 若为 `.foo` 正在离开你的标记.

更多关于这个项目的背面故事和讨论:v0.1.0 alpha: [/r/javascript](https://old.reddit.com/r/javascript/comments/b3mcu8/dropcss_010_a_minimal_and_thorough_unused_css/), (中文(简体) ), [黑客新闻](https://news.ycombinator.com/item?id=19469080) 和 v1.0.0 发布 : [/r/javascript](https://old.reddit.com/r/javascript/comments/bb7im2/dropcss_v100_an_exceptionally_fast_thorough_and/)。 。 。 .

* * *

### 现场德莫: [https://codepen.io/leeoniya/pen/LvbRyq 页面存档备份,存于互联网档案馆](https://codepen.io/leeoniya/pen/LvbRyq)

* * *

### 安装

```
npm install -D dropcss
```

* * *

### 用法 & API

```js
const dropcss = require('dropcss');

let html = `
    <html>
        <head></head>
        <body>
            <p>Hello World!</p>
        </body>
    </html>
`;

let css = `
    .card {
      padding: 8px;
    }

    p:hover a:first-child {
      color: red;
    }
`;

const whitelist = /#foo|\.bar/;

let dropped = new Set();

let cleaned = dropcss({
    html,
    css,
    shouldDrop: (sel) => {
        if (whitelist.test(sel))
            return false;
        else {
            dropped.add(sel);
            return true;
        }
    },
});

console.log(cleaned.css);

console.log(dropped);
```

这个 `shouldDrop` 钩对无法匹配的 CSS 选择器 `html`返回时 `false` 以保留选择器或 `true` 放弃它.

* * *

### 特征

-   支持的选择者
    
    | 常见 | 属性 | 立场 | 位置(类型) | 其它 |
    | --- | --- | --- | --- | --- |
    | `*` - 普遍性  
    `<tag>` - 标签  
    `#` - 编号  
    `.` - 类  
      - 后裔  
    `>` - 儿童  
    `+` - 相邻的兄弟  
    `~` - 将军兄弟 | `[attr]`  
    `[attr=val]`  
    `[attr*=val]`  
    `[attr^=val]`  
    `[attr$=val]`  
    `[attr~=val]` | `:first-child`  
    `:last-child`  
    `:only-child`  
    `:nth-child()`  
    `:nth-last-child()` | `:first-of-type`  
    `:last-of-type`  
    `:only-of-type`  
    `:nth-of-type()`  
    `:nth-last-of-type()` | `:not()`  
    `:is()`  
    `:has()` |
    
-   保留所有无法从解析的 HTML 中决定性地检查的瞬态伪类和伪元素选择器 .
    
-   清除未使用 `@font-face` 财务报告和审定财务报表 `@keyframes` 块.
    
-   清除未使用 [CSS 变量](https://developer.mozilla.org/en-US/docs/Web/CSS/--*)。 。 。 .
    
-   深入解析综合CSS变量,例如:
    
    ```css
    :root {
      --font-style: italic;
      --font-weight: bold;
      --line-height: var(--height)em;
      --font-family: 'Open Sans';
      --font: var(--font-style) var(--font-weight) 1em/var(--line-height) var(--font-family);
      --height: 1.6;
    }
    
    @font-face {
      font-family: var(--font-family);
      src: url("/fonts/OpenSans-Regular-webfont.woff2") format("woff2"),
           url("/fonts/OpenSans-Regular-webfont.woff") format("woff");
    }
    
    body {
      font: var(--font);
    }
    ```
    

* * *

### 业绩

#### 投入

**测试.html**

-   18.8 KB 改进
-   502个圆顶节点通过 `document.querySelectorAll("*").length`

**样式.min.css**

-   27.67 KB 组合、优化和精密化 [干净](https://github.com/jakubpawlowicz/clean-css)
-   内容: 靴子 [重新启动.css](https://github.com/twbs/bootstrap/blob/master/dist/css/bootstrap-reboot.css),一个内部弹性框网格,全局布局,导航栏,颜色和页面专用样式. (网格占起步重量的~85%,媒体查询和重复次数很多)

#### 产出

|  | 自由大小w/ deps | 输出大小 | 减少 | 时间过后 | 未使用的字节( test.html 覆盖) |
| --- | --- | --- | --- | --- | --- |
| **调试CSS** | 58.4 KB (韩语)  
6个文件, 2个文件夹 | 6.58 KB (韩语) | 76.15% | 21分钟 | 575个/ 8.5% |
| [失败](https://github.com/uncss/uncss) | 13.5 甲基溴  
2 829个文件, 301个文件夹 | 6.72 KB (韩语) | 75.71% | 385分钟 | 638%/9.3% |
| [清洗器](https://github.com/FullHuman/purgecss) | 2.69 甲基溴  
560个文件, 119个文件夹 | 8.01 KB (韩语) | 71.05% (中文(简体) ) | 88分钟 | 1 806个/ 22.0% |
| [净化CSS](https://github.com/purifycss/purifycss) | 3.46 甲基溴  
792个文件, 207个文件夹 | 15.46 KB (韩语) | 44.34% | 173分钟 | 9,440人/59.6% 妇女 |

**页:1**

-   大约400个"未被使用的字节"是由于一个明确的/共享的白名单,而不是由于工具无法检测/移动CSS.
-   大约175个"未被使用的字节"是由于销售商前置(-moz,-ms)属性和选择器在Chrome中不活动,用于测试覆盖.
-   清洗不支持属性或复杂选择器 : [问题110](https://github.com/FullHuman/purgecss/issues/110)。 。 。 .

满 **[压力测试](https://github.com/leeoniya/dropcss/tree/master/test/bench)** 还提供.

* * *

### Java 脚本执行

DropCSS 不装入外部资源或执行 `<script>` 标记,所以您的 HTML 必须完全形成( 或 SSR' d) 。 或者,你可以使用 [傀儡](https://github.com/GoogleChrome/puppeteer) 和本地的 http 服务器以获得充电 `<script>` 执行.

[这是35行脚本](https://npmcn.com/demos/puppeteer/index.js) 具体是:

```js
const httpServer = require('http-server');
const puppeteer = require('puppeteer');
const fetch = require('node-fetch');
const dropcss = require('dropcss');

const server = httpServer.createServer({root: './www'});
server.listen(8080);

(async () => {
    const browser = await puppeteer.launch();
    const page = await browser.newPage();
    await page.goto('http://127.0.0.1:8080/index.html');
    const html = await page.content();
    const styleHrefs = await page.$$eval('link[rel=stylesheet]', els => Array.from(els).map(s => s.href));
    await browser.close();

    await Promise.all(styleHrefs.map(href =>
        fetch(href).then(r => r.text()).then(css => {
            let start = +new Date();

            let clean = dropcss({
                css,
                html,
            });

            console.log({
                stylesheet: href,
                cleanCss: clean.css,
                elapsed: +new Date() - start,
            });
        })
    ));

    server.close();
})();
```

* * *

### 累积白名单

或许您想要取出一个巨大的 CSS 文件, 并针对多个 HTML 源对其进行清除, 从而保留 HTML 源中出现的任何选择器 。 在使用 Puppeteer 来引用不同的应用程序状态时,这也适用,以确保DropCSS在清理 CSS 之前将每个状态都考虑在内. 这个想法相当简单:

1.  运行 DropCSS 以对抗 HTML 源 .
2.  从每个结果中累积出一个白名单.
3.  在空的 HTML 字符串下运行 DroppCSS, 只依靠累积的白名单 .

见 [/减少/累积.js](https://npmcn.com/demos/accumulate.js)数字 :

```js
const dropcss = require('dropcss');

// super mega-huge combined stylesheet
let css = `
    em {
        color: red;
    }

    p {
        font-weight: bold;
    }

    .foo {
        font-size: 10pt;
    }
`;

// html of page (or state) A
let htmlA = `
    <html>
        <head></head>
        <body>
            <em>Hello World!</em>
        </body>
    </html>
`;

// html of page (or state) B
let htmlB = `
    <html>
        <head></head>
        <body>
            <p>Soft Kitties!</p>
        </body>
    </html>
`;

// whitelist
let whitelist = new Set();

function didRetain(sel) {
    whitelist.add(sel);
}

let resA = dropcss({
    css,
    html: htmlA,
    didRetain,
});

let resB = dropcss({
    css,
    html: htmlB,
    didRetain,
});

// final purge relying only on accumulated whitelist
let cleaned = dropcss({
    html: '',
    css,
    shouldDrop: sel => !whitelist.has(sel),
});

console.log(cleaned.css);
```

* * *

### 特殊/ 逃脱顺序

DropCSS很愚蠢,会像大众一样,对不寻常的选手窒息 [尾风 CSS](https://github.com/tailwindcss/tailwindcss) 框架:

`class` 属性可以看起来像:

```html
<div class="px-6 pt-6 overflow-y-auto text-base lg:text-sm lg:py-12 lg:pl-6 lg:pr-8 sticky?lg:h-(screen-16)"></div>
<div class="px-2 -mx-2 py-1 transition-fast relative block hover:translate-r-2px hover:text-gray-900 text-gray-600 font-medium"></div>
```

...CSS是这样的:

```css
.sticky\?lg\:h-\(screen-16\){...}
.lg\:text-sm{...}
.lg\:focus\:text-green-700:focus{...}
```

哎哟.

解决方案是将 HTML 和 CSS 中的已逃出字符临时替换为一些匹配的独有字符串 `/[\w-]/`。这使得 DroppCSS 的标注器能够将类名视为一个相接的东西。 经过处理后,我们只需扭转操作.

```js
// remap
let css2 = css
    .replace(/\\\:/gm, '__0')
    .replace(/\\\//gm, '__1')
    .replace(/\\\?/gm, '__2')
    .replace(/\\\(/gm, '__3')
    .replace(/\\\)/gm, '__4');

let html2 = html.replace(/class=["'][^"']*["']/gm, m =>
    m
    .replace(/\:/gm, '__0')
    .replace(/\//gm, '__1')
    .replace(/\?/gm, '__2')
    .replace(/\(/gm, '__3')
    .replace(/\)/gm, '__4')
);

let res = dropcss({
    css: css2,
    html: html2,
});

// undo
res.css = res.css
    .replace(/__0/gm, '\\:')
    .replace(/__1/gm, '\\/')
    .replace(/__2/gm, '\\?')
    .replace(/__3/gm, '\\(')
    .replace(/__4/gm, '\\)');
```

这个表演的绕行工作可以让DroppCSS在不出问题的情况下处理 Tailwind \\o/,并且容易适应支持其他"感兴趣的"案例. 记住一件事 `shouldDrop()` 将调用含有临时替换的选取器,而不是原选取器,因此如果 `shouldDrop()` 用于测试某些白名单.

* * *

### 洞穴

-   未测试或设计用于处理不正确的 HTML 或 CSS
-   在您的 HTML 或 CSS 中过度逃出或保留字符可以打破 DroppCSS 的解析器

* * *

### 鸣谢

-   费利克斯·伯姆 [检查](https://github.com/fb55/nth-check) - 这不是很多代码,但得到 `An+B` 表达式测试完全正确令人沮丧。 在发现这个微小的解决方案之前,我得到了一部分.
-   瓦迪姆·基鲁克欣的 [虚拟化](https://github.com/vkiryukhin/vkBeautify) - 基准和测试代码使用这个微小的前置物,从而更容易发现输出diffs的差异.

## 常见问题

### @freddy38510/dropcss 是什么？

一个特别快、彻底和微小的未使用CSS清洁器

### 如何安装 @freddy38510/dropcss？

在项目目录运行 npm install @freddy38510/dropcss，或使用 pnpm add / yarn add / bun add。

### @freddy38510/dropcss 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### @freddy38510/dropcss 支持 ESM 还是 CommonJS？

同时提供 ES Module 与 CommonJS 入口，import 和 require\(\) 都可以使用，打包工具会自动选择合适的版本。

### @freddy38510/dropcss 可以商用吗？

@freddy38510/dropcss 使用 MIT 许可。宽松许可：允许商业使用、修改和再分发，通常只需在分发时保留原版权与许可声明。以上为概括，不构成法律意见，请以许可原文为准。

### @freddy38510/dropcss 的下载量有多少？

根据 npm 官方下载统计，@freddy38510/dropcss 在 2026/10/16 – 2026/11/14 这 30 天内被下载 2,420 次，日均约 81 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @freddy38510/dropcss 还在维护吗？

最新版本 2\.5\.0 发布于 2023/02/23（3 年前）；至今共发布 7 个版本，其中过去 12 个月发布了 0 个；首次发布于 2021/06/30。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

