PostCSS 架构

🌙
手机阅读
本文目录结构

PostCSS 架构

PostCSS 体系结构的概述。对于希望为核心做出贡献或更好地了解该工具的每个人来说,它都是有用的。

目录

总览

本节描述了 PostCSS 背后的想法

在深入探讨 PostCSS 的开发之前,我们先简要介绍一下什么是 PostCSS,什么不是 PostCSS。

PostCSS

    • 不是样式预处理器 , 例如 Sass or Less.*

      它没有定义自定义语法和语义,实际上不是语言。PostCSS 可与 CSS 一起使用,并且可以轻松地与上述工具集成。话虽如此,任何有效的 CSS 都可以由 PostCSS 处理。

  • 是 CSS 语法转换的工具

    它允许您定义定制 CSS 之类的语法,插件可以理解和转换它们。话虽这么说,PostCSS 并不是严格地关于 CSS 规范,而是关于 CSS 的语法定义方式。通过这种方式,您可以定义自定义语法结构(如 at-rule),这对于围绕 PostCSS 构建工具非常有用。PostCSS 扮演了一个框架的角色,可为 CSS 操作构建出色的工具。

  • 在 CSS 生态系统中扮演重要角色

    可爱的工具,大量的喜欢 Autoprefixer, Stylelint, CSSnano 是建立在 PostCSS 生态系统。您很有可能已经隐式使用它,只需检查您的 node_modules :smiley:

工作流程

这是整个 PostCSS 工作流程的高级概述

workflow

从上图可以看到,PostCSS 体系结构非常简单,但是其中的某些部分可能会被误解。

您可以看到一个名为 Parser 的部分,稍后将对此结构进行详细描述,仅现在将其视为可以理解 CSS 语法并为其创建对象表示的结构。

话虽如此,编写解析器的方法很少。

  • 将带有字符串的单个文件写入 AST 转换

    这种方法非常流行,例如 Rework analyzer 就是用这种风格编写的。但是,由于代码库很大,所以代码变得难以阅读,而且速度很慢。

  • 将其分为词法分析 / 解析步骤(源字符串→标记→AST)

    这是我们在 PostCSS 中也是最受欢迎的方法。很多解析器一样 @babel/parser (parser behind Babel), CSSTree 写于这样的方式。将令牌化与解析步骤分开的主要原因是性能和抽象复杂性。

让我们考虑一下为什么第二种方法更好地满足了我们的需求。

首先,因为从字符串到令牌的步骤比解析步骤花费更多的时间。我们对大型源字符串进行操作,然后逐个字符处理它,这就是为什么它在性能方面效率很低的原因,我们只应该执行一次。

但是从另一端令牌到 AST 转换在逻辑上更加复杂,因此通过这种分离,我们可以编写非常快速的令牌生成器(但有时很难读取代码)和易于读取(但速度较慢)的解析器。

将其总结为两个步骤,可以提高性能和代码可读性。

因此,现在让我们更仔细地研究在 PostCSS 工作流程中起主要作用的结构。

核心结构

  • 标记器 ( lib/tokenize.es6 )

    标记器(又名 Lexer)在语法分析中起着重要的作用。

    它接受 CSS 字符串并返回令牌列表。

    令牌是一种结构简单,描述句法等的某些部分 at-rule``,commentword 。它还可以包含位置信息,以获取更多描述性错误。

    例如,如果我们考虑遵循 CSS

    .className { color: #FFF; }
    

    来自 PostCSS 的相应令牌将是

    [
        ["word", ".className", 1, 1, 1, 10]
        ["space", " "]
        ["{", "{", 1, 12]
        ["space", " "]
        ["word", "color", 1, 14, 1, 18]
        [":", ":", 1, 19]
        ["space", " "]
        ["word", "#FFF" , 1, 21, 1, 23]
        [";", ";", 1, 24]
        ["space", " "]
        ["}", "}", 1, 26]
    ]
    

    如您从上面的示例中看到的,单个标记表示为列表,并且 space 标记也没有位置信息。

    让我们更仔细地研究单个令牌,例如 word 。据说每个令牌都表示为列表并遵循这种模式。

    const token = [
         // represents token type
        'word',
    
        // represents matched word
        '.className',
    
        // This two numbers represent start position of token.
        // It is optional value as we saw in the example above,
        // tokens like `space` don't have such information.
    
        // Here the first number is line number and the second one is corresponding column.
        1, 1,
    
        // Next two numbers also optional and represent end position for multichar tokens like this one. Numbers follow same rule as was described above
        1, 10
    ]
    

    有许多模式可以完成标记化,PostCSS 的座右铭是性能和简单性。令牌化是一个复杂的计算操作,需要大量的语法分析时间(约 90%),这就是为什么 PostCSS 的令牌化器看上去很脏,但它针对速度进行了优化。诸如类之类的任何高级构造都可能会大大减慢令牌生成器的速度。

    PostCSS’ Tokenizer uses some sort of streaming/chaining API where you expose nextToken() method to Parser. In this manner, we provide a clean interface for Parser and reduce memory usage by storing only a few tokens and not the whole list of tokens.

  • 解析器 ( lib/parse.es6, lib/parser.es6 )

    解析器是负责传入 CSS 语法分析的主要结构。解析器生成一种称为抽象语法树(AST)的结构,以后可以通过插件对其进行转换。

    解析器与 Tokenizer 共同使用,并且对令牌(而不是源字符串)进行操作,因为这将是非常低效的操作。

    它主要使用 Tokenizer 提供的方法 nextToken 和 backTokenizer 提供的方法来获取单个或多个令牌,然后构造称为的 AST 的一部分 Node。

    PostCSS 可以产生多种 Node 类型,但是它们都继承自 Node 类。

  • 处理器 ( lib/processor.es6 )

    Processor 是一个非常简单的结构,用于初始化插件并运行语法转换。插件只是在 postcss.plugin 调用中注册的功能。

    它仅公开了一些公共 API 方法。可以在 api.postcss.org/Processor 上找到它们的描述。

  • Stringifier ( lib/stringify.es6, lib/stringifier.es6 )

    Stringifier 是将修改后的 AST 转换为纯 CSS 字符串的基类。Stringifier 从提供的 Node 开始遍历 AST,并生成其原始字符串表示形式并调用相应的方法。

    最基本的方法是 Stringifier.stringify 接受初始 Node 和分号指示符。您可以通过检查 stringifier.es6 了解更多信息

API 参考

可在 这里 找到更多描述性的API文档

AXIHE / 精选资源

浏览全部教程

面试题

学习网站

前端培训
自己甄别

前端书籍

关于朱安邦

我叫 朱安邦,阿西河的站长,在杭州。

以前是一名平面设计师,后来开始接接触前端开发,主要研究前端技术中的JS方向。

业余时间我喜欢分享和交流自己的技术,欢迎大家关注我的 Bilibili

关注我: Github / 知乎

于2021年离开前端领域,目前重心放在研究区块链上面了

我叫朱安邦,阿西河的站长

目前在杭州从事区块链周边的开发工作,机械专业,以前从事平面设计工作。

2014年底脱产在老家自学6个月的前端技术,自学期间几乎从未出过家门,最终找到了满意的前端工作。更多>

于2021年离开前端领域,目前从事区块链方面工作了