Skip to content

Commit

Permalink
fix(@angular-devkit/build-angular): resolve transitive dependencies i…
Browse files Browse the repository at this point in the history
…n Sass when using Yarn PNP

Enchanced resolver is unable to resolve transitive dependencies in Sass when using Yarn PNP. The main reason for this is that Sass doesn't provide context on which file is requesting the module. See: sass/sass#3247

As a workaround for this we store previously resolved paths and when a new request comes in we try to resolve this from the previously resolved files if we are unable to resolve the request from the workspace root.
  • Loading branch information
alan-agius4 committed Oct 13, 2022
1 parent 253199a commit f480245
Showing 1 changed file with 30 additions and 13 deletions.
43 changes: 30 additions & 13 deletions packages/angular_devkit/build_angular/src/webpack/configs/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import * as fs from 'fs';
import MiniCssExtractPlugin from 'mini-css-extract-plugin';
import * as path from 'path';
import { dirname } from 'path';
import type { FileImporter } from 'sass';
import { pathToFileURL } from 'url';
import type { Configuration, LoaderContext, RuleSetUseItem } from 'webpack';
Expand Down Expand Up @@ -422,31 +423,47 @@ function getSassResolutionImporter(
mainFiles: ['_index', 'index', '...'],
});

/**
* This is required as SASS does not provide context from which the file is being resolved.
* This breaks Yarn PNP as transitive deps cannot be resolved from the workspace root.
*
* Workaround until https://github.com/sass/sass/issues/3247 is addressed.
*/
const contextPaths = new Set<string>([root]);

return {
findFileUrl: async (url, { fromImport }): Promise<URL | null> => {
if (url.charAt(0) === '.') {
// Let Sass handle relative imports.
return null;
}

let file: string | undefined;
const resolve = fromImport ? resolveImport : resolveModule;
let file: string | undefined;

for (const context of contextPaths) {
try {
file = await resolve(context, url);
} catch {
// Try to resolve a partial file
// @use '@material/button/button' as mdc-button;
// `@material/button/button` -> `@material/button/_button`
const lastSlashIndex = url.lastIndexOf('/');
const underscoreIndex = lastSlashIndex + 1;
if (underscoreIndex > 0 && url.charAt(underscoreIndex) !== '_') {
const partialFileUrl = `${url.slice(0, underscoreIndex)}_${url.slice(underscoreIndex)}`;
file = await resolve(context, partialFileUrl).catch(() => undefined);
}
}

if (file) {
contextPaths.add(dirname(file));

try {
file = await resolve(root, url);
} catch {
// Try to resolve a partial file
// @use '@material/button/button' as mdc-button;
// `@material/button/button` -> `@material/button/_button`
const lastSlashIndex = url.lastIndexOf('/');
const underscoreIndex = lastSlashIndex + 1;
if (underscoreIndex > 0 && url.charAt(underscoreIndex) !== '_') {
const partialFileUrl = `${url.slice(0, underscoreIndex)}_${url.slice(underscoreIndex)}`;
file = await resolve(root, partialFileUrl).catch(() => undefined);
return pathToFileURL(file);
}
}

return file ? pathToFileURL(file) : null;
return null;
},
};
}

0 comments on commit f480245

Please sign in to comment.