Does PostCSS guarantee sequential plugin execution when plugins return promises?
0 reputation · 28 Nov 2020, 07:32 UTC
0 reputation · 28 Nov 2020, 07:32 UTC
PostCSS's plugin architecture supports both synchronous and asynchronous transformations through a standardized API where plugins receive the root AST node. The API allows plugins to return a promise for async operations, but the documentation does not clearly specify how promise resolution affects the execution order of subsequent plugins in the pipeline.
The core uncertainty revolves around whether PostCSS enforces a strict sequential execution model for all plugins regardless of their async nature, or permits potential concurrent execution for performance optimization. This becomes critical when plugins modify shared AST state or depend on transformations from preceding plugins.
While many plugin implementations assume the root AST is fully processed before the next plugin runs, this behavior is not explicitly guaranteed by the PostCSS runtime. In environments where async plugins might execute concurrently, this could lead to race conditions where plugins operate on incomplete or inconsistent AST states.
The unresolved decision impacts plugin developers who must choose between defensive coding practices (assuming sequential execution) or optimizing for potential parallelism. This also affects how developers structure complex transformation pipelines with interdependent plugins.
Can PostCSS guarantee that async plugins execute in the order they are defined in the plugin array? Does the current implementation support concurrent plugin execution that could compromise AST consistency? What is the recommended approach for plugin authors to ensure predictable behavior across different PostCSS versions?
34775 reputation · 28 Nov 2020, 17:46 UTC
Yes. In the current PostCSS 8.x architecture, plugins are executed sequentially in the order they appear in the plugin array, and a plugin that returns a Promise is awaited before the next plugin runs. PostCSS does not run plugins concurrently against the same AST.
The sequential guarantee applies to plugin-to-plugin order. It does not protect against a single plugin that fires off floating promises inside its own visitors without awaiting them. Within a plugin, async work scheduled in Declaration or other visitors must be returned/awaited by the plugin author; otherwise the plugin may report completion before its internal work finishes.
Assumption: PostCSS 8.x core runtime. Very old versions pre-8 used a different plugin API and async handling. Third-party wrappers or bundler integrations around PostCSS may batch or reorder work independently of the core runtime.
If you can share the exact PostCSS version in use, the recommendation can be tightened to that release's LazyResult implementation.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.