Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export interface BundleStylesheetOptions {
externalDependencies?: string[];
target: string[];
tailwindConfiguration?: { file: string; package: string };
postcssConfiguration?: PostcssConfiguration;
postcssConfiguration?: { config: PostcssConfiguration; configPath: string };
publicPath?: string;
cacheOptions: NormalizedCachedOptions;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
import type { OnLoadResult, Plugin, PluginBuild } from 'esbuild';
import assert from 'node:assert';
import { readFile } from 'node:fs/promises';
import { extname } from 'node:path';
import { createRequire } from 'node:module';
import { dirname, extname } from 'node:path';
import type { Options } from 'sass';
import { glob } from 'tinyglobby';
import { assertIsError } from '../../../utils/error';
Expand Down Expand Up @@ -69,7 +70,7 @@ export interface StylesheetPluginOptions {
* initialized and used for every stylesheet. This overrides the tailwind integration
* and any tailwind usage must be manually configured in the custom postcss usage.
*/
postcssConfiguration?: PostcssConfiguration;
postcssConfiguration?: { config: PostcssConfiguration; configPath: string };

/**
* Optional Options for configuring Sass behavior.
Expand Down Expand Up @@ -215,14 +216,18 @@ export class StylesheetPluginFactory {

const { options } = this;
if (options.postcssConfiguration) {
const postCssInstanceKey = JSON.stringify(options.postcssConfiguration);
const { config, configPath } = options.postcssConfiguration;
const postCssInstanceKey = JSON.stringify(config);
let postcssProcessor = postcssProcessors.get(postCssInstanceKey)?.deref();

if (!postcssProcessor) {
postcss ??= (await import('postcss')).default;
postcssProcessor = postcss();
for (const [pluginName, pluginOptions] of options.postcssConfiguration.plugins) {
const { default: plugin } = await import(pluginName);

const postCssPluginRequire = createRequire(dirname(configPath) + '/');
Copy link

@th0r th0r Sep 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alan-agius4 this change brakes importing of plugins that are ES modules as in this case the plugin below won't be a function, but an {default: <function>, __esModule: true} object and it won't pass a check below.


for (const [pluginName, pluginOptions] of config.plugins) {
const plugin = postCssPluginRequire(pluginName);
if (typeof plugin !== 'function' || plugin.postcss !== true) {
throw new Error(`Attempted to load invalid Postcss plugin: "${pluginName}"`);
}
Expand Down
14 changes: 9 additions & 5 deletions packages/angular/build/src/utils/postcss-configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,13 @@ async function readPostcssConfiguration(
return config;
}

export async function loadPostcssConfiguration(
searchDirectories: SearchDirectory[],
): Promise<PostcssConfiguration | undefined> {
export async function loadPostcssConfiguration(searchDirectories: SearchDirectory[]): Promise<
| {
configPath: string;
config: PostcssConfiguration;
}
| undefined
> {
const configPath = findFile(searchDirectories, postcssConfigurationFiles);
if (!configPath) {
return undefined;
Expand Down Expand Up @@ -101,7 +105,7 @@ export async function loadPostcssConfiguration(
}
}

return config;
return { config, configPath };
}

// Normalize plugin object map form
Expand All @@ -119,5 +123,5 @@ export async function loadPostcssConfiguration(
config.plugins.push([name, options]);
}

return config;
return { config, configPath };
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
loadPostcssConfiguration,
} from '@angular/build/private';
import MiniCssExtractPlugin from 'mini-css-extract-plugin';
import { createRequire } from 'node:module';
import * as path from 'node:path';
import { fileURLToPath, pathToFileURL } from 'node:url';
import type { FileImporter } from 'sass';
Expand Down Expand Up @@ -83,9 +84,10 @@ export async function getStylesConfig(wco: WebpackConfigOptions): Promise<Config
const postcssConfig = await loadPostcssConfiguration(searchDirectories);

if (postcssConfig) {
for (const [pluginName, pluginOptions] of postcssConfig.plugins) {
const resolvedPlugin = require.resolve(pluginName, { paths: [root] });
const { default: plugin } = await import(resolvedPlugin);
const postCssPluginRequire = createRequire(path.dirname(postcssConfig.configPath) + '/');

for (const [pluginName, pluginOptions] of postcssConfig.config.plugins) {
const plugin = postCssPluginRequire(pluginName);
if (typeof plugin !== 'function' || plugin.postcss !== true) {
throw new Error(`Attempted to load invalid Postcss plugin: "${pluginName}"`);
}
Expand Down