Skip to content
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

fix(@angular-devkit/build-angular): improve package deep import Sass index resolution in esbuild plugin #24279

Merged
merged 1 commit into from Nov 21, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -31,6 +31,30 @@ export function createSassPlugin(options: { sourcemap: boolean; loadPaths?: stri
return {
name: 'angular-sass',
setup(build: PluginBuild): void {
const resolveUrl = async (url: string, previousResolvedModules?: Set<string>) => {
let result = await build.resolve(url, {
kind: 'import-rule',
// This should ideally be the directory of the importer file from Sass
// but that is not currently available from the Sass importer API.
resolveDir: build.initialOptions.absWorkingDir,
});

// Workaround to support Yarn PnP without access to the importer file from Sass
if (!result.path && previousResolvedModules?.size) {
for (const previous of previousResolvedModules) {
result = await build.resolve(url, {
kind: 'import-rule',
resolveDir: previous,
});
if (result.path) {
break;
}
}
}

return result;
};

build.onLoad({ filter: /\.s[ac]ss$/ }, async (args) => {
// Lazily load Sass when a Sass file is found
sassWorkerPool ??= new SassWorkerImplementation(true);
Expand All @@ -51,48 +75,30 @@ export function createSassPlugin(options: { sourcemap: boolean; loadPaths?: stri
url,
{ previousResolvedModules }: FileImporterWithRequestContextOptions,
): Promise<URL | null> => {
let result = await build.resolve(url, {
kind: 'import-rule',
// This should ideally be the directory of the importer file from Sass
// but that is not currently available from the Sass importer API.
resolveDir: build.initialOptions.absWorkingDir,
});

// Workaround to support Yarn PnP without access to the importer file from Sass
if (!result.path && previousResolvedModules?.size) {
for (const previous of previousResolvedModules) {
result = await build.resolve(url, {
kind: 'import-rule',
resolveDir: previous,
});
}
}
const result = await resolveUrl(url, previousResolvedModules);

// Check for package deep imports
if (!result.path) {
const parts = url.split('/');
const hasScope = parts.length > 2 && parts[0].startsWith('@');
if (hasScope || parts.length > 1) {
const [nameOrScope, nameOrFirstPath, ...pathPart] = parts;
const packageName = hasScope
? `${nameOrScope}/${nameOrFirstPath}`
: nameOrScope;
const packageResult = await build.resolve(packageName + '/package.json', {
kind: 'import-rule',
// This should ideally be the directory of the importer file from Sass
// but that is not currently available from the Sass importer API.
resolveDir: build.initialOptions.absWorkingDir,
});

if (packageResult.path) {
return pathToFileURL(
join(
dirname(packageResult.path),
!hasScope ? nameOrFirstPath : '',
...pathPart,
),
);
}
const hasScope = parts.length >= 2 && parts[0].startsWith('@');
const [nameOrScope, nameOrFirstPath, ...pathPart] = parts;
const packageName = hasScope
? `${nameOrScope}/${nameOrFirstPath}`
: nameOrScope;

const packageResult = await resolveUrl(
packageName + '/package.json',
previousResolvedModules,
);

if (packageResult.path) {
return pathToFileURL(
join(
dirname(packageResult.path),
!hasScope ? nameOrFirstPath : '',
...pathPart,
),
);
}
}

Expand Down