Происхождение увидело, что EarlyBirdCamp использовал tailwindcss, а затем воспользовалось ситуацией, чтобы узнать об этом.
что такое tailwindcss
Если вы включите tailwindcssрепозиторий github,вы наверное запутаетесь.Почему css framework это куча js,а css файл тоже странный атрул?Можно сказать что использование postcss tailwindcss действительно на уровне,я не ожидал играй так раньше! Через конфигурацию js, postcss-js и postcss-nested для разбора нашей конфигурации, генерации node, а затем, наконец, использования postcss для генерации css, и даже использования purecss для обрезки сгенерированного css или использования более привычных терминов, то есть вы можете дерево встряхивая наш css, звучит очень продвинуто. Я не буду вдаваться в подробности здесь, я, вероятно, выберу несколько более характерных для разговора.
Классический попутный ветер.css
Сначала взгляните на следующие три классических атрула,atrule
Это узел ast в postcss, представляющий узел @ в css, за которым следуют параметры этого узла, вы можете перейти кastexplorerи в сочетании с postcssAPI-документациячтобы понять
@tailwind base;
@tailwind components;
@tailwind utilities;
В tailwindcss такой классический узел будет играть две роли, взять@tailwind base;
В этом случае, когда плагин postcss встречает этот атрибут, он распознает, что params является базовым, и будет генерировать css из содержимого узла в pluginBase, и в то же время исправит исходный код, чтобы исходная карта не ошиблась. подробности, вы можете увидеть ниже, вы можете видеть, Теперь вставьте содержимое перед atRule, удалите это atRule
css.walkAtRules('tailwind', atRule => {
if (atRule.params === 'preflight') {
// prettier-ignore
throw atRule.error("`@tailwind preflight` is not a valid at-rule in Tailwind v1.0, use `@tailwind base` instead.", { word: 'preflight' })
}
if (atRule.params === 'base') {
atRule.before(updateSource(pluginBase, atRule.source))
atRule.remove()
}
if (atRule.params === 'components') {
atRule.before(postcss.comment({ text: 'tailwind start components' }))
atRule.before(updateSource(pluginComponents, atRule.source))
atRule.after(postcss.comment({ text: 'tailwind end components' }))
atRule.remove()
}
if (atRule.params === 'utilities') {
atRule.before(postcss.comment({ text: 'tailwind start utilities' }))
atRule.before(updateSource(pluginUtilities, atRule.source))
atRule.after(postcss.comment({ text: 'tailwind end utilities' }))
atRule.remove()
}
if (atRule.params === 'screens') {
includesScreensExplicitly = true
atRule.before(postcss.comment({ text: 'tailwind start screens' }))
atRule.after(postcss.comment({ text: 'tailwind end screens' }))
}
})
if (!includesScreensExplicitly) {
css.append([
postcss.comment({ text: 'tailwind start screens' }),
postcss.atRule({ name: 'tailwind', params: 'screens' }),
postcss.comment({ text: 'tailwind end screens' }),
])
}
Что касается исправления указания исходной карты, вы можете увидеть следующую функцию, чтобы все вновь сгенерированные узлы указывали на источник исходного atRule, идеально~
function updateSource(nodes, source) {
return _.tap(Array.isArray(nodes) ? postcss.root({ nodes }) : nodes, tree => {
tree.walk(node => (node.source = source))
})
}
Поговорим о другом экране в Rule
Instead of writing a raw media query that duplicates that value like this:
@media (min-width: 640px) {
/* ... */
}
you can use the @screen directive and reference the breakpoint by name:
@screen sm {
/* ... */
}
Английский выше скопирован из документа, это обычный медиа-запрос, мы можем записать его в CSS, но что, если через некоторое время его нужно будет изменить? Вот извлекаем в js конфиг.Читая конфиг файл, по умолчанию стоит tailwind.config.js.theme.screens в нем соответствует значению params в atRule для генерации нашего конкретного css, что не слишком удобно.
import _ from 'lodash'
import buildMediaQuery from '../util/buildMediaQuery'
export default function({ theme }) {
return function(css) {
css.walkAtRules('screen', atRule => {
const screen = atRule.params
if (!_.has(theme.screens, screen)) {
throw atRule.error(`No \`${screen}\` screen found.`)
}
atRule.name = 'media'
atRule.params = buildMediaQuery(theme.screens[screen])
})
}
}
О методе написания плагина tailwindcss
Способ написания плагина tailwindcss, как его написать конкретно, здесь раскрываться не буду, но принцип будет объяснен здесь. На самом деле, основная функция плагина состоит в том, чтобы сгенерировать предварительный css из написанной нами js-конфигурации css, затем выполнить вторичную обработку в соответствии с файлом конфигурации и, наконец, сгенерировать фактический css.Возьмем встроенный плагин zIndex как пример, в основном этот Плагин еще и тестовые кейсы писал, совмещенный с документацией, не слишком удобно вводить
Во-первых, давайте посмотрим, как написан этот плагин.
import _ from 'lodash'
import prefixNegativeModifiers from '../util/prefixNegativeModifiers'
export default function() {
return function({ addUtilities, e, theme, variants }) {
const utilities = _.fromPairs(
_.map(theme('zIndex'), (value, modifier) => {
return [
`.${e(prefixNegativeModifiers('z', modifier))}`,
{
'z-index': value,
},
]
})
)
addUtilities(utilities, variants('zIndex'))
}
}
На самом деле все, о чем нам нужно заботиться, этоaddUtilities(utilities, variants('zIndex'))
Что за хрень это делает?Проще говоря, zIndex запихивается в pluginUtilities, то есть последний является соответствующим@tailwind utilities;
, можно посмотреть что генерируется в тесткейсе, следующим образом, вот так, среди каких утилит легко понять, какие есть варианты? Использование вариантов можно увидеть в документации, грубо говоря, там будет@variants responsive
Оберните код, сгенерированный в наших утилитах, чтобы изначально сгенерировался наш css, а затем replaceResponsiveAtRules дважды обработает atRule, чтобы сгенерировать окончательный css
expect(addedUtilities).toEqual([
{
utilities: {
'.-z-20': { 'z-index': '-20' },
'.-z-10': { 'z-index': '-10' },
'.z-10': { 'z-index': '10' },
'.z-20': { 'z-index': '20' },
},
variants: ['responsive'],
},
])
Последнее слово
tailwindcss
Способов играть еще много, за подробностями можно обратиться в документацию, здесь лишь краткое описание принципа его реализации, шок меня это повергло в то, что я не ожидал, что postcss или css смогут играй так, дыра в мозгу слишком большая, пс: Чтобы понять этот продукт, я в основном взглянул на документы основной зависимой библиотеки, :побег)