fix(@angular-devkit/build-angular): allow emitting multiple files with the same filename

Previously when hashing of media was disabled, if 2 files had the same name. Only one files used to be emitted. With this change we change the behaviour so that both files are emitted.

Closes #12186
This commit is contained in:
Alan Agius 2021-01-26 11:41:50 +01:00
parent 36a28e5226
commit a86ea3f154
4 changed files with 39 additions and 8 deletions

View File

@ -17,7 +17,7 @@ import {
RemoveHashPlugin,
SuppressExtractedTextChunksWebpackPlugin,
} from '../plugins';
import { getOutputHashFormat, normalizeExtraEntryPoints } from '../utils/helpers';
import { assetNameTemplateFactory, getOutputHashFormat, normalizeExtraEntryPoints } from '../utils/helpers';
// tslint:disable-next-line:no-big-function
export function getStylesConfig(wco: WebpackConfigOptions) {
@ -154,6 +154,8 @@ export function getStylesConfig(wco: WebpackConfigOptions) {
},
];
const assetNameTemplate = assetNameTemplateFactory(hashFormat);
const postcssOptionsCreator = (sourceMap: boolean, extracted: boolean | undefined) => {
return (loader: webpack.loader.LoaderContext) => ({
map: sourceMap && {
@ -183,7 +185,7 @@ export function getStylesConfig(wco: WebpackConfigOptions) {
deployUrl: buildOptions.deployUrl,
resourcesOutputPath: buildOptions.resourcesOutputPath,
loader,
filename: `[name]${hashFormat.file}.[ext]`,
filename: assetNameTemplate,
emitFile: buildOptions.platform !== 'server',
extracted,
}),

View File

@ -31,7 +31,7 @@ export interface PostcssCliResourcesOptions {
rebaseRootRelative?: boolean;
/** CSS is extracted to a `.css` or is embedded in a `.js` file. */
extracted?: boolean;
filename: string;
filename: (resourcePath: string) => string;
loader: webpack.loader.LoaderContext;
emitFile: boolean;
}
@ -114,9 +114,10 @@ export default function(options?: PostcssCliResourcesOptions): Plugin {
let outputPath = interpolateName(
{ resourcePath: result } as webpack.loader.LoaderContext,
filename,
{ content },
);
filename(result),
{ content, context: loader.context || loader.rootContext },
)
.replace(/\\|\//g, '-');
if (resourcesOutputPath) {
outputPath = path.posix.join(resourcesOutputPath, outputPath);

View File

@ -7,6 +7,7 @@
*/
import { basename, normalize } from '@angular-devkit/core';
import * as path from 'path';
import { ScriptTarget } from 'typescript';
import { Options, SourceMapDevToolPlugin } from 'webpack';
import { ExtraEntryPoint, ExtraEntryPointClass } from '../../browser/schema';
@ -124,3 +125,30 @@ export function getWatchOptions(poll: number | undefined): Options.WatchOptions
ignored: poll === undefined ? undefined : withWebpackFourOrFive(/[\\\/]node_modules[\\\/]/, 'node_modules/**'),
};
}
export function assetNameTemplateFactory(hashFormat: HashFormat): (resourcePath: string) => string {
const visitedFiles = new Map<string, string>();
return (resourcePath: string) => {
if (hashFormat.file) {
// File names are hashed therefore we don't need to handle files with the same file name.
return `[name]${hashFormat.file}.[ext]`;
}
const filename = path.basename(resourcePath);
// Check if the file with the same name has already been processed.
const visited = visitedFiles.get(filename);
if (!visited) {
// Not visited.
visitedFiles.set(filename, resourcePath);
return filename;
} else if (visited === resourcePath) {
// Same file.
return filename;
}
// File has the same name but it's in a different location.
return '[path][name].[ext]';
};
}