PostCSS 外掛指南
PostCSS 外掛是一個函式,接收並通常轉換來自 PostCSS 解析器的 CSS AST。
以下規則對所有 PostCSS 外掛而言是強制性的。
另請參閱 ClojureWerkz 對開源專案的建議。
1. API
1.1 使用 postcss-
前綴的明確名稱
僅透過閱讀外掛名稱,應能清楚了解外掛的用途。如果您撰寫了 CSS 4 自訂媒體的轉譯器,postcss-custom-media
將會是很好的名稱。如果您撰寫了支援 mixin 的外掛,postcss-mixins
將會是很好的名稱。
前綴 postcss-
表示外掛是 PostCSS 生態系的一部分。
對於可以作為獨立工具執行的外掛,此規則並非強制性的,而使用者不一定知道它是由 PostCSS 提供支援的,例如 RTLCSS 和 Autoprefixer。
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.log
或 console.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.md
、History.md
或 GitHub 版本。請瀏覽 保持變更日誌,深入了解如何撰寫這些檔案。
當然,您應該使用 SemVer。
5.4. 在 package.json
中包含 postcss-plugin
關鍵字
為 npm 編寫的 PostCSS 外掛程式必須在 package.json
中包含 postcss-plugin
關鍵字。此特殊關鍵字有助於提供有關 PostCSS 生態系統的回饋。
對於未發佈至 npm 的套件,這並非強制性,但如果套件格式包含關鍵字,建議這麼做。