Tailwind CSS Just-in-Time Mode

2022-07-27 15:27 更新

Just-in-Time Mode

适用于 Tailwind CSS v2.1+ 的更快、更强大的按需引擎。


此功能目前处于预览阶段。语义版本控制未涵盖预览功能,并且随着我们不断完善它们,某些细节可能会发生变化。

Tailwind CSS v2.1 为 Tailwind CSS 引入了新的即时编译器,可在您创作模板时按需生成样式,而不是在初始构建时提前生成所有内容。

这有很多优点:

  • 闪电般的快速构建时间。使用我们的 CLI 最初编译 Tailwind 可能需要 3-8 秒,而在 webpack 项目中则需要 30-45 秒,因为 webpack 难以处理大型 CSS 文件。无论您使用什么构建工具,这个库甚至可以在大约 800 毫秒内编译最大的项目(增量重建速度最快 3 毫秒)。
  • 每个变体都是开箱即用的。由于文件大小的考虑,默认情况下通常不会启用 ​focus-visible​, ​active​, ​disabled ​等变体。由于此库按需生成样式,因此您可以随时使用所需的任何变体。你甚至可以像 ​sm:hover:active:disabled:opacity-75​ 一样堆叠它们。永远不要再次配置您的变体。
  • 无需编写自定义 CSS 即可生成任意样式。曾经需要一些不属于您的设计系统的超特定值,例如 ​top: -113px​ 用于古怪的背景图像?由于样式是按需生成的,因此您可以根据需要使用方括号表示法(如 ​top-[-113px]​)为此生成实用程序。也适用于变体,例如 ​md:top-[-113px]​。
  • 您的 CSS 在开发和生产中是相同的。由于样式是根据需要生成的,因此您无需清除未使用的样式以进行生产,这意味着您可以在所有环境中看到完全相同的 CSS。再也不用担心意外清除生产中的重要样式。
  • 开发中更好的浏览器性能。由于开发版本与生产版本一样小,因此浏览器不必解析和管理数兆字节的预生成 CSS。在具有大量扩展配置的项目中,这使开发工具的响应速度更快。

启用 JIT 模式

要启用即时模式,请在 ​tailwind.config.js ​文件中将 ​mode ​选项设置为 ​'jit'​:

  // tailwind.config.js
  module.exports = {
   mode: 'jit',
    purge: [
      // ...
    ],
    theme: {
      // ...
    }
    // ...
  }

由于 JIT 模式通过扫描模板文件按需生成 CSS,因此在 ​tailwind.config.js​ 文件中使用所有模板路径配置 ​purge ​选项至关重要,否则您的 CSS 将为空:

  // tailwind.config.js
  module.exports = {
    mode: 'jit',
   // These paths are just examples, customize them to match your project structure
   purge: [
     './public/**/*.html',
     './src/**/*.{js,jsx,ts,tsx,vue}',
   ],
    theme: {
      // ...
    }
    // ...
  }

现在,当您启动开发服务器或构建运行器时,Tailwind 将按需生成您的样式,而不是预先生成所有内容。

新的功能

所有变体均已启用

由于样式是按需生成的,因此无需配置每个核心插件可用的变体。

<input class="disabled:opacity-75">

您可以将 ​focus-visible​, ​active​, ​disabled​, ​even ​等变体与任何实用程序结合使用,而无需对 tailwind.config.js 文件进行任何更改。

可堆叠变体

所有变体都可以组合在一起,以轻松针对非常特定的情况,而无需编写自定义 CSS。

<button class="md:dark:disabled:focus:hover:bg-gray-400">

任意值支持

许多实用程序使用新的方括号表示法支持任意值,以表明您正在“breaking out”您的设计系统。

<!-- Sizes and positioning -->
<img class="absolute w-[762px] h-[918px] top-[-325px] right-[62px] md:top-[-400px] md:right-[80px]" src="/crazy-background-image.png">

