Skip to content

Commit

Permalink
fix(@angular-devkit/build-angular): account for package.json exports …
Browse files Browse the repository at this point in the history
…with Sass in esbuild builder

When using the experimental esbuild-based browser application builder, Sass module imports will
now resolve using esbuild's resolve methods. This allows for package.json exports and main fields
to be recognized when resolving an import or use rules in Sass files (scss or sass file extensions).

(cherry picked from commit 0662a2e)
  • Loading branch information
clydin authored and dgp1130 committed Nov 4, 2022
1 parent 1e29b81 commit 0014459
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 8 deletions.
Expand Up @@ -8,19 +8,23 @@

import type { PartialMessage, Plugin, PluginBuild } from 'esbuild';
import { readFile } from 'node:fs/promises';
import { dirname, relative } from 'node:path';
import { dirname, join, relative } from 'node:path';
import { fileURLToPath, pathToFileURL } from 'node:url';
import type { CompileResult, Exception } from 'sass';
import { SassWorkerImplementation } from '../../sass/sass-service';
import {
FileImporterWithRequestContextOptions,
SassWorkerImplementation,
} from '../../sass/sass-service';

let sassWorkerPool: SassWorkerImplementation;
let sassWorkerPool: SassWorkerImplementation | undefined;

function isSassException(error: unknown): error is Exception {
return !!error && typeof error === 'object' && 'sassMessage' in error;
}

export function shutdownSassWorkerPool(): void {
sassWorkerPool?.close();
sassWorkerPool = undefined;
}

export function createSassPlugin(options: { sourcemap: boolean; loadPaths?: string[] }): Plugin {
Expand All @@ -41,6 +45,61 @@ export function createSassPlugin(options: { sourcemap: boolean; loadPaths?: stri
sourceMap: options.sourcemap,
sourceMapIncludeSources: options.sourcemap,
quietDeps: true,
importers: [
{
findFileUrl: async (
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,
});
}
}

// 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,
),
);
}
}
}

return result.path ? pathToFileURL(result.path) : null;
},
},
],
logger: {
warn: (text, { deprecation, span }) => {
warnings.push({
Expand Down
Expand Up @@ -27,10 +27,6 @@ async function bundleStylesheet(
entry: Required<Pick<BuildOptions, 'stdin'> | Pick<BuildOptions, 'entryPoints'>>,
options: BundleStylesheetOptions,
) {
const loadPaths = options.includePaths ?? [];
// Needed to resolve node packages.
loadPaths.push(path.join(options.workspaceRoot, 'node_modules'));

// Execute esbuild
const result = await bundle({
...entry,
Expand All @@ -50,7 +46,7 @@ async function bundleStylesheet(
conditions: ['style', 'sass'],
mainFields: ['style', 'sass'],
plugins: [
createSassPlugin({ sourcemap: !!options.sourcemap, loadPaths }),
createSassPlugin({ sourcemap: !!options.sourcemap, loadPaths: options.includePaths }),
createCssResourcePlugin(),
],
});
Expand Down

0 comments on commit 0014459

Please sign in to comment.