Tailwind CSS 生产优化

2022-07-26 09:35 更新

生产优化

从您的生产构建中移除未使用的 CSS,以获得最佳性能。


使用默认配置,TailwindCSS 的开发版本是3645.2kB未压缩,294.2kB用Gzip进行压缩,72.8kB用Brotli进行压缩。

Uncompressed Minified Gzip Brotli
3645.2kB 2936.0kB 294.2kB 72.8kB

这听起来可能很庞大,那是因为设计就很庞大。

为了使开发经验尽可能的富有成效,Tailwind 为您生成了成千上万的功能类,其中大部分您可能不会真正使用。

把 Tailwind 想象成一个巨大的乐高盒子—您把它倾倒在地板上,建造您想建造的东西,然后当您完成后,您把所有您不用的碎片放回盒子里。

例如,Tailwind 为您的间距尺度中的每一个尺寸,为您可能想要应用边距的元素的每一个侧面,在您的项目中使用的每一个断点生成边距实用程序。这导致了数以百计的不同组合,这些组合都是重要的,但不可能都是需要的。

当构建生产时,您应该总是使用 Tailwind 的 ​purge ​选项来 tree-shake 优化未使用的样式,并优化您的最终构建大小当使用 Tailwind 删除未使用的样式时,很难最终得到超过 10kb 的压缩 CSS。

编写可清除的 HTML

在开始使用 ​Purge ​功能之前,重要的是要了解它是如何工作的,并建立正确的心理模型,以确保您在为生产构建时永远不会意外地删除重要的样式。

