Skip to content

Commit 4e779b4

Browse files
authored
feat(turbopack): support merged PostCSS configs (#186)
1 parent 2ed2153 commit 4e779b4

1 file changed

Lines changed: 96 additions & 20 deletions

File tree

  • turbopack/crates/turbopack-node/src/transforms

turbopack/crates/turbopack-node/src/transforms/postcss.rs

Lines changed: 96 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -518,16 +518,85 @@ async fn postcss_executor(
518518
asset_context: Vc<Box<dyn AssetContext>>,
519519
project_path: FileSystemPath,
520520
config_source: PostCssConfigSource,
521+
additional_config_content: Option<RcStr>,
521522
) -> Result<Vc<ProcessResult>> {
522523
let config_asset = asset_context
523524
.process(
524-
config_loader_source(project_path, config_source),
525+
config_loader_source(project_path.clone(), config_source),
525526
ReferenceType::Entry(EntryReferenceSubType::Undefined),
526527
)
527528
.module()
528529
.to_resolved()
529530
.await?;
530531

532+
let config_asset = if let Some(additional_config_content) = additional_config_content {
533+
let additional_config_asset = asset_context
534+
.process(
535+
config_loader_source(
536+
project_path.clone(),
537+
PostCssConfigSource::Inline(additional_config_content),
538+
),
539+
ReferenceType::Entry(EntryReferenceSubType::Undefined),
540+
)
541+
.module()
542+
.to_resolved()
543+
.await?;
544+
let code = r#"
545+
import config from 'CONFIG';
546+
import additionalConfig from 'ADDITIONAL_CONFIG';
547+
548+
const resolveConfig = async (value, args) =>
549+
typeof value === 'function' ? await value(...args) : value;
550+
const pluginsToArray = (plugins) => {
551+
if (Array.isArray(plugins)) {
552+
return plugins;
553+
}
554+
555+
if (plugins && typeof plugins === 'object') {
556+
return Object.entries(plugins).filter(([, options]) => options);
557+
}
558+
559+
return [];
560+
};
561+
562+
export default async (...args) => {
563+
const resolvedConfig = await resolveConfig(config, args);
564+
const resolvedAdditionalConfig = await resolveConfig(additionalConfig, args);
565+
566+
if (
567+
typeof resolvedConfig === 'undefined' ||
568+
typeof resolvedAdditionalConfig === 'undefined'
569+
) {
570+
return undefined;
571+
}
572+
573+
return {
574+
plugins: [
575+
...pluginsToArray(resolvedConfig.plugins),
576+
...pluginsToArray(resolvedAdditionalConfig.plugins),
577+
],
578+
};
579+
};
580+
"#;
581+
582+
asset_context
583+
.process(
584+
Vc::upcast(VirtualSource::new(
585+
project_path.join(".postcss.merged.config.mjs")?,
586+
AssetContent::file(FileContent::Content(File::from(code)).cell()),
587+
)),
588+
ReferenceType::Internal(ResolvedVc::cell(fxindexmap! {
589+
rcstr!("CONFIG") => config_asset,
590+
rcstr!("ADDITIONAL_CONFIG") => additional_config_asset,
591+
})),
592+
)
593+
.module()
594+
.to_resolved()
595+
.await?
596+
} else {
597+
config_asset
598+
};
599+
531600
let path = embed_file_path(rcstr!("transforms/postcss.ts"))
532601
.owned()
533602
.await?;
@@ -621,32 +690,39 @@ impl PostCssTransformedAsset {
621690
let evaluate_context = self.evaluate_context;
622691
let source_map = self.source_map;
623692

624-
let (config_source, additional_invalidation) =
625-
if let Some(config_content) = self.config_content.as_ref() {
626-
(
627-
PostCssConfigSource::Inline(config_content.clone()),
628-
Completion::immutable().to_resolved().await?,
629-
)
630-
} else if let Some(config_path) =
631-
find_config_in_location(project_path.clone(), self.config_location, *self.source)
632-
.await?
633-
{
634-
(
693+
let config_path =
694+
find_config_in_location(project_path.clone(), self.config_location, *self.source)
695+
.await?;
696+
let (config_source, additional_config_content, additional_invalidation) =
697+
match (config_path, self.config_content.as_ref()) {
698+
(Some(config_path), config_content) => (
635699
PostCssConfigSource::Path(config_path.clone()),
700+
config_content.cloned(),
636701
config_changed(*self.config_tracing_context, config_path)
637702
.to_resolved()
638703
.await?,
639-
)
640-
} else {
641-
return Ok(ProcessPostCssResult {
642-
content: self.source.content().to_resolved().await?,
643-
assets: Vec::new(),
704+
),
705+
(None, Some(config_content)) => (
706+
PostCssConfigSource::Inline(config_content.clone()),
707+
None,
708+
Completion::immutable().to_resolved().await?,
709+
),
710+
(None, None) => {
711+
return Ok(ProcessPostCssResult {
712+
content: self.source.content().to_resolved().await?,
713+
assets: Vec::new(),
714+
}
715+
.cell());
644716
}
645-
.cell());
646717
};
647718

648-
let postcss_executor =
649-
postcss_executor(*evaluate_context, project_path.clone(), config_source).module();
719+
let postcss_executor = postcss_executor(
720+
*evaluate_context,
721+
project_path.clone(),
722+
config_source,
723+
additional_config_content,
724+
)
725+
.module();
650726

651727
let entries =
652728
get_evaluate_entries(postcss_executor, *evaluate_context, **node_backend, None)

0 commit comments

Comments
 (0)