<!-- Colors -->
<button class="bg-[#1da1f1]">Share on Twitter</button>

<!-- Complex grids -->
<div class="grid-cols-[1fr,700px,2fr]">
  <!-- ... -->
</div>

这对于构建像素完美的设计非常有用,其中有一些元素需要超特定的样式,例如营销网站上精心定位的背景图像。

动态值

请注意,在使用任意值时,您仍然需要编写可清除的 HTML,并且您的类需要作为完整的字符串存在,以便 Tailwind 正确检测它们。

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

<div className={`mt-[${size === 'lg' ? '22px' : '17px' }]`}></div>

动态选择一个完整的类名

<div className={ size === 'lg' ? 'mt-[22px]' : 'mt-[17px]' }></div>

Tailwind 不包括任何类型的客户端运行时,因此类名需要在构建时可静态提取,并且不能依赖于客户端上更改的任何类型的任意动态值。在这些情况下使用内联样式,或者将 Tailwind 与 Emotion 等 CSS-in-JS 库结合起来,如果它对您的项目有意义的话。

不能从动态值计算任意值

<div class="bg-[{{ userThemeColor }}]"></div>

对真正的动态或用户定义的值使用内联样式

<div style="background-color: {{ userThemeColor }}"></div>

带空格的值

同样重要的是要注意 CSS 类不能包含空格,这意味着您不能按原样使用 ​calc(100px - 4rem)​ 或 ​1fr 700px 2fr​ 之类的任意值。要在您的类名中使用这样的任意值,您需要删除 ​calc ​调用内容中的空格,并用 ​1fr 700px 2fr​ 等列表中的逗号替换空格。 Tailwind 会在 ​calc ​调用中自动为您重新引入空格,并在生成相应的 CSS 时将列表中的逗号替换为空格。

不要在任意值中使用空格

<div class="h-[calc(1000px - 4rem)]">...</div>
<div class="grid-cols-[1fr 700px 2fr]">...</div>

酌情删除空格或用逗号替换

<div class="h-[calc(1000px-4rem)]">...</div>
<div class="grid-cols-[1fr,700px,2fr]">...</div>

模棱两可的值

如果您将 CSS 变量用作任意值,它有时会导致类名对引擎来说不明确,例如:

<!-- Is this a font size utility, or a text color utility? -->
<div class="text-[var(--mystery-var)]">

在这些情况下,您可以通过在任意值前面加上类型名称来向引擎提供提示:

<div class="text-[color:var(--mystery-var)]">

支持的类型有:

  • length
  • color
  • angle
  • list

内置重要修饰符

你可以通过在开头添加一个 ​!​ 字符来使任何实用程序变得重要。

<p class="font-bold !font-medium">
  This will be medium even though bold comes later in the CSS.
</p>

!​ 总是出现在实用程序名称的开头,在任何变体之后,但在任何前缀之前。

<div class="sm:hover:!tw-font-bold">

这在您需要提高特异性的极少数情况下很有用,因为您与一些您无法控制的样式交战。原文:(This can be useful in rare situations where you need to increase specificity because you’re at war with some styles you don’t control.)

颜色不透明度速记

无需使用 ​bg-opacity-50​、​text-opacity-25​ 或 ​placeholder-opacity-40​ 等实用程序,JIT 引擎让您只需将不透明度添加到颜色的末尾:

 <div class="bg-red-500 bg-opacity-25">
 <div class="bg-red-500/25">

这意味着您现在可以在 Tailwind 中的任何位置更改颜色的不透明度,即使我们以前没有特定的不透明度实用程序,例如在渐变中:

<div class="bg-gradient-to-r from-red-500/50">

不透明度值取自您的 ​opacity ​比例,但您也可以使用方括号表示法使用任意不透明度值:

<div class="bg-red-500/[0.31]">

每边边框颜色

