Static Arguments
這是 PikaCSS 最重要的限制。
pika() 會在 build-time 直接從原始碼裡被解析。也就是說,integration 必須在不執行應用程式的前提下,就看懂 argument 的形狀。如果 style 輸入依賴 runtime state,PikaCSS 就無法穩定地轉換它。
什麼是安全的
字面值 objects、arrays、strings、巢狀的字面值結構,以及穩定的組合方式,都是安全又理想的用法。
ts
// pika() 是全域函式,不需要另外匯入
// ✅ 靜態 object literal,可以正常運作
const btn = pika({
backgroundColor: 'blue',
color: 'white',
padding: '8px 16px',
})什麼是不安全的
runtime function calls、mutable state、computed member access,或是塞進 pika() 裡的任意 expressions,都會破壞 build-time 模型。
ts
// pika() 是全域函式,不需要另外匯入
// ❌ Runtime 變數,無法在 build-time 評估
const userColor = getUserPreference()
const btn = pika({
backgroundColor: userColor, // 錯誤:userColor 無法被靜態分析
})ts
// ❌ 不合法:直接引用變數
const color = 'red'
pika({ color: color })
// ❌ 不合法:把變數直接當成 argument
const styles = { color: 'red' }
pika(styles)
// ❌ 不合法:在值裡呼叫函式
pika({ color: getColor() })
// ❌ 不合法:帶有 expression 的 template literal
const size = 16
pika({ fontSize: `${size}px` })
// ❌ 不合法:展開變數
const base = { color: 'red' }
pika({ ...base })
// ❌ 不合法:條件運算式
const isDark = true
pika({ color: isDark ? 'white' : 'black' })
// ❌ 不合法:二元運算式
const x = 10
pika({ width: x + 'px' })
// ❌ 不合法:成員存取運算式
const theme = { color: 'red' }
pika({ color: theme.color })
// ❌ 不合法:動態計算的 key
const key = 'color'
pika({ [key]: 'red' })為什麼會有這個限制
PikaCSS 的價值,正是建立在這條邊界上:
- 它可以把原始碼轉成 deterministic atomic CSS。
- 它可以在事先知道 style 內容的前提下去重 declarations。
- 它可以產生 autocomplete 型別與 plugin 定義的 tokens。
- 它讓 runtime bundle 不需要承擔 styling 工作。
如果 engine 也接受任意 runtime values,這些保證就會一起失效。
建議替代方案
當你覺得自己需要 runtime style logic 時,請先試試下面這些模式:
- 先宣告好 variants,然後在 runtime 切換 class names。
- 把重複組合移進 shortcuts。
- 把主題值或每個實例各自不同的值移進 CSS variables。
- 把 state 差異移進像
hover、focus之類的 selectors,或自訂 aliases。 - 計算該用哪個靜態 style block,而不是在 runtime 去組出 block 內容。
一個好的思考模型
在 runtime 選擇靜態 style definitions,而不是在 runtime 動態組出 style definitions。
如果真正會變的是 value 本身,請接著看 Dynamic Values 與 CSS Variables。
盡早強制這條規則
加入 ESLint integration,讓錯誤在 editor 與 CI 階段就先被攔下來,不要等到 build 輸出少東少西時才回頭找原因。
ts
// ✅ 合法:使用靜態字面值 arguments
pika({ color: 'red' })
// ✅ 合法:使用多個靜態 arguments
pika({ color: 'red' }, { fontSize: '16px' })
// ✅ 合法:巢狀的靜態物件(例如 pseudo-classes、media queries)
pika({ color: 'black', '&:hover': { color: 'blue' } })
// ✅ 合法:數值型別
pika({ fontSize: 16, zIndex: -1 })
// ✅ 合法:不含 expressions 的 template literal
pika({ color: `red` })
// ✅ 合法:展開靜態 object literal
pika({ ...{ color: 'red' } })
// ✅ 合法:使用不同輸出形式
pika.str({ color: 'red' })
pika.arr({ display: 'flex' })
pikap({ margin: '10px' })該做與不該做
| 該做 | 不該做 |
|---|---|
先宣告 primary、secondary、danger 這類 style variants。 | 在 pika() 裡根據 API 資料臨時組出 style object。 |
| 用 CSS variables 承載主題值。 | 直接在呼叫裡讀取 runtime theme object。 |
| 用 selectors 與 shortcuts 收斂重複模式。 | 在每個 component 裡各自用臨時計算的 object 重寫同一套邏輯。 |