PostCSS 外掛指南

PostCSS 外掛是一個函式,接收並通常轉換來自 PostCSS 解析器的 CSS AST。

以下規則對所有 PostCSS 外掛而言是強制性的。

另請參閱 ClojureWerkz 對開源專案的建議

1. API

1.1 使用 postcss- 前綴的明確名稱

僅透過閱讀外掛名稱,應能清楚了解外掛的用途。如果您撰寫了 CSS 4 自訂媒體的轉譯器,postcss-custom-media 將會是很好的名稱。如果您撰寫了支援 mixin 的外掛,postcss-mixins 將會是很好的名稱。

前綴 postcss- 表示外掛是 PostCSS 生態系的一部分。

對於可以作為獨立工具執行的外掛,此規則並非強制性的,而使用者不一定知道它是由 PostCSS 提供支援的,例如 RTLCSSAutoprefixer

1.2. 專注於單一任務,並執行得很好

不要建立多功能外掛。將幾個小型的單一用途外掛打包成外掛套件通常是更好的解決方案。

例如,postcss-preset-env 包含許多小型外掛,每個外掛對應一個 W3C 規範。而 cssnano 則包含一個獨立的外掛來處理每個最佳化。

1.3. 不要使用 mixin

預處理器函式庫(例如 Compass)提供一個包含混合的 API。

PostCSS 外掛有所不同。外掛不能只是一個 postcss-mixins 混合集。

若要達成您的目標,請考慮轉換有效的 CSS 或使用自訂 at 規則和自訂屬性。

1.4. 將 postcss 保持在 peerDependencies

AST 可能會因為不同外掛中不同的 postcss 版本而中斷。不同的外掛可以使用不同的節點建立器(例如 postcss.decl())。

{
  "peerDependencies": {
    "postcss": "^8.0.0"
  }
}

最好甚至不要匯入 postcss

- const { list, decl } = require('postcss')
  module.exports = opts => {
    postcssPlugin: 'postcss-name',
-   Once (root) {
+   Once (root, { list, decl }) {
      // Plugin code
    }
  }
  module.exports.postcss = true

1.5. 使用外掛名稱設定 plugin.postcssPlugin

外掛名稱將用於錯誤訊息和警告。

module.exports = opts => {
  return {
    postcssPlugin: 'postcss-name',
    Once (root) {
      // Plugin code
    }
  }
}
module.exports.postcss = true

2. 處理

2.1. 外掛必須經過測試

也建議使用 Travis 等 CI 服務來測試不同環境中的程式碼。您應該在(至少)Node.js active LTS 和目前的穩定版本中進行測試。

2.2. 盡可能使用非同步方法

例如,使用 fs.writeFile 取代 fs.writeFileSync

let { readFile } = require('fs').promises

module.exports = opts => {
  return {
    postcssPlugin: 'plugin-inline',
    async Decl (decl) {
      const imagePath = findImage(decl)
      if (imagePath) {
        let imageFile = await readFile(imagePath)
        decl.value = replaceUrl(decl.value, imageFile)
      }
    }
  }
}
module.exports.postcss = true

2.3. 使用快速節點掃描

訂閱特定節點類型比呼叫 walk* 方法快很多

  module.exports = {
    postcssPlugin: 'postcss-example',
-   Once (root) {
-     root.walkDecls(decl => {
-       // Slow
-     })
-   }
+   Declaration (decl) {
+     // Faster
+   }
  }
  module.exports.postcss = true

但是,如果您知道需要哪個宣告的屬性或 at 規則的名稱,您可以讓掃描速度更快

  module.exports = {
    postcssPlugin: 'postcss-example',
-   Declaration (decl) {
-     if (decl.prop === 'color') {
-       // Faster
-     }
-   }
+   Declaration: {
+     color: decl => {
+       // The fastest
+     }
+   }
  }
  module.exports.postcss = true

2.4. 為新節點設定 node.source

每個節點都必須有一個相關的 source,以便 PostCSS 可以產生準確的原始碼對應。

因此,如果您根據某些現有宣告新增一個新宣告,您應該複製現有宣告以儲存原始的 source

if (needPrefix(decl.prop)) {
  decl.cloneBefore({ prop: '-webkit-' + decl.prop })
}

您也可以直接設定 source,從某些現有節點複製

if (decl.prop === 'animation') {
  const keyframe = createAnimationByName(decl.value)
  keyframes.source = decl.source
  decl.root().append(keyframes)
}

2.5. 僅使用公開的 PostCSS API

PostCSS 外掛程式不得依賴未記載的屬性或方法,這些屬性或方法可能會在任何次要版本中變更。公開 API 已在 API 文件 中說明。

3. 相依性

3.1. 使用訊息指定相依性

如果外掛程式依賴另一個檔案,應透過將 dependency 訊息附加到 result 來指定。

result.messages.push({
  type: 'dependency',
  plugin: 'postcss-import',
  file: '/imported/file.css',
  parent: result.opts.from
})

目錄相依性應使用 dir-dependency 訊息類型來指定。預設情況下,目錄中的所有檔案(遞迴)都被視為相依性。可使用選用的 glob 屬性來指出,僅應考慮符合特定 glob 模式的檔案。

result.messages.push({
  type: 'dir-dependency',
  plugin: 'postcss-import',
  dir: '/imported',
  glob: '**/*.css', // optional
  parent: result.opts.from
})

4. 錯誤

4.1. 對與 CSS 相關的錯誤使用 node.error

如果因為輸入 CSS 而發生錯誤(例如混合外掛程式中的未知名稱),您應使用 node.error 來建立包含來源位置的錯誤。

if (typeof mixins[name] === 'undefined') {
  throw node.error('Unknown mixin ' + name)
}

4.2. 對警告使用 result.warn

請勿使用 console.logconsole.warn 來印出警告,因為某些 PostCSS 執行器可能不允許主控台輸出。

Declaration (decl, { result }) {
  if (outdated(decl.prop)) {
    result.warn(decl.prop + ' is outdated', { node: decl })
  }
}

如果 CSS 輸入是警告的來源,外掛程式必須設定 node 選項。

5. 文件

5.1. 以英文撰寫外掛文件

PostCSS 外掛程式的 README.md 必須以英文撰寫。不要害怕您的英文能力,因為開放原始碼社群會修正您的錯誤。

當然,歡迎您使用其他語言撰寫文件;只要適當地命名它們(例如 README.ja.md)。

5.2. 包含輸入和輸出範例

外掛程式的 README.md 必須包含範例輸入和輸出 CSS。清楚的範例是說明外掛程式運作方式的最佳方法。

README.md 的第一個區段是放置範例的好地方。請參閱 postcss-opacity 以取得範例。

當然,如果您的外掛程式未轉換 CSS,則不適用此準則。

5.3. 維護變更日誌

PostCSS 外掛程式必須在一個獨立的檔案中描述所有版本的變更,例如 CHANGELOG.mdHistory.mdGitHub 版本。請瀏覽 保持變更日誌,深入了解如何撰寫這些檔案。

當然,您應該使用 SemVer

5.4. 在 package.json 中包含 postcss-plugin 關鍵字

為 npm 編寫的 PostCSS 外掛程式必須在 package.json 中包含 postcss-plugin 關鍵字。此特殊關鍵字有助於提供有關 PostCSS 生態系統的回饋。

對於未發佈至 npm 的套件,這並非強制性,但如果套件格式包含關鍵字,建議這麼做。