PurgeCSS(我们在引擎下使用的库)在寻找 HTML 中的类的方式上故意非常幼稚。它并不试图解析您的 HTML 并查找类的属性,也不动态执行您的 JavaScript —它只是在整个文件中查找符合这个正则表达式的任何字符串。

  /[^<>"'`\s]*[^<>"'`\s:]/g

这基本上可以匹配任何由空格、引号或角括号分隔的字符串,包括 HTML 标签、属性、类,甚至是您标记中的实际书面内容。

<div class="md:flex">
  <div class="md:flex-shrink-0">
    <img class="rounded-lg md:w-56" src="/img/shopping.jpg" alt="Woman paying for a purchase">
  </div>
  <div class="mt-4 md:mt-0 md:ml-6">
    <div class="uppercase tracking-wide text-sm text-indigo-600 font-bold">
      Marketing
    </div>
    <a href="/get-started" class="block mt-1 text-lg leading-tight font-semibold text-gray-900 hover:underline">
      Finding customers for your new business
    </a>
    <p class="mt-2 text-gray-600">
      Getting a new business off the ground is a lot of hard work.
      Here are five ideas you can use to find your first customers.
    </p>
  </div>
</div>

这意味着,重要的是避免在您的模板中使用字符串连接动态创建类字符串,否则 PurgeCSS 将不知道保存这些类。

不要使用字符串连接来创建类名

<div class="text-{{  error  ?  'red'  :  'green'  }}-600"></div>

动态选择一个完整的类名

<div class="{{  error  ?  'text-red-600'  :  'text-green-600'  }}"></div>

只要一个类名出现在您的模板中,PurgeCSS 就不会删除它。

删除未使用的CSS

基本用途

要开始使用,请使用 ​purge ​选项为您所有的模板文件提供一个路径数组。

// tailwind.config.js
module.exports = {
  purge: [
    './src/**/*.html',
    './src/**/*.vue',
    './src/**/*.jsx',
  ],
  theme: {},
  variants: {},
  plugins: [],
}

例如,如果您的项目中有一个 JS 文件,在您的 HTML 中动态切换一些类,您应该确保在这个列表中包括该文件。

现在,每当您在编译 CSS 时将 ​NODE_ENV ​设置为 ​production​,Tailwind 将自动从您的 CSS 中清除未使用的样式。

手动启用

如果您想手动控制是否应该删除未使用的样式(而不是隐性地依赖环境变量),您可以使用一个对象语法,并提供 ​enabled ​选项,使用 ​content ​选项指定您的模板。

// tailwind.config.js
module.exports = {
  purge: {
    enabled: true,
    content: ['./src/**/*.html'],
  },
  // ...
}

我们建议只在生产中移除未使用的样式,因为在开发中移除它们意味着您需要在任何时候改变您的模板时重新编译,并且在启用 PurgeCSS 的情况下编译速度要慢得多。

将特定类列入安全列表

如果您需要将特定类列入安全列表以确保它们不会被意外从 CSS 中删除(可能是因为它们用于来自数据库或类似内容的内容中),您可以使用我们的顶级 ​safelist​ 选项:

// tailwind.config.js
module.exports = {
  purge: {
    content: ['./src/**/*.html'],
    safelist: [
      'bg-blue-500',
      'text-center',
      'hover:opacity-100',
      // ...
      'lg:text-right',
    ]
  },
  // ...
}

转换内容

有时您正在以一种可编译为 HTML 的格式创作内容,最好先将该内容编译为 HTML,然后再寻找潜在的类。一个很好的例子是使用 markdown 文件。

您可以使用 ​transform ​选项告诉 Tailwind 在查找类之前转换与特定扩展名匹配的任何文件以保证最准确的结果:

// tailwind.config.js
let remark = require('remark')

module.exports = {
  purge: {
    content: ['./src/**/*.{html,md}'],
    transform: {
      md: (content) => {
        return remark().process(content)
      }
    }
  },
  // ...
}

自定义提取逻辑

如果您需要覆盖 Tailwind 用于检测特定文件类型内容中的类的逻辑,您可以使用 ​extract ​选项提供一个函数,该函数将用于检测匹配文件中的潜在类:

// tailwind.config.js
module.exports = {
  purge: {
    content: ['./src/**/*.{html,md}'],
    extract: {
      md: (content) => {
        return content.match(/[^<>"'`\s]*/)
      }
    }
  },
  // ...
}

这是一项高级功能,大多数用户不需要它。 Tailwind 中的默认提取逻辑适用于几乎所有项目。

保留 HTML 元素

默认情况下,Tailwind 将保留所有基本的 HTML 元素样式在您的 CSS 中,如 ​html​,​body​,​p​,​h1 ​等标签的样式。这是为了减少意外的过度清洗,例如在您使用 markdown 源文件的情况下(其中没有实际的 ​h1 ​标签),或者使用一个框架将文档外壳(包含 ​html ​和 ​body ​标签)隐藏在供应商目录的某个地方(像 Next.js 那样)。

如果您想禁止这种行为,您可以将 ​preserveHtmlElements ​设置为 false。

// tailwind.config.js
module.exports = {
  purge: {
    preserveHtmlElements: false,
    content: ['./src/**/*.html'],
  },
  // ...
}

清理特定层

默认情况下,Tailwind 将清除 ​base ​、​components ​和 ​utilities ​层中的所有样式。如果您想更改此设置,请使用 ​layers​ 选项手动指定您要清除的图层:

// tailwind.config.js
module.exports = {
  purge: {
    layers: ['components', 'utilities'],
    content: ['./src/**/*.html'],
  },
  // ...
}

移除所有未使用到的 styles

默认情况下,Tailwind 将只删除它自己生成的未使用的类,或者被明确地包裹在 ​@layer​ 指令中。它不会从第三方 CSS 中移除未使用的样式,比如您拉到您的项目中的 datepicker 库。

/* These styles will all be purged */
@tailwind base;
@tailwind components;
@tailwind utilities;

/* These styles will be purged */
@layer components {
  .btn { /* ... */ }
}

/* These styles will not be purged */
.flatpickr-innerContainer { /* ... */ }
.flatpickr-weekdayContainer { /* ... */ }
.flatpickr-weekday { /* ... */ }

这是为了避免意外地删除那些您可能需要的但在模板中没有直接引用的样式,比如那些只在 ​node_modules ​文件夹深处引用的类,它们是其他依赖关系的一部分。

如果您真的想删除所有未使用的样式,设置 ​mode: 'all'​ 和 ​preserveHtmlElements: false​,并且要非常小心地提供可能引用任何类或HTML元素的所有文件的路径。

// tailwind.config.js
module.exports = {
  purge: {
    mode: 'all',
    preserveHtmlElements: false,
    content: [
      './src/**/*.js',
      './node_modules/flatpickr/**/*.js',
    ],
  },
  // ...
}

我们不推荐这样做,一般来说,您会发现坚持使用更保守的默认方法可以获得 99% 的文件大小的好处。

删除未使用的 keyframes

默认情况下,PurgeCSS 不会删除未使用的 ​@keyframes​ 规则,因此即使您没有使用它们,您也可能会注意到样式表中遗留了一些与动画相关的样式。您可以使用 ​options ​下的 PurgeCSS 的 ​keyframes ​选项删除这些:

// tailwind.config.js
module.exports = {
  purge: {
    content: ['./src/**/*.html'],
    options: {
      keyframes: true,
    },
  },
  // ...
}

PurgeCSS选项

如果你需要直接向PurgeCSS传递任何其他选项,你可以使用​options​来实现。

// tailwind.config.js
module.exports = {
  purge: {
    content: ['./src/**/*.html'],

    // These options are passed through directly to PurgeCSS
    options: {
      safelist: ['bg-red-500', 'px-4'],
      blocklist: [/^debug-/],
      keyframes: true,
      fontFace: true,
    },
  },
  // ...
}

可用的选项列表可以在 PurgeCSS 文档中找到。

其他办法

如果您因为某种原因不能使用 PurgeCSS,您也可以通过从您的配置文件中删除未使用的值来减少Tailwind的足迹。

默认的主题提供了一套非常慷慨的颜色,断点,大小,边距等,以确保当您把Tailwind拉下来做原型,创建一个 CodePen 演示,或者只是尝试一下工作流程,体验是尽可能的愉快和流畅。

我们不希望您不得不去写新的 CSS,因为我们没有提供足够的 padding helpers,或者因为您想为您的演示使用橙色方案,而我们只给您蓝色。

不过这也是有代价的:默认的构建要比在一个有专门配置文件的项目上要重得多。

以下是一些策略,您可以用它来保持您生成的 CSS 小而性能好。

限制您的调色板

默认的主题包含了高达 84 种颜色,用于背景、边框、文本和占位符,所有这些颜色都有 ​hover:​ 和 ​focus:​ 变体,以及六种默认屏幕尺寸的响应变体。

默认情况下,有成千上万的类生成以适应这些颜色,它占了最终构建大小的近一半。

很少有项目真正需要这么多颜色,删除不需要的颜色会对整体文件大小产生巨大影响。

以下是使用较小的调色板对最终大小的影响。

Colors Original Minified Gzip Brotli
84 (default) 3645.2kB 2936.0kB 294.2kB 72.8kB
50 2805.8kB 2231.3kB 238.7kB 59.3kB
25 2177.6kB 1702.8kB 198.3kB 50.6kB

删除未使用的断点

由于几乎每个 Tailwind 功能类都是为每一个屏幕尺寸复制的,所以使用较少的屏幕尺寸也会对整体文件大小产生巨大的影响。

以下是定义较少屏幕如何影响输出:

Breakpoints Original Minified Gzip Brotli
(default) 3645.2kB 2936.0kB 294.2kB 72.8kB
3 2395.9kB 1936.0kB 196.2kB 62.3kB
2 1781.4kB 1446.0kB 147.4kB 57.3kB
1 1167.3kB 956.3kB 98.6kB 52.5kB

如果您只需要 3 种屏幕尺寸和 35 种颜色,那么您可以在不更改任何其他内容的情况下将其压缩为 46.8kB 。

禁用未使用到的核心插件和变体

如果您不希望在您的项目中需要某个功能插件,您可以通过在配置文件的 ​corePlugins ​部分将其设置为 ​false ​来完全禁用它。

// tailwind.config.js
module.exports = {
  // ...
  corePlugins: {
    float: false
  }
}

如果您只需要少量的功能类,您可以向 ​corePlugins ​传递一个数组,其中包含您想保留的功能插件。

// tailwind.config.js
module.exports = {
  // ...
  corePlugins: [
    'margin',
    'padding'
  ]
}

以上将禁用除 margin 和 padding 以外的所有功能类。

如果需要一个功能类,但不需要响应式版本,将其变体设置为空数组,以减少 83% 的类生成。

module.exports = {
  // ...
  variants: {
    appearance: []
  }
}

与限制您的调色板或使用较少的断点相比,这些大多是小的优化,但它们仍然可以进一步减小构建体积。


以上内容是否对您有帮助:
在线笔记
App下载
App下载

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号