目录
人们一直在讨论在 Tailwind 项目中对实用程序类进行排序的最佳方法。今天,我们很高兴地宣布,随着我们官方 prettier-plugin-tailwindcss 的发布,您终于可以不用为此担心了。

此插件会扫描您的模板,查找包含 Tailwind CSS 类的 class 属性,然后按照我们推荐的类排序动对这些类进行排序。
<!-- Before -->
<button class="text-white px-4 sm:px-8 py-2 sm:py-3 bg-sky-700 hover:bg-sky-800">...</button>
<!-- After -->
<button class="bg-sky-700 px-4 py-2 text-white hover:bg-sky-800 sm:px-8 sm:py-3">...</button>
它可以与自定义 Tailwind 配置无缝协作,并且因为它只是一个prettier插件,所以它可以在任何 Prettier 可以工作的地方工作------包括每个流行的编辑器和 IDE,当然也可以在命令行中使用。
要开始使用,请将 prettier-plugin-tailwindcss
安装为开发依赖项
npm install -D prettier prettier-plugin-tailwindcss
然后将插件添加到您的 .prettierrc 中
{
"plugins": ["prettier-plugin-tailwindcss"]
}
您还可以通过将 --plugin 标志与 Prettier CLI 一起使用,或者通过将 plugins 选项与 Prettier API 一起使用来加载插件。
插件是向 Prettier 添加新语言或格式规则的方法。Prettier 自身对所有语言的实现都使用插件 API 来表达。核心
prettier
包内置了 JavaScript 和其他 Web 语言。如需添加其他语言,则需要安装插件您可以使用以下方式加载插件:
{ "plugins": ["prettier-plugin-foo"] }
提供的字符串
plugins
最终传递给import()表达式,此您可以提供模块/包名称、路径或任何其他import()
内容。
类如何排序
从本质上讲,此插件所做的只是按照 Tailwind 在 CSS 中对其类进行排序的相同顺序来组织您的类。
这意味着基础层中的任何类都将首先排序,然后是组件层中的类,最后是实用程序层中的类。
<!-- `container` is a component so it comes first -->
<div class="container mx-auto px-6">
<!-- ... -->
</div>
实用程序本身的排序顺序也与我们在 CSS 中对它们进行排序的顺序相同,这意味着任何覆盖其他类的类总是出现在类列表的后面
<div class="pt-2 p-4">
<div class="p-4 pt-2">
<!-- ... -->
</div>
</div>
不同实用程序的实际顺序大致基于盒模型,并尝试将影响布局的高影响类放在开头,将装饰类放在结尾,同时还尝试将相关的实用程序放在一起
<div class="text-gray-700 shadow-md p-3 border-gray-300 ml-4 h-24 flex border-2">
<div class="ml-4 flex h-24 border-2 border-gray-300 p-3 text-gray-700 shadow-md">
<!-- ... -->
</div>
</div>
像 hover:
和 focus:
这样的修饰符被分组在一起,并在任何普通实用程序之后进行排序
<div class="hover:opacity-75 opacity-50 hover:scale-150 scale-125">
<div class="scale-125 opacity-50 hover:scale-150 hover:opacity-75">
<!-- ... -->
</div>
</div>
像 md:
和 lg:
这样的响应式修饰符被分组在最后,并按照它们在您的主题中配置的顺序排序------默认情况下是从最小到最大
<div class="lg:grid-cols-4 grid sm:grid-cols-3 grid-cols-2">
<div class="grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4">
<!-- ... -->
</div>
</div>
任何不来自 Tailwind 插件的自定义类(例如用于定位第三方库的类)始终排序在最前面,因此很容易看出元素何时正在使用它们
<div class="p-3 shadow-xl select2-dropdown">
<div class="select2-dropdown p-3 shadow-xl">
<!-- ... -->
</div>
</div>
自定义
我们认为,在保持主观性和在自定义方面提供较少选择时,Prettier 做对了------归根结底,对您的类进行排序的最大好处是,您可以减少一件与团队争论的事情。 我们非常努力地提出了一个易于理解且能尽快传达最重要信息的排序顺序。 该插件将尊重您的 tailwind.config.js 文件,并与您安装的任何 Tailwind 插件一起工作,但是无法更改排序顺序。就像 Prettier 一样,我们认为自动格式化的好处将很快超过您拥有的任何样式偏好,并且您会很快习惯它。
https://prettier.io/docs/option-philosophy.html
然而,该停下来的时候到了。如今 Prettier 已经足够成熟,我们看到它被如此多的组织和项目采用,研究阶段已经结束。我们有充分的信心得出结论,Prettier 已经达到了一个应该"冻结"选项的阶段。**选项请求将不再被接受。**我们感谢所有参与这段艰难旅程的人。
实战应用
作者在使用的时候因为使用的 prettier, eslint-plugin-prettier 这两个第三方插件的版本太低导致各种不生效 所以我把现在可以运行的版本贴出来供参考
如果遇到问题可以先更新版本 然后在参考文档看看是否有最新方案
.prettierrc
{
"plugins": ["prettier-plugin-tailwindcss"],
"printWidth": 80,
"tabWidth": 2,
"useTabs": false,
"singleQuote": true,
"semi": false,
"trailingComma": "none",
"bracketSpacing": true
}
package
{
"private": true,
"version": "1.0.0",
"description": "通知H5 MonoRepo项目",
"main": "index.js",
"type": "module",
"scripts": {
"dev": "turbo run dev",
"build": "turbo run build",
"prepare": "husky install"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@types/node": "^18.11.9",
"@typescript-eslint/eslint-plugin": "^5.42.0",
"@typescript-eslint/parser": "^5.42.0",
"eslint": "^8.26.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-prettier": "^5.5.1",
"eslint-plugin-vue": "^9.7.0",
"husky": "^8.0.1",
"lint-staged": "^13.0.3",
"prettier": "^3.6.2",
"prettier-plugin-tailwindcss": "^0.6.14",
"turbo": "^2.5.4",
"typescript": "^4.8.4"
},
"lint-staged": {
"*.{js,ts,vue,jsx,tsx,json}": "eslint --cache --fix"
},
"packageManager": "pnpm@9.0.0"
}
.eslintrc
{
"env": {
"browser": true,
"es2021": true,
"node": true
},
"extends": [
"eslint:recommended",
"plugin:vue/vue3-essential",
"plugin:@typescript-eslint/recommended",
"plugin:prettier/recommended"
],
"overrides": [],
"parser": "vue-eslint-parser",
"parserOptions": {
"ecmaVersion": "latest",
"parser": "@typescript-eslint/parser",
"sourceType": "module"
},
"plugins": [
"vue",
"@typescript-eslint"
],
"rules": {
"vue/multi-word-component-names": "off",
"@typescript-eslint/no-this-alias": [
"off"
]
},
"globals": {
"uni": true,
"getApp": true,
"Android": true
}
}