Skip to content

fix(@angular-devkit/build-angular): detect tailwind.config.cjs as valid tailwindcss configuration #23240

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 27, 2022
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
29 changes: 19 additions & 10 deletions packages/angular_devkit/build_angular/src/webpack/configs/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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;
}
39 changes: 39 additions & 0 deletions tests/legacy-cli/e2e/tests/build/styles/tailwind-v3-cjs.ts
Original file line number Diff line number Diff line change
@@ -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;'),
);
}