From 48630ccfd7a672fc5174ef484b3bd5c549d32fef Mon Sep 17 00:00:00 2001 From: Alan Agius Date: Fri, 27 May 2022 11:37:40 +0000 Subject: [PATCH] fix(@angular-devkit/build-angular): detect `tailwind.config.cjs` as valid tailwindcss configuration `tailwind.config.cjs` is a valid tailwindcss configuration file as it's listed in https://github.com/tailwindlabs/tailwindcss/blob/8845d112fb62d79815b50b3bae80c317450b8b92/src/util/resolveConfigPath.js#L46-L52 as such we should also take this filename into consideration. Closes #23236 (cherry picked from commit ee2e75610b37354ed7bfcce95f5bc18713b2fa41) --- .../src/webpack/configs/styles.ts | 29 +++++++++----- .../e2e/tests/build/styles/tailwind-v3-cjs.ts | 39 +++++++++++++++++++ 2 files changed, 58 insertions(+), 10 deletions(-) create mode 100644 tests/legacy-cli/e2e/tests/build/styles/tailwind-v3-cjs.ts diff --git a/packages/angular_devkit/build_angular/src/webpack/configs/styles.ts b/packages/angular_devkit/build_angular/src/webpack/configs/styles.ts index 91669dfa097a..e1ecba8216ea 100644 --- a/packages/angular_devkit/build_angular/src/webpack/configs/styles.ts +++ b/packages/angular_devkit/build_angular/src/webpack/configs/styles.ts @@ -121,19 +121,10 @@ export function getStylesConfig(wco: WebpackConfigOptions): Configuration { const extraPostcssPlugins: import('postcss').Plugin[] = []; // Attempt to setup Tailwind CSS - // A configuration file can exist in the project or workspace root - const tailwindConfigFile = 'tailwind.config.js'; - let tailwindConfigPath; - for (const basePath of [wco.projectRoot, wco.root]) { - const fullPath = path.join(basePath, tailwindConfigFile); - if (fs.existsSync(fullPath)) { - tailwindConfigPath = fullPath; - break; - } - } // Only load Tailwind CSS plugin if configuration file was found. // This acts as a guard to ensure the project actually wants to use Tailwind CSS. // The package may be unknowningly present due to a third-party transitive package dependency. + const tailwindConfigPath = getTailwindConfigPath(wco); if (tailwindConfigPath) { let tailwindPackagePath; try { @@ -402,3 +393,21 @@ export function getStylesConfig(wco: WebpackConfigOptions): Configuration { plugins: extraPlugins, }; } + +function getTailwindConfigPath({ projectRoot, root }: WebpackConfigOptions): string | undefined { + // A configuration file can exist in the project or workspace root + // The list of valid config files can be found: + // https://github.com/tailwindlabs/tailwindcss/blob/8845d112fb62d79815b50b3bae80c317450b8b92/src/util/resolveConfigPath.js#L46-L52 + const tailwindConfigFiles = ['tailwind.config.js', 'tailwind.config.cjs']; + for (const basePath of [projectRoot, root]) { + for (const configFile of tailwindConfigFiles) { + // Irrespective of the name project level configuration should always take precedence. + const fullPath = path.join(basePath, configFile); + if (fs.existsSync(fullPath)) { + return fullPath; + } + } + } + + return undefined; +} diff --git a/tests/legacy-cli/e2e/tests/build/styles/tailwind-v3-cjs.ts b/tests/legacy-cli/e2e/tests/build/styles/tailwind-v3-cjs.ts new file mode 100644 index 000000000000..f6074b674a8f --- /dev/null +++ b/tests/legacy-cli/e2e/tests/build/styles/tailwind-v3-cjs.ts @@ -0,0 +1,39 @@ +import { expectFileToMatch, moveFile, writeFile } from '../../../utils/fs'; +import { installPackage } from '../../../utils/packages'; +import { ng, silentExec } from '../../../utils/process'; +import { updateJsonFile } from '../../../utils/project'; +import { expectToFail } from '../../../utils/utils'; + +export default async function () { + // Temporarily turn off caching until the build cache accounts for the presence of tailwind + // and its configuration file. Otherwise cached builds without tailwind will cause test failures. + await ng('cache', 'off'); + + // Add type module in package.json. + await updateJsonFile('package.json', (json) => { + json['type'] = 'module'; + }); + + // Install Tailwind + await installPackage('tailwindcss@3'); + + // Create configuration file + await silentExec('npx', 'tailwindcss', 'init'); + + // tailwind doesn't create the config file with a cjs extension. + // We need to rename it manually until + // https://github.com/tailwindlabs/tailwindcss/commit/6c63f67d20c433b5c7281e9e26744038ed41ccc2 is released. + await moveFile('tailwind.config.js', 'tailwind.config.cjs'); + + // Add Tailwind directives to a global style + await writeFile('src/styles.css', '@tailwind base; @tailwind components;'); + + // Build should succeed and process Tailwind directives + await ng('build', '--configuration=development'); + + // Check for Tailwind output + await expectFileToMatch('dist/test-project/styles.css', /::placeholder/); + await expectToFail(() => + expectFileToMatch('dist/test-project/styles.css', '@tailwind base; @tailwind components;'), + ); +}