自 2017 年以来就提出请求,但由于文件大小的考虑而被遗漏,JIT 引擎最终增加了对独立设置元素每一侧的边框颜色的支持:

<div class="border-2 border-t-blue-500 border-r-pink-500 border-b-green-500 border-l-yellow-500">
  <!-- ... -->
</div>

伪元素变体

JIT 引擎添加了对样式伪元素的支持,例如 ​::before​、​::after​、​::first-letter​、​::first-line​、​::marker​ 和 ​::selection​。

<div class="before:block before:bg-blue-500 after:flex after:bg-pink-300">

当您在变体之前或之后添加任何内容时,​content ​属性会自动设置为 ​""​ 以确保元素实际上是可见的。要更改内容属性,请使用新的内容实用程序。

如前所述,我们还添加了对其他伪元素的支持,例如 ​::selection​,它允许您设置选定文本的样式:

<p class="selection:bg-yellow-300 ...">
  I'm yellow when you highlight me.
</p>

或者 ​::marker​ 伪元素,它允许您设置列表标记的样式:

<ul class="marker:text-gray-500">
  <li>Odio et sed.</li>
  <li>Voluptatem perferendis optio est id.</li>
  <li>Accusamus et aut odit.</li>
</ul>

内容实用程序

我们添加了新的 ​content-*​ 实用程序来设置 ​content ​属性——与新的 ​before ​和 ​after ​变体一起非常有用:

<div class="before:content-['hello'] before:block ...">

它们甚至支持 ​attr ​函数之类的东西,因此您可以引用存储在属性中的值:

<div data-content="hello world" class="before:content-[attr(data-content)] before:block ...">

详尽的伪类支持

除了 ​hover​, ​focus ​等现有内容之外,我们还添加了对我们认为有意义的每个伪类的支持,例如 ​required​, ​invalid​, ​placeholder-shown​ 等等。

<input class="invalid:border-red-500 ...">

以下是新伪类变体的完整列表:

  • only​ (for ​only-child​)
  • first-of-type
  • last-of-type
  • only-of-type
  • target
  • default
  • indeterminate
  • placeholder-shown
  • autofill
  • required
  • valid
  • invalid
  • in-range
  • out-of-range

插入符号颜色实用程序(Caret color utilities)

您现在可以使用新的 ​caret-{color}​ 实用程序在表单字段中设置光标的颜色:

<input class="caret-red-500">

这些可以使用 ​tailwind.config.js​ 文件的 ​theme ​部分中的 ​caretColor ​键进行自定义。

兄弟选择器变体(Sibling selector variants)

与我们多年来支持的基于父状态设置元素样式的 ​group-*​ 变体类似,您可以使用新的 ​peer-*​ 变体根据其先前兄弟元素之一的状态设置元素样式:

<label>
  <input type="checkbox" class="peer sr-only">
  <span class="h-4 w-4 bg-gray-200 peer-checked:bg-blue-500">
    <!-- ... -->
  </span>
  <!-- ... -->
</label>

只需使用 ​peer ​类标记您感兴趣的前一个同级,然后使用 ​peer-hover​、​peer-checked​、​peer-focus​ 等变体来根据该同级的状态设置元素的样式。

简化的变换、滤镜和背景滤镜组合(Simplified transform, filter, and backdrop-filter composition)

不再需要 ​transform​, ​filter ​和 ​backdrop-filter​ 类来“enable”它们各自的可组合实用程序集。

 <div class="transform scale-50 filter grayscale backdrop-filter backdrop-blur-sm">
 <div class="scale-50 grayscale backdrop-blur-sm">

现在,只要您使用任何相关的子实用程序,这些功能就会自动启用。

改变

我们将 JIT 引擎视为我们计划作为 Tailwind CSS v3.0 发布的内容的预览,因此在选择加入时需要考虑一些小的重大更改。我们真的不希望这些会影响很多人,但值得一读,尤其是当您注意到项目外观的任何细微差异时。

