mirror of
https://github.com/angular/angular-cli.git
synced 2025-05-26 01:01:13 +08:00
fix(@angular-devkit/build-angular): update list of known tailwind configuration files
With this change we added `tailwind.config.mjs` and `tailwind.config.ts` to known tailwind config files. Closes #24943
This commit is contained in:
parent
d5fed32096
commit
758b0695f3
@ -13,6 +13,7 @@ import path from 'node:path';
|
|||||||
import { normalizeAssetPatterns, normalizeOptimization, normalizeSourceMaps } from '../../utils';
|
import { normalizeAssetPatterns, normalizeOptimization, normalizeSourceMaps } from '../../utils';
|
||||||
import { normalizeCacheOptions } from '../../utils/normalize-cache';
|
import { normalizeCacheOptions } from '../../utils/normalize-cache';
|
||||||
import { generateEntryPoints } from '../../utils/package-chunk-sort';
|
import { generateEntryPoints } from '../../utils/package-chunk-sort';
|
||||||
|
import { findTailwindConfigurationFile } from '../../utils/tailwind';
|
||||||
import { getIndexInputFile, getIndexOutputFile } from '../../utils/webpack-browser-config';
|
import { getIndexInputFile, getIndexOutputFile } from '../../utils/webpack-browser-config';
|
||||||
import { globalScriptsByBundleName, normalizeGlobalStyles } from '../../webpack/utils/helpers';
|
import { globalScriptsByBundleName, normalizeGlobalStyles } from '../../webpack/utils/helpers';
|
||||||
import { Schema as BrowserBuilderOptions, OutputHashing } from './schema';
|
import { Schema as BrowserBuilderOptions, OutputHashing } from './schema';
|
||||||
@ -97,7 +98,7 @@ export async function normalizeOptions(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let tailwindConfiguration: { file: string; package: string } | undefined;
|
let tailwindConfiguration: { file: string; package: string } | undefined;
|
||||||
const tailwindConfigurationPath = findTailwindConfigurationFile(workspaceRoot, projectRoot);
|
const tailwindConfigurationPath = await findTailwindConfigurationFile(workspaceRoot, projectRoot);
|
||||||
if (tailwindConfigurationPath) {
|
if (tailwindConfigurationPath) {
|
||||||
// Create a node resolver at the project root as a directory
|
// Create a node resolver at the project root as a directory
|
||||||
const resolver = createRequire(projectRoot + '/');
|
const resolver = createRequire(projectRoot + '/');
|
||||||
@ -203,27 +204,6 @@ export async function normalizeOptions(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function findTailwindConfigurationFile(
|
|
||||||
workspaceRoot: string,
|
|
||||||
projectRoot: string,
|
|
||||||
): 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, workspaceRoot]) {
|
|
||||||
for (const configFile of tailwindConfigFiles) {
|
|
||||||
// Project level configuration should always take precedence.
|
|
||||||
const fullPath = path.join(basePath, configFile);
|
|
||||||
if (fs.existsSync(fullPath)) {
|
|
||||||
return fullPath;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Normalize a directory path string.
|
* Normalize a directory path string.
|
||||||
* Currently only removes a trailing slash if present.
|
* Currently only removes a trailing slash if present.
|
||||||
|
40
packages/angular_devkit/build_angular/src/utils/tailwind.ts
Normal file
40
packages/angular_devkit/build_angular/src/utils/tailwind.ts
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Google LLC All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by an MIT-style license that can be
|
||||||
|
* found in the LICENSE file at https://angular.io/license
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { readdir } from 'node:fs/promises';
|
||||||
|
import { join } from 'node:path';
|
||||||
|
|
||||||
|
const tailwindConfigFiles: string[] = [
|
||||||
|
'tailwind.config.js',
|
||||||
|
'tailwind.config.cjs',
|
||||||
|
'tailwind.config.mjs',
|
||||||
|
'tailwind.config.ts',
|
||||||
|
];
|
||||||
|
|
||||||
|
export async function findTailwindConfigurationFile(
|
||||||
|
workspaceRoot: string,
|
||||||
|
projectRoot: string,
|
||||||
|
): Promise<string | undefined> {
|
||||||
|
const dirEntries = [projectRoot, workspaceRoot].map((root) =>
|
||||||
|
readdir(root, { withFileTypes: false }).then((entries) => ({
|
||||||
|
root,
|
||||||
|
files: new Set(entries),
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
|
||||||
|
// A configuration file can exist in the project or workspace root
|
||||||
|
for await (const { root, files } of dirEntries) {
|
||||||
|
for (const potentialConfig of tailwindConfigFiles) {
|
||||||
|
if (files.has(potentialConfig)) {
|
||||||
|
return join(root, potentialConfig);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
}
|
@ -7,7 +7,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import MiniCssExtractPlugin from 'mini-css-extract-plugin';
|
import MiniCssExtractPlugin from 'mini-css-extract-plugin';
|
||||||
import * as fs from 'node:fs';
|
|
||||||
import * as path from 'node:path';
|
import * as path from 'node:path';
|
||||||
import { pathToFileURL } from 'node:url';
|
import { pathToFileURL } from 'node:url';
|
||||||
import type { FileImporter } from 'sass';
|
import type { FileImporter } from 'sass';
|
||||||
@ -19,6 +18,7 @@ import {
|
|||||||
import { SassLegacyWorkerImplementation } from '../../sass/sass-service-legacy';
|
import { SassLegacyWorkerImplementation } from '../../sass/sass-service-legacy';
|
||||||
import { WebpackConfigOptions } from '../../utils/build-options';
|
import { WebpackConfigOptions } from '../../utils/build-options';
|
||||||
import { useLegacySass } from '../../utils/environment-options';
|
import { useLegacySass } from '../../utils/environment-options';
|
||||||
|
import { findTailwindConfigurationFile } from '../../utils/tailwind';
|
||||||
import {
|
import {
|
||||||
AnyComponentStyleBudgetChecker,
|
AnyComponentStyleBudgetChecker,
|
||||||
PostcssCliResources,
|
PostcssCliResources,
|
||||||
@ -34,8 +34,8 @@ import {
|
|||||||
} from '../utils/helpers';
|
} from '../utils/helpers';
|
||||||
|
|
||||||
// eslint-disable-next-line max-lines-per-function
|
// eslint-disable-next-line max-lines-per-function
|
||||||
export function getStylesConfig(wco: WebpackConfigOptions): Configuration {
|
export async function getStylesConfig(wco: WebpackConfigOptions): Promise<Configuration> {
|
||||||
const { root, buildOptions, logger } = wco;
|
const { root, buildOptions, logger, projectRoot } = wco;
|
||||||
const extraPlugins: Configuration['plugins'] = [];
|
const extraPlugins: Configuration['plugins'] = [];
|
||||||
|
|
||||||
extraPlugins.push(new AnyComponentStyleBudgetChecker(buildOptions.budgets));
|
extraPlugins.push(new AnyComponentStyleBudgetChecker(buildOptions.budgets));
|
||||||
@ -86,13 +86,13 @@ export function getStylesConfig(wco: WebpackConfigOptions): Configuration {
|
|||||||
// Only load Tailwind CSS plugin if configuration file was found.
|
// 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.
|
// 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.
|
// The package may be unknowningly present due to a third-party transitive package dependency.
|
||||||
const tailwindConfigPath = getTailwindConfigPath(wco);
|
const tailwindConfigPath = await findTailwindConfigurationFile(root, projectRoot);
|
||||||
if (tailwindConfigPath) {
|
if (tailwindConfigPath) {
|
||||||
let tailwindPackagePath;
|
let tailwindPackagePath;
|
||||||
try {
|
try {
|
||||||
tailwindPackagePath = require.resolve('tailwindcss', { paths: [wco.root] });
|
tailwindPackagePath = require.resolve('tailwindcss', { paths: [root] });
|
||||||
} catch {
|
} catch {
|
||||||
const relativeTailwindConfigPath = path.relative(wco.root, tailwindConfigPath);
|
const relativeTailwindConfigPath = path.relative(root, tailwindConfigPath);
|
||||||
logger.warn(
|
logger.warn(
|
||||||
`Tailwind CSS configuration file found (${relativeTailwindConfigPath})` +
|
`Tailwind CSS configuration file found (${relativeTailwindConfigPath})` +
|
||||||
` but the 'tailwindcss' package is not installed.` +
|
` but the 'tailwindcss' package is not installed.` +
|
||||||
@ -315,24 +315,6 @@ export function getStylesConfig(wco: WebpackConfigOptions): Configuration {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getSassLoaderOptions(
|
function getSassLoaderOptions(
|
||||||
root: string,
|
root: string,
|
||||||
implementation: SassWorkerImplementation | SassLegacyWorkerImplementation,
|
implementation: SassWorkerImplementation | SassLegacyWorkerImplementation,
|
||||||
@ -399,7 +381,7 @@ function getSassResolutionImporter(
|
|||||||
root: string,
|
root: string,
|
||||||
preserveSymlinks: boolean,
|
preserveSymlinks: boolean,
|
||||||
): FileImporter<'async'> {
|
): FileImporter<'async'> {
|
||||||
const commonResolverOptions: Parameters<typeof loaderContext['getResolve']>[0] = {
|
const commonResolverOptions: Parameters<(typeof loaderContext)['getResolve']>[0] = {
|
||||||
conditionNames: ['sass', 'style'],
|
conditionNames: ['sass', 'style'],
|
||||||
mainFields: ['sass', 'style', 'main', '...'],
|
mainFields: ['sass', 'style', 'main', '...'],
|
||||||
extensions: ['.scss', '.sass', '.css'],
|
extensions: ['.scss', '.sass', '.css'],
|
||||||
|
Loading…
x
Reference in New Issue
Block a user