Skip to content

Hook Execution

如果你只記得 plugin hooks 的一件事,那就是:選擇「仍然能提供所需控制力」的最晚 hook。

這樣會讓 plugins 更容易理解,也能減少對其他 plugins 的意外干擾。

Hook 決策表

需求Hook
在 defaults 套用前修改 user configconfigureRawConfig
檢查或調整 resolved defaultsconfigureResolvedConfig
呼叫 engine APIs 並註冊行為configureEngine
在 extraction 前改寫 style itemstransformStyleItems
改寫 selector chainstransformSelectors
改寫巢狀 style definitionstransformStyleDefinitions
只觀察 engine eventssync notification hooks

Payload chaining

Async hooks 可以回傳新的 payload,而這個新 payload 會按照順序傳給下一個 plugin。

ts
import { defineEnginePlugin } from '@pikacss/core'

export const asyncHookPlugin = defineEnginePlugin({
	name: 'async-hook-example',

	// 非同步 hook:在 raw config 被 resolved 前修改它。
	// 回傳修改後的 config,交給下一個 plugin,
	// 或回傳 void/undefined 以保留目前的值。
	configureRawConfig(config) {
		config.prefix = 'pk-'
		return config
	},

	// 非同步 hook:在樣式提取期間轉換 selectors。
	// 回傳的陣列會取代下一個 plugin 的輸入。
	transformSelectors(selectors) {
		return selectors.map(s => s.replace('$hover', '&:hover'))
	},
})

實際上意思很簡單:只要 plugin 會回傳轉換後的 payload,就該寫得明確而保守,因為後面的 plugins 看到的就是這份修改後結果。

Error isolation

Hook errors 會被攔截並記錄,所以單一壞掉的 plugin 預設不會讓整條鏈完全中斷。這對韌性很好,但也代表如果你不去檢查 logs,plugin 的靜默失敗看起來就會像是功能缺失。

Notification hooks 是拿來觀察的

Notification hooks 的存在,是讓 integrations 或 plugins 可以對 preflight 更新、atomic style generation、autocomplete 更新等變化做出反應。

ts
import { defineEnginePlugin } from '@pikacss/core'

export const plugin = defineEnginePlugin({
	name: 'example',

	// 同步:當產生新的 atomic style 時呼叫
	atomicStyleAdded(atomicStyle) {
		console.log(`New atomic style: ${atomicStyle.id}`)
	},

	// 同步:當 preflights 更新時呼叫
	preflightUpdated() {
		console.log('Preflights updated')
	},

	// 同步:當 autocomplete config 變更時呼叫
	autocompleteConfigUpdated() {
		console.log('Autocomplete config updated')
	},
})

給 plugin authors 的實用規則

先從 configureEngine 開始。只有在具體限制逼迫你更早或更深入進入 transforms 時,才往前移。

Next