变体被一起渲染(Variants are rendered together)

在经典引擎中,实用程序变体在每个实用程序生成的 CSS 中组合在一起,如下所示:

/* Classic engine */

.bg-black { background-color: #000 }
.hover\:bg-black:hover { background-color: #000 }
.focus\:bg-black:focus { background-color: #000 }

/* ... */

.opacity-75 { opacity: 0.75 }
.hover\:opacity-75:hover { opacity: 0.75 }
.focus\:opacity-75:focus { opacity: 0.75 }

/* ... */

.translate-x-4 { --tw-translate-x: 1rem }
.hover\:translate-x-4:hover { --tw-translate-x: 1rem }
.focus\:translate-x-4:focus { --tw-translate-x: 1rem }

在 JIT 引擎中,变体按变体分组在一起:(In the JIT engine, variants are grouped together per variant:)

/* JIT engine */

.bg-black { background-color: #000 }
.opacity-75 { opacity: 0.75 }
.translate-x-4 { --tw-translate-x: 1rem }

/* ... */

.hover\:bg-black:hover { background-color: #000 }
.hover\:opacity-75:hover { opacity: 0.75 }
.hover\:translate-x-4:hover { --tw-translate-x: 1rem }

/* ... */

.focus\:bg-black:focus { background-color: #000 }
.focus\:opacity-75:focus { opacity: 0.75 }
.focus\:translate-x-4:focus { --tw-translate-x: 1rem }

这意味着不能再为每个核心插件指定变体顺序——所有实用程序的变体将始终处于相同的顺序。如果您以前需要 ​hover ​来取消 ​focus ​以获取特定实用程序并确保 ​hover ​在变体列表中位于 ​focus ​之后,这对您来说可能是个问题。

 // tailwind.config.js
  module.exports {
    // Variant configuration (including order) is not respected by the JIT engine
   variants: {
     // ...
     backgroundColor: ['focus', 'hover']
   }
  }

要使用 JIT 引擎处理这些情况,我们建议使用堆叠变体:(To handle these situations with the JIT engine, we recommend using stacked variants instead:)

<!-- This ensures the element is blue on hover, even if it's also focused -->
<div class="focus:bg-red-500 hover:bg-blue-500 hover:focus:bg-blue-500">

堆叠变体允许您指定当多个变体同时处于活动状态时应如何设置样式,因此您无需尝试使用 ​hover ​样式覆盖 ​focus ​样式,而是显式声明当 ​hover ​和 ​focus ​同时处于活动状态时元素的外观。

变体在@tailwind 变体中插入(Variants are inserted at @tailwind variants)

在经典引擎中,所有实用程序变体都作为 ​@tailwind utilities​ 指令的一部分注入。

在 JIT 引擎中,变体在 ​@tailwind variants​ 指令中注入,该指令已从 ​@tailwind screens​ 重命名。

该指令是可选的(就像 ​@tailwind screens​ 一样),并且仅在您想要显式控制实用程序变体的注入位置时才有用。默认情况下,它们总是在样式表的最后注入。

如果您之前使用过 ​@tailwind screens​,则应更新代码以使用 ​@tailwind variants​:

 @tailwind base;
  @tailwind components;
  @tailwind utilities;
 @tailwind screens;
 @tailwind variants;

  /* Some custom CSS... */

@tailwind variants​ 功能被认为是一个高级避风港,我们建议默认省略它。只有当你的项目在没有它的情况下无法正常工作时,你才应该使用它,而这只有在你将 Tailwind 引入到一个传统的系统时才是真的,这个系统有一个非常脆弱的现有CSS代码库,它的样式绝对需要在样式表的最末端才能工作。

不需要显式启用转换和过滤器

使用 JIT 引擎时,不需要 ​transform​, ​filter ​和 ​backdrop-filter​ 类来 "enabling" 这些功能:

 <div class="transform scale-50 filter grayscale backdrop-filter backdrop-blur-sm">
 <div class="scale-50 grayscale backdrop-blur-sm">

这意味着您不能再期望 transforms 和 filters 默认处于休眠状态,并通过添加 ​transform​, ​filter ​或 ​backdrop-filter​ 有条件地激活。

(This means you can no longer expect transforms and filters to be dormant by default, and conditionally activated by adding transform, filter, or backdrop-filter.)

相反,您需要将任何变体放在子实用程序本身上:

 <div class="scale-105 -translate-y-1 hover:transform">
 <div class="hover:scale-105 hover:-translate-y-1">

限制

这个新引擎几乎支持经典引擎中存在的所有功能,再加上大量的新功能,如果所有的东西都要预先生成,那是不可能的。

然而,由于引擎工作方式的性质,有一些事情目前是不可能的。

  • safelist​ 选项不支持正则表达式。因为默认情况下没有生成CSS,所以 safelist 必须是一个完整的类名的列表。不可能用正则表达式来做安全列表,因为没有一个预先生成的类名列表可以与该正则表达式相匹配。
  • 当配置为函数时,prefix 选项无法检测完整的类名。因为我们不预先生成类名,所以我们只能将实用程序“namespace”传递给自定义前缀函数。有关示例,请参见此评论
  • 您只能 ​@apply​ 属于核心的类、由插件生成或在 ​@layer​ 规则中定义的类。您目前不能 ​@apply​ 未在 ​@layer​ 规则中定义的任意 CSS 类,尽管我们将来可能会添加对此的支持。(You can only @apply classes that are part of core, generated by plugins, or defined within a @layer rule. You can’t currently @apply arbitrary CSS classes that aren’t defined within a @layer rule, although we may add support for this in the future.)

我们还在解决与某些构建工具的一些兼容性问题,您可以在我们的 issue tracker 中关注这些问题。

如果您遇到任何其他问题或发现任何错误,请打开一个 issue,以便我们修复它。

故障排除

删除类时不会删除样式

当 JIT 引擎在监视模式下运行时,您可能会注意到,当您向 HTML 添加一个类然后删除它时,该类仍然存在于您的 CSS 中。

这不是一个错误,而是一种刻意的性能优化,它极大地提高了增量重建的速度,尤其是在大型项目中。

我们建议您在部署到生产之前始终在单独的一次性构建中编译您的 CSS,以便您可以缩小输出。对于大多数现代工具(例如 Next.js),这种事情会自动发生,因为您编译的 CSS 永远不会提交给版本控制。

如果您希望 Tailwind 在监视模式下从头开始完全重建 CSS,保存 ​tailwind.config.js​ 文件或 CSS 输入文件将使所有缓存无效并触发新的重建。

保存内容文件时样式不更新

从 Tailwind CSS v2.2+ 开始,JIT 引擎依赖 PostCSS 的目录依赖消息(directory dependency messages)将您的内容文件注册为使用构建工具的 CSS 构建依赖项。这些是 PostCSS 的一个相当新的补充(于 2021 年 5 月添加),并非所有构建工具都已更新以支持它们。

如果您更改内容文件时 CSS 没有重新构建,请尝试将 ​TAILWIND_MODE=watch​ 设置为您的监视脚本的一部分,以告诉 Tailwind 改用旧的依赖项跟踪策略,该策略适用于许多构建工具。

例如,如果您使用 ​postcss-cli​,请在您的 dev/watch 脚本中设置 ​TAILWIND_MODE=watch​:

// package.json
{
  // ...
  scripts: {
    // Set TAILWIND_MODE=watch when starting your dev server
    "dev": "TAILWIND_MODE=watch postcss -i tailwind.css -o build.css --watch",

    // Do not set TAILWIND_MODE for one-off builds
    "build": "postcss -i tailwind.css -o build.css --minify",
    // ...
  },
  // ...
}

如果你使用的是Windows,我们推荐使用 cross-env 来设置脚本中的环境变量。

请注意,设置 ​TAILWIND_MODE=watch​ 将在后台启动一个长时间运行的监视进程,因此如果您在尝试进行一次性构建时设置了该环境变量,它看起来就像构建挂起。

仅当您实际运行开发服务器/监视进程时,并且仅当您的构建工具尚不支持 PostCSS 目录依赖消息时,才应设置 ​TAILWIND_MODE=watch​。此标志是不兼容工具的临时解决方法,最终将在 Tailwind CSS 的未来版本中删除。

样式在无限循环中重建(Styles rebuild in an infinite loop)

如果你的 CSS 似乎在无限循环中重建,很有可能是因为你的构建工具在注册依赖项(registering dependencies)时不支持 PostCSS 的 ​ glob ​选项。

许多构建工具(例如 webpack)不支持此选项,因此我们只能告诉它们查看特定文件或整个目录。例如,我们不能告诉 webpack 只查看目录中的 ​*.html​ 文件。

这意味着如果构建 CSS 导致这些目录中的任何文件发生更改,则会触发重建,即使更改的文件与 glob 中的扩展名不匹配。

// tailwind.config.js
module.exports = {
  purge: [
    // Your CSS will rebuild any time *any* file in `src` changes
    './src/**/*.{html,js}',
  ],
  // ...
}

因此,如果你在观察​ src/**/*.html​ 的变化,但你却把你的CSS输出文件写到 ​src/css/styles.css​,你会在一些工具中得到一个无限的重建循环。

理想情况下,我们可以在控制台中警告您这一点,但许多工具都非常支持它(包括我们自己的 CLI 工具),而且我们没有可靠的方法来检测您正在使用的构建工具。

您有几个选项可以解决此问题:

  1. 在 ​purge ​配置中使用更具体的路径。确保只包含在 CSS 构建时不会更改的目录。
  2.   // tailwind.config.js
      module.exports = {
        purge: [
         './src/**/*.{html,js}',
         './src/pages/**/*.{html,js}',
         './src/components/**/*.{html,js}',
         './src/layouts/**/*.{html,js}',
         './src/index.html',
        ],
        // ...
      }

    如有必要,请调整您的实际项目目录结构,以确保您可以定位您的模板文件,而不会意外捕获您的 CSS 文件或其他构建工件(如清单文件)。

  3. 使用支持 PostCSS glob 的构建工具。如果您绝对无法更改清除配置或目录结构,最好的办法是使用具有完整 glob 支持的工具单独编译 CSS。我们建议使用 Tailwind CLI,它是一种快速、简单、专门构建的工具,用于使用 Tailwind 编译 CSS。

它似乎无法正常工作

如果您遇到奇怪的、难以描述的输出问题,或者看起来根本无法正常工作,很有可能是因为您的构建工具不正确(或根本不支持)PostCSS 依赖消息。目前一个已知的例子是 Stencil

当您遇到此类问题时,我们建议您使用 Tailwind CLI 工具单独编译您的 CSS,而不是尝试将 Tailwind 集成到您现有的工具中。

你可以使用 ​npm-run-all​ 或 ​concurrently ​这样的包,通过在你的项目中添加一些脚本,在你通常的开发命令旁边编译你的CSS,就像这样。

// package.json
{
  // ...
  "scripts": {
    "dev": "npm-run-all --parallel dev:*",
    "dev:parcel": "parcel serve ./src/index.html",
    "dev:css": "tailwindcss -o src/tailwind.css --watch",
    "build": "npm-run-all build:css build:parcel",
    "build:parcel": "parcel build ./src/index.html",
    "build:css": "tailwindcss -o src/tailwind.css --minify",
  },
}

无论哪种方式,请务必检查现有问题打开一个新问题,以便我们找出问题并尝试提高与您使用的任何工具的兼容性。

目前存在已知兼容性问题的工具包括:


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

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号