@angular-devkit/build-angular 15.0.0-rc.2 → 15.0.0-rc.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +14 -14
- package/src/builders/browser-esbuild/css-resource-plugin.js +8 -0
- package/src/builders/browser-esbuild/sass-plugin.js +44 -1
- package/src/builders/browser-esbuild/stylesheets.js +4 -7
- package/src/builders/server/index.js +16 -19
- package/src/sass/rebasing-importer.d.ts +98 -0
- package/src/sass/rebasing-importer.js +281 -0
- package/src/sass/sass-service.d.ts +2 -0
- package/src/sass/sass-service.js +5 -2
- package/src/sass/worker.js +56 -24
- package/src/webpack/configs/common.js +1 -1
- package/src/webpack/configs/styles.js +17 -10
- package/src/webpack/utils/helpers.d.ts +5 -0
- package/src/webpack/utils/helpers.js +15 -1
package/package.json
CHANGED
|
@@ -1,37 +1,37 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@angular-devkit/build-angular",
|
|
3
|
-
"version": "15.0.0-rc.
|
|
3
|
+
"version": "15.0.0-rc.3",
|
|
4
4
|
"description": "Angular Webpack Build Facade",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"typings": "src/index.d.ts",
|
|
7
7
|
"builders": "builders.json",
|
|
8
8
|
"dependencies": {
|
|
9
9
|
"@ampproject/remapping": "2.2.0",
|
|
10
|
-
"@angular-devkit/architect": "0.1500.0-rc.
|
|
11
|
-
"@angular-devkit/build-webpack": "0.1500.0-rc.
|
|
12
|
-
"@angular-devkit/core": "15.0.0-rc.
|
|
13
|
-
"@babel/core": "7.
|
|
14
|
-
"@babel/generator": "7.20.
|
|
10
|
+
"@angular-devkit/architect": "0.1500.0-rc.3",
|
|
11
|
+
"@angular-devkit/build-webpack": "0.1500.0-rc.3",
|
|
12
|
+
"@angular-devkit/core": "15.0.0-rc.3",
|
|
13
|
+
"@babel/core": "7.20.2",
|
|
14
|
+
"@babel/generator": "7.20.3",
|
|
15
15
|
"@babel/helper-annotate-as-pure": "7.18.6",
|
|
16
16
|
"@babel/plugin-proposal-async-generator-functions": "7.20.1",
|
|
17
17
|
"@babel/plugin-transform-async-to-generator": "7.18.6",
|
|
18
18
|
"@babel/plugin-transform-runtime": "7.19.6",
|
|
19
|
-
"@babel/preset-env": "7.
|
|
19
|
+
"@babel/preset-env": "7.20.2",
|
|
20
20
|
"@babel/runtime": "7.20.1",
|
|
21
21
|
"@babel/template": "7.18.10",
|
|
22
22
|
"@discoveryjs/json-ext": "0.5.7",
|
|
23
|
-
"@ngtools/webpack": "15.0.0-rc.
|
|
23
|
+
"@ngtools/webpack": "15.0.0-rc.3",
|
|
24
24
|
"ansi-colors": "4.1.3",
|
|
25
25
|
"autoprefixer": "10.4.13",
|
|
26
|
-
"babel-loader": "9.0
|
|
26
|
+
"babel-loader": "9.1.0",
|
|
27
27
|
"babel-plugin-istanbul": "6.1.1",
|
|
28
28
|
"browserslist": "^4.9.1",
|
|
29
|
-
"cacache": "17.0.
|
|
29
|
+
"cacache": "17.0.2",
|
|
30
30
|
"chokidar": "3.5.3",
|
|
31
31
|
"copy-webpack-plugin": "11.0.0",
|
|
32
32
|
"critters": "0.0.16",
|
|
33
33
|
"css-loader": "6.7.1",
|
|
34
|
-
"esbuild-wasm": "0.15.
|
|
34
|
+
"esbuild-wasm": "0.15.13",
|
|
35
35
|
"glob": "8.0.3",
|
|
36
36
|
"https-proxy-agent": "5.0.1",
|
|
37
37
|
"inquirer": "8.2.4",
|
|
@@ -41,8 +41,8 @@
|
|
|
41
41
|
"less-loader": "11.1.0",
|
|
42
42
|
"license-webpack-plugin": "4.0.2",
|
|
43
43
|
"loader-utils": "3.2.0",
|
|
44
|
+
"magic-string": "0.26.7",
|
|
44
45
|
"mini-css-extract-plugin": "2.6.1",
|
|
45
|
-
"minimatch": "5.1.0",
|
|
46
46
|
"open": "8.4.0",
|
|
47
47
|
"ora": "5.4.1",
|
|
48
48
|
"parse5-html-rewriting-stream": "6.0.1",
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
"regenerator-runtime": "0.13.10",
|
|
53
53
|
"resolve-url-loader": "5.0.0",
|
|
54
54
|
"rxjs": "6.6.7",
|
|
55
|
-
"sass": "1.
|
|
55
|
+
"sass": "1.56.0",
|
|
56
56
|
"sass-loader": "13.1.0",
|
|
57
57
|
"semver": "7.3.8",
|
|
58
58
|
"source-map-loader": "4.0.1",
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
"webpack-subresource-integrity": "5.1.0"
|
|
69
69
|
},
|
|
70
70
|
"optionalDependencies": {
|
|
71
|
-
"esbuild": "0.15.
|
|
71
|
+
"esbuild": "0.15.13"
|
|
72
72
|
},
|
|
73
73
|
"peerDependencies": {
|
|
74
74
|
"@angular/compiler-cli": "^15.0.0-next",
|
|
@@ -33,6 +33,14 @@ function createCssResourcePlugin() {
|
|
|
33
33
|
if (args.kind !== 'url-token' || ((_a = args.pluginData) === null || _a === void 0 ? void 0 : _a[CSS_RESOURCE_RESOLUTION])) {
|
|
34
34
|
return null;
|
|
35
35
|
}
|
|
36
|
+
// If root-relative, absolute or protocol relative url, mark as external to leave the
|
|
37
|
+
// path/URL in place.
|
|
38
|
+
if (/^((?:\w+:)?\/\/|data:|chrome:|#|\/)/.test(args.path)) {
|
|
39
|
+
return {
|
|
40
|
+
path: args.path,
|
|
41
|
+
external: true,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
36
44
|
const { importer, kind, resolveDir, namespace, pluginData = {} } = args;
|
|
37
45
|
pluginData[CSS_RESOURCE_RESOLUTION] = true;
|
|
38
46
|
const result = await build.resolve(args.path, {
|
|
@@ -18,6 +18,7 @@ function isSassException(error) {
|
|
|
18
18
|
}
|
|
19
19
|
function shutdownSassWorkerPool() {
|
|
20
20
|
sassWorkerPool === null || sassWorkerPool === void 0 ? void 0 : sassWorkerPool.close();
|
|
21
|
+
sassWorkerPool = undefined;
|
|
21
22
|
}
|
|
22
23
|
exports.shutdownSassWorkerPool = shutdownSassWorkerPool;
|
|
23
24
|
function createSassPlugin(options) {
|
|
@@ -26,7 +27,7 @@ function createSassPlugin(options) {
|
|
|
26
27
|
setup(build) {
|
|
27
28
|
build.onLoad({ filter: /\.s[ac]ss$/ }, async (args) => {
|
|
28
29
|
// Lazily load Sass when a Sass file is found
|
|
29
|
-
sassWorkerPool !== null && sassWorkerPool !== void 0 ? sassWorkerPool : (sassWorkerPool = new sass_service_1.SassWorkerImplementation());
|
|
30
|
+
sassWorkerPool !== null && sassWorkerPool !== void 0 ? sassWorkerPool : (sassWorkerPool = new sass_service_1.SassWorkerImplementation(true));
|
|
30
31
|
const warnings = [];
|
|
31
32
|
try {
|
|
32
33
|
const data = await (0, promises_1.readFile)(args.path, 'utf-8');
|
|
@@ -37,6 +38,48 @@ function createSassPlugin(options) {
|
|
|
37
38
|
sourceMap: options.sourcemap,
|
|
38
39
|
sourceMapIncludeSources: options.sourcemap,
|
|
39
40
|
quietDeps: true,
|
|
41
|
+
importers: [
|
|
42
|
+
{
|
|
43
|
+
findFileUrl: async (url, { previousResolvedModules }) => {
|
|
44
|
+
let result = await build.resolve(url, {
|
|
45
|
+
kind: 'import-rule',
|
|
46
|
+
// This should ideally be the directory of the importer file from Sass
|
|
47
|
+
// but that is not currently available from the Sass importer API.
|
|
48
|
+
resolveDir: build.initialOptions.absWorkingDir,
|
|
49
|
+
});
|
|
50
|
+
// Workaround to support Yarn PnP without access to the importer file from Sass
|
|
51
|
+
if (!result.path && (previousResolvedModules === null || previousResolvedModules === void 0 ? void 0 : previousResolvedModules.size)) {
|
|
52
|
+
for (const previous of previousResolvedModules) {
|
|
53
|
+
result = await build.resolve(url, {
|
|
54
|
+
kind: 'import-rule',
|
|
55
|
+
resolveDir: previous,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// Check for package deep imports
|
|
60
|
+
if (!result.path) {
|
|
61
|
+
const parts = url.split('/');
|
|
62
|
+
const hasScope = parts.length > 2 && parts[0].startsWith('@');
|
|
63
|
+
if (hasScope || parts.length > 1) {
|
|
64
|
+
const [nameOrScope, nameOrFirstPath, ...pathPart] = parts;
|
|
65
|
+
const packageName = hasScope
|
|
66
|
+
? `${nameOrScope}/${nameOrFirstPath}`
|
|
67
|
+
: nameOrScope;
|
|
68
|
+
const packageResult = await build.resolve(packageName + '/package.json', {
|
|
69
|
+
kind: 'import-rule',
|
|
70
|
+
// This should ideally be the directory of the importer file from Sass
|
|
71
|
+
// but that is not currently available from the Sass importer API.
|
|
72
|
+
resolveDir: build.initialOptions.absWorkingDir,
|
|
73
|
+
});
|
|
74
|
+
if (packageResult.path) {
|
|
75
|
+
return (0, node_url_1.pathToFileURL)((0, node_path_1.join)((0, node_path_1.dirname)(packageResult.path), !hasScope ? nameOrFirstPath : '', ...pathPart));
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return result.path ? (0, node_url_1.pathToFileURL)(result.path) : null;
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
],
|
|
40
83
|
logger: {
|
|
41
84
|
warn: (text, { deprecation, span }) => {
|
|
42
85
|
warnings.push({
|
|
@@ -36,17 +36,14 @@ const css_resource_plugin_1 = require("./css-resource-plugin");
|
|
|
36
36
|
const esbuild_1 = require("./esbuild");
|
|
37
37
|
const sass_plugin_1 = require("./sass-plugin");
|
|
38
38
|
async function bundleStylesheet(entry, options) {
|
|
39
|
-
var _a, _b
|
|
40
|
-
const loadPaths = (_a = options.includePaths) !== null && _a !== void 0 ? _a : [];
|
|
41
|
-
// Needed to resolve node packages.
|
|
42
|
-
loadPaths.push(path.join(options.workspaceRoot, 'node_modules'));
|
|
39
|
+
var _a, _b;
|
|
43
40
|
// Execute esbuild
|
|
44
41
|
const result = await (0, esbuild_1.bundle)({
|
|
45
42
|
...entry,
|
|
46
43
|
absWorkingDir: options.workspaceRoot,
|
|
47
44
|
bundle: true,
|
|
48
|
-
entryNames: (
|
|
49
|
-
assetNames: (
|
|
45
|
+
entryNames: (_a = options.outputNames) === null || _a === void 0 ? void 0 : _a.bundles,
|
|
46
|
+
assetNames: (_b = options.outputNames) === null || _b === void 0 ? void 0 : _b.media,
|
|
50
47
|
logLevel: 'silent',
|
|
51
48
|
minify: options.optimization,
|
|
52
49
|
sourcemap: options.sourcemap,
|
|
@@ -59,7 +56,7 @@ async function bundleStylesheet(entry, options) {
|
|
|
59
56
|
conditions: ['style', 'sass'],
|
|
60
57
|
mainFields: ['style', 'sass'],
|
|
61
58
|
plugins: [
|
|
62
|
-
(0, sass_plugin_1.createSassPlugin)({ sourcemap: !!options.sourcemap, loadPaths }),
|
|
59
|
+
(0, sass_plugin_1.createSassPlugin)({ sourcemap: !!options.sourcemap, loadPaths: options.includePaths }),
|
|
63
60
|
(0, css_resource_plugin_1.createCssResourcePlugin)(),
|
|
64
61
|
],
|
|
65
62
|
});
|
|
@@ -43,6 +43,7 @@ const purge_cache_1 = require("../../utils/purge-cache");
|
|
|
43
43
|
const version_1 = require("../../utils/version");
|
|
44
44
|
const webpack_browser_config_1 = require("../../utils/webpack-browser-config");
|
|
45
45
|
const configs_1 = require("../../webpack/configs");
|
|
46
|
+
const helpers_1 = require("../../webpack/utils/helpers");
|
|
46
47
|
const stats_1 = require("../../webpack/utils/stats");
|
|
47
48
|
/**
|
|
48
49
|
* @experimental Direct usage of this function is considered experimental.
|
|
@@ -127,23 +128,19 @@ async function initialize(options, context, webpackConfigurationTransform) {
|
|
|
127
128
|
function getPlatformServerExportsConfig(wco) {
|
|
128
129
|
// Add `@angular/platform-server` exports.
|
|
129
130
|
// This is needed so that DI tokens can be referenced and set at runtime outside of the bundle.
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
},
|
|
146
|
-
],
|
|
147
|
-
},
|
|
148
|
-
};
|
|
131
|
+
// Only add `@angular/platform-server` exports when it is installed.
|
|
132
|
+
// In some cases this builder is used when `@angular/platform-server` is not installed.
|
|
133
|
+
// Example: when using `@nguniversal/common/clover` which does not need `@angular/platform-server`.
|
|
134
|
+
return (0, helpers_1.isPlatformServerInstalled)(wco.root)
|
|
135
|
+
? {
|
|
136
|
+
module: {
|
|
137
|
+
rules: [
|
|
138
|
+
{
|
|
139
|
+
loader: require.resolve('./platform-server-exports-loader'),
|
|
140
|
+
include: [path.resolve(wco.root, wco.buildOptions.main)],
|
|
141
|
+
},
|
|
142
|
+
],
|
|
143
|
+
},
|
|
144
|
+
}
|
|
145
|
+
: {};
|
|
149
146
|
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright Google LLC All Rights Reserved.
|
|
4
|
+
*
|
|
5
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
6
|
+
* found in the LICENSE file at https://angular.io/license
|
|
7
|
+
*/
|
|
8
|
+
/// <reference types="node" />
|
|
9
|
+
/// <reference types="node" />
|
|
10
|
+
import { RawSourceMap } from '@ampproject/remapping';
|
|
11
|
+
import { Dirent } from 'node:fs';
|
|
12
|
+
import type { FileImporter, Importer, ImporterResult } from 'sass';
|
|
13
|
+
/**
|
|
14
|
+
* A Sass Importer base class that provides the load logic to rebase all `url()` functions
|
|
15
|
+
* within a stylesheet. The rebasing will ensure that the URLs in the output of the Sass compiler
|
|
16
|
+
* reflect the final filesystem location of the output CSS file.
|
|
17
|
+
*
|
|
18
|
+
* This class provides the core of the rebasing functionality. To ensure that each file is processed
|
|
19
|
+
* by this importer's load implementation, the Sass compiler requires the importer's canonicalize
|
|
20
|
+
* function to return a non-null value with the resolved location of the requested stylesheet.
|
|
21
|
+
* Concrete implementations of this class must provide this canonicalize functionality for rebasing
|
|
22
|
+
* to be effective.
|
|
23
|
+
*/
|
|
24
|
+
declare abstract class UrlRebasingImporter implements Importer<'sync'> {
|
|
25
|
+
private entryDirectory;
|
|
26
|
+
private rebaseSourceMaps?;
|
|
27
|
+
/**
|
|
28
|
+
* @param entryDirectory The directory of the entry stylesheet that was passed to the Sass compiler.
|
|
29
|
+
* @param rebaseSourceMaps When provided, rebased files will have an intermediate sourcemap added to the Map
|
|
30
|
+
* which can be used to generate a final sourcemap that contains original sources.
|
|
31
|
+
*/
|
|
32
|
+
constructor(entryDirectory: string, rebaseSourceMaps?: Map<string, RawSourceMap> | undefined);
|
|
33
|
+
abstract canonicalize(url: string, options: {
|
|
34
|
+
fromImport: boolean;
|
|
35
|
+
}): URL | null;
|
|
36
|
+
load(canonicalUrl: URL): ImporterResult | null;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Provides the Sass importer logic to resolve relative stylesheet imports via both import and use rules
|
|
40
|
+
* and also rebase any `url()` function usage within those stylesheets. The rebasing will ensure that
|
|
41
|
+
* the URLs in the output of the Sass compiler reflect the final filesystem location of the output CSS file.
|
|
42
|
+
*/
|
|
43
|
+
export declare class RelativeUrlRebasingImporter extends UrlRebasingImporter {
|
|
44
|
+
private directoryCache;
|
|
45
|
+
constructor(entryDirectory: string, directoryCache?: Map<string, Dirent[]>, rebaseSourceMaps?: Map<string, RawSourceMap>);
|
|
46
|
+
canonicalize(url: string, options: {
|
|
47
|
+
fromImport: boolean;
|
|
48
|
+
}): URL | null;
|
|
49
|
+
/**
|
|
50
|
+
* Attempts to resolve a provided URL to a stylesheet file using the Sass compiler's resolution algorithm.
|
|
51
|
+
* Based on https://github.com/sass/dart-sass/blob/44d6bb6ac72fe6b93f5bfec371a1fffb18e6b76d/lib/src/importer/utils.dart
|
|
52
|
+
* @param url The file protocol URL to resolve.
|
|
53
|
+
* @param fromImport If true, URL was from an import rule; otherwise from a use rule.
|
|
54
|
+
* @param checkDirectory If true, try checking for a directory with the base name containing an index file.
|
|
55
|
+
* @returns A full resolved URL of the stylesheet file or `null` if not found.
|
|
56
|
+
*/
|
|
57
|
+
private resolveImport;
|
|
58
|
+
/**
|
|
59
|
+
* Checks an array of potential stylesheet files to determine if there is a valid
|
|
60
|
+
* stylesheet file. More than one discovered file may indicate an error.
|
|
61
|
+
* @param found An array of discovered stylesheet files.
|
|
62
|
+
* @returns A fully resolved URL for a stylesheet file or `null` if not found.
|
|
63
|
+
* @throws If there are ambiguous files discovered.
|
|
64
|
+
*/
|
|
65
|
+
private checkFound;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Provides the Sass importer logic to resolve module (npm package) stylesheet imports via both import and
|
|
69
|
+
* use rules and also rebase any `url()` function usage within those stylesheets. The rebasing will ensure that
|
|
70
|
+
* the URLs in the output of the Sass compiler reflect the final filesystem location of the output CSS file.
|
|
71
|
+
*/
|
|
72
|
+
export declare class ModuleUrlRebasingImporter extends RelativeUrlRebasingImporter {
|
|
73
|
+
private finder;
|
|
74
|
+
constructor(entryDirectory: string, directoryCache: Map<string, Dirent[]>, rebaseSourceMaps: Map<string, RawSourceMap> | undefined, finder: FileImporter<'sync'>['findFileUrl']);
|
|
75
|
+
canonicalize(url: string, options: {
|
|
76
|
+
fromImport: boolean;
|
|
77
|
+
}): URL | null;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Provides the Sass importer logic to resolve load paths located stylesheet imports via both import and
|
|
81
|
+
* use rules and also rebase any `url()` function usage within those stylesheets. The rebasing will ensure that
|
|
82
|
+
* the URLs in the output of the Sass compiler reflect the final filesystem location of the output CSS file.
|
|
83
|
+
*/
|
|
84
|
+
export declare class LoadPathsUrlRebasingImporter extends RelativeUrlRebasingImporter {
|
|
85
|
+
private loadPaths;
|
|
86
|
+
constructor(entryDirectory: string, directoryCache: Map<string, Dirent[]>, rebaseSourceMaps: Map<string, RawSourceMap> | undefined, loadPaths: Iterable<string>);
|
|
87
|
+
canonicalize(url: string, options: {
|
|
88
|
+
fromImport: boolean;
|
|
89
|
+
}): URL | null;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Workaround for Sass not calling instance methods with `this`.
|
|
93
|
+
* The `canonicalize` and `load` methods will be bound to the class instance.
|
|
94
|
+
* @param importer A Sass importer to bind.
|
|
95
|
+
* @returns The bound Sass importer.
|
|
96
|
+
*/
|
|
97
|
+
export declare function sassBindWorkaround<T extends Importer>(importer: T): T;
|
|
98
|
+
export {};
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @license
|
|
4
|
+
* Copyright Google LLC All Rights Reserved.
|
|
5
|
+
*
|
|
6
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
7
|
+
* found in the LICENSE file at https://angular.io/license
|
|
8
|
+
*/
|
|
9
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
10
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
11
|
+
};
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.sassBindWorkaround = exports.LoadPathsUrlRebasingImporter = exports.ModuleUrlRebasingImporter = exports.RelativeUrlRebasingImporter = void 0;
|
|
14
|
+
const magic_string_1 = __importDefault(require("magic-string"));
|
|
15
|
+
const node_fs_1 = require("node:fs");
|
|
16
|
+
const node_path_1 = require("node:path");
|
|
17
|
+
const node_url_1 = require("node:url");
|
|
18
|
+
/**
|
|
19
|
+
* A Regular expression used to find all `url()` functions within a stylesheet.
|
|
20
|
+
* From packages/angular_devkit/build_angular/src/webpack/plugins/postcss-cli-resources.ts
|
|
21
|
+
*/
|
|
22
|
+
const URL_REGEXP = /url(?:\(\s*(['"]?))(.*?)(?:\1\s*\))/g;
|
|
23
|
+
/**
|
|
24
|
+
* A Sass Importer base class that provides the load logic to rebase all `url()` functions
|
|
25
|
+
* within a stylesheet. The rebasing will ensure that the URLs in the output of the Sass compiler
|
|
26
|
+
* reflect the final filesystem location of the output CSS file.
|
|
27
|
+
*
|
|
28
|
+
* This class provides the core of the rebasing functionality. To ensure that each file is processed
|
|
29
|
+
* by this importer's load implementation, the Sass compiler requires the importer's canonicalize
|
|
30
|
+
* function to return a non-null value with the resolved location of the requested stylesheet.
|
|
31
|
+
* Concrete implementations of this class must provide this canonicalize functionality for rebasing
|
|
32
|
+
* to be effective.
|
|
33
|
+
*/
|
|
34
|
+
class UrlRebasingImporter {
|
|
35
|
+
/**
|
|
36
|
+
* @param entryDirectory The directory of the entry stylesheet that was passed to the Sass compiler.
|
|
37
|
+
* @param rebaseSourceMaps When provided, rebased files will have an intermediate sourcemap added to the Map
|
|
38
|
+
* which can be used to generate a final sourcemap that contains original sources.
|
|
39
|
+
*/
|
|
40
|
+
constructor(entryDirectory, rebaseSourceMaps) {
|
|
41
|
+
this.entryDirectory = entryDirectory;
|
|
42
|
+
this.rebaseSourceMaps = rebaseSourceMaps;
|
|
43
|
+
}
|
|
44
|
+
load(canonicalUrl) {
|
|
45
|
+
const stylesheetPath = (0, node_url_1.fileURLToPath)(canonicalUrl);
|
|
46
|
+
let contents = (0, node_fs_1.readFileSync)(stylesheetPath, 'utf-8');
|
|
47
|
+
// Rebase any URLs that are found
|
|
48
|
+
if (contents.includes('url(')) {
|
|
49
|
+
const stylesheetDirectory = (0, node_path_1.dirname)(stylesheetPath);
|
|
50
|
+
let match;
|
|
51
|
+
URL_REGEXP.lastIndex = 0;
|
|
52
|
+
let updatedContents;
|
|
53
|
+
while ((match = URL_REGEXP.exec(contents))) {
|
|
54
|
+
const originalUrl = match[2];
|
|
55
|
+
// If root-relative, absolute or protocol relative url, leave as-is
|
|
56
|
+
if (/^((?:\w+:)?\/\/|data:|chrome:|#|\/)/.test(originalUrl)) {
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
const rebasedPath = (0, node_path_1.relative)(this.entryDirectory, (0, node_path_1.join)(stylesheetDirectory, originalUrl));
|
|
60
|
+
// Normalize path separators and escape characters
|
|
61
|
+
// https://developer.mozilla.org/en-US/docs/Web/CSS/url#syntax
|
|
62
|
+
const rebasedUrl = './' + rebasedPath.replace(/\\/g, '/').replace(/[()\s'"]/g, '\\$&');
|
|
63
|
+
updatedContents !== null && updatedContents !== void 0 ? updatedContents : (updatedContents = new magic_string_1.default(contents));
|
|
64
|
+
updatedContents.update(match.index, match.index + match[0].length, `url(${rebasedUrl})`);
|
|
65
|
+
}
|
|
66
|
+
if (updatedContents) {
|
|
67
|
+
contents = updatedContents.toString();
|
|
68
|
+
if (this.rebaseSourceMaps) {
|
|
69
|
+
// Generate an intermediate source map for the rebasing changes
|
|
70
|
+
const map = updatedContents.generateMap({
|
|
71
|
+
hires: true,
|
|
72
|
+
includeContent: true,
|
|
73
|
+
source: canonicalUrl.href,
|
|
74
|
+
});
|
|
75
|
+
this.rebaseSourceMaps.set(canonicalUrl.href, map);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
let syntax;
|
|
80
|
+
switch ((0, node_path_1.extname)(stylesheetPath).toLowerCase()) {
|
|
81
|
+
case 'css':
|
|
82
|
+
syntax = 'css';
|
|
83
|
+
break;
|
|
84
|
+
case 'sass':
|
|
85
|
+
syntax = 'indented';
|
|
86
|
+
break;
|
|
87
|
+
default:
|
|
88
|
+
syntax = 'scss';
|
|
89
|
+
break;
|
|
90
|
+
}
|
|
91
|
+
return {
|
|
92
|
+
contents,
|
|
93
|
+
syntax,
|
|
94
|
+
sourceMapUrl: canonicalUrl,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Provides the Sass importer logic to resolve relative stylesheet imports via both import and use rules
|
|
100
|
+
* and also rebase any `url()` function usage within those stylesheets. The rebasing will ensure that
|
|
101
|
+
* the URLs in the output of the Sass compiler reflect the final filesystem location of the output CSS file.
|
|
102
|
+
*/
|
|
103
|
+
class RelativeUrlRebasingImporter extends UrlRebasingImporter {
|
|
104
|
+
constructor(entryDirectory, directoryCache = new Map(), rebaseSourceMaps) {
|
|
105
|
+
super(entryDirectory, rebaseSourceMaps);
|
|
106
|
+
this.directoryCache = directoryCache;
|
|
107
|
+
}
|
|
108
|
+
canonicalize(url, options) {
|
|
109
|
+
return this.resolveImport(url, options.fromImport, true);
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Attempts to resolve a provided URL to a stylesheet file using the Sass compiler's resolution algorithm.
|
|
113
|
+
* Based on https://github.com/sass/dart-sass/blob/44d6bb6ac72fe6b93f5bfec371a1fffb18e6b76d/lib/src/importer/utils.dart
|
|
114
|
+
* @param url The file protocol URL to resolve.
|
|
115
|
+
* @param fromImport If true, URL was from an import rule; otherwise from a use rule.
|
|
116
|
+
* @param checkDirectory If true, try checking for a directory with the base name containing an index file.
|
|
117
|
+
* @returns A full resolved URL of the stylesheet file or `null` if not found.
|
|
118
|
+
*/
|
|
119
|
+
resolveImport(url, fromImport, checkDirectory) {
|
|
120
|
+
var _a;
|
|
121
|
+
let stylesheetPath;
|
|
122
|
+
try {
|
|
123
|
+
stylesheetPath = (0, node_url_1.fileURLToPath)(url);
|
|
124
|
+
}
|
|
125
|
+
catch {
|
|
126
|
+
// Only file protocol URLs are supported by this importer
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
const directory = (0, node_path_1.dirname)(stylesheetPath);
|
|
130
|
+
const extension = (0, node_path_1.extname)(stylesheetPath);
|
|
131
|
+
const hasStyleExtension = extension === '.scss' || extension === '.sass' || extension === '.css';
|
|
132
|
+
// Remove the style extension if present to allow adding the `.import` suffix
|
|
133
|
+
const filename = (0, node_path_1.basename)(stylesheetPath, hasStyleExtension ? extension : undefined);
|
|
134
|
+
let entries;
|
|
135
|
+
try {
|
|
136
|
+
entries = this.directoryCache.get(directory);
|
|
137
|
+
if (!entries) {
|
|
138
|
+
entries = (0, node_fs_1.readdirSync)(directory, { withFileTypes: true });
|
|
139
|
+
this.directoryCache.set(directory, entries);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
const importPotentials = new Set();
|
|
146
|
+
const defaultPotentials = new Set();
|
|
147
|
+
if (hasStyleExtension) {
|
|
148
|
+
if (fromImport) {
|
|
149
|
+
importPotentials.add(filename + '.import' + extension);
|
|
150
|
+
importPotentials.add('_' + filename + '.import' + extension);
|
|
151
|
+
}
|
|
152
|
+
defaultPotentials.add(filename + extension);
|
|
153
|
+
defaultPotentials.add('_' + filename + extension);
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
if (fromImport) {
|
|
157
|
+
importPotentials.add(filename + '.import.scss');
|
|
158
|
+
importPotentials.add(filename + '.import.sass');
|
|
159
|
+
importPotentials.add(filename + '.import.css');
|
|
160
|
+
importPotentials.add('_' + filename + '.import.scss');
|
|
161
|
+
importPotentials.add('_' + filename + '.import.sass');
|
|
162
|
+
importPotentials.add('_' + filename + '.import.css');
|
|
163
|
+
}
|
|
164
|
+
defaultPotentials.add(filename + '.scss');
|
|
165
|
+
defaultPotentials.add(filename + '.sass');
|
|
166
|
+
defaultPotentials.add(filename + '.css');
|
|
167
|
+
defaultPotentials.add('_' + filename + '.scss');
|
|
168
|
+
defaultPotentials.add('_' + filename + '.sass');
|
|
169
|
+
defaultPotentials.add('_' + filename + '.css');
|
|
170
|
+
}
|
|
171
|
+
const foundDefaults = [];
|
|
172
|
+
const foundImports = [];
|
|
173
|
+
let hasPotentialIndex = false;
|
|
174
|
+
for (const entry of entries) {
|
|
175
|
+
// Record if the name should be checked as a directory with an index file
|
|
176
|
+
if (checkDirectory && !hasStyleExtension && entry.name === filename && entry.isDirectory()) {
|
|
177
|
+
hasPotentialIndex = true;
|
|
178
|
+
}
|
|
179
|
+
if (!entry.isFile()) {
|
|
180
|
+
continue;
|
|
181
|
+
}
|
|
182
|
+
if (importPotentials.has(entry.name)) {
|
|
183
|
+
foundImports.push((0, node_path_1.join)(directory, entry.name));
|
|
184
|
+
}
|
|
185
|
+
if (defaultPotentials.has(entry.name)) {
|
|
186
|
+
foundDefaults.push((0, node_path_1.join)(directory, entry.name));
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
// `foundImports` will only contain elements if `options.fromImport` is true
|
|
190
|
+
const result = (_a = this.checkFound(foundImports)) !== null && _a !== void 0 ? _a : this.checkFound(foundDefaults);
|
|
191
|
+
if (result === null && hasPotentialIndex) {
|
|
192
|
+
// Check for index files using filename as a directory
|
|
193
|
+
return this.resolveImport(url + '/index', fromImport, false);
|
|
194
|
+
}
|
|
195
|
+
return result;
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Checks an array of potential stylesheet files to determine if there is a valid
|
|
199
|
+
* stylesheet file. More than one discovered file may indicate an error.
|
|
200
|
+
* @param found An array of discovered stylesheet files.
|
|
201
|
+
* @returns A fully resolved URL for a stylesheet file or `null` if not found.
|
|
202
|
+
* @throws If there are ambiguous files discovered.
|
|
203
|
+
*/
|
|
204
|
+
checkFound(found) {
|
|
205
|
+
if (found.length === 0) {
|
|
206
|
+
// Not found
|
|
207
|
+
return null;
|
|
208
|
+
}
|
|
209
|
+
// More than one found file may be an error
|
|
210
|
+
if (found.length > 1) {
|
|
211
|
+
// Presence of CSS files alongside a Sass file does not cause an error
|
|
212
|
+
const foundWithoutCss = found.filter((element) => (0, node_path_1.extname)(element) !== '.css');
|
|
213
|
+
// If the length is zero then there are two or more css files
|
|
214
|
+
// If the length is more than one than there are two or more sass/scss files
|
|
215
|
+
if (foundWithoutCss.length !== 1) {
|
|
216
|
+
throw new Error('Ambiguous import detected.');
|
|
217
|
+
}
|
|
218
|
+
// Return the non-CSS file (sass/scss files have priority)
|
|
219
|
+
// https://github.com/sass/dart-sass/blob/44d6bb6ac72fe6b93f5bfec371a1fffb18e6b76d/lib/src/importer/utils.dart#L44-L47
|
|
220
|
+
return (0, node_url_1.pathToFileURL)(foundWithoutCss[0]);
|
|
221
|
+
}
|
|
222
|
+
return (0, node_url_1.pathToFileURL)(found[0]);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
exports.RelativeUrlRebasingImporter = RelativeUrlRebasingImporter;
|
|
226
|
+
/**
|
|
227
|
+
* Provides the Sass importer logic to resolve module (npm package) stylesheet imports via both import and
|
|
228
|
+
* use rules and also rebase any `url()` function usage within those stylesheets. The rebasing will ensure that
|
|
229
|
+
* the URLs in the output of the Sass compiler reflect the final filesystem location of the output CSS file.
|
|
230
|
+
*/
|
|
231
|
+
class ModuleUrlRebasingImporter extends RelativeUrlRebasingImporter {
|
|
232
|
+
constructor(entryDirectory, directoryCache, rebaseSourceMaps, finder) {
|
|
233
|
+
super(entryDirectory, directoryCache, rebaseSourceMaps);
|
|
234
|
+
this.finder = finder;
|
|
235
|
+
}
|
|
236
|
+
canonicalize(url, options) {
|
|
237
|
+
if (url.startsWith('file://')) {
|
|
238
|
+
return super.canonicalize(url, options);
|
|
239
|
+
}
|
|
240
|
+
const result = this.finder(url, options);
|
|
241
|
+
return result ? super.canonicalize(result.href, options) : null;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
exports.ModuleUrlRebasingImporter = ModuleUrlRebasingImporter;
|
|
245
|
+
/**
|
|
246
|
+
* Provides the Sass importer logic to resolve load paths located stylesheet imports via both import and
|
|
247
|
+
* use rules and also rebase any `url()` function usage within those stylesheets. The rebasing will ensure that
|
|
248
|
+
* the URLs in the output of the Sass compiler reflect the final filesystem location of the output CSS file.
|
|
249
|
+
*/
|
|
250
|
+
class LoadPathsUrlRebasingImporter extends RelativeUrlRebasingImporter {
|
|
251
|
+
constructor(entryDirectory, directoryCache, rebaseSourceMaps, loadPaths) {
|
|
252
|
+
super(entryDirectory, directoryCache, rebaseSourceMaps);
|
|
253
|
+
this.loadPaths = loadPaths;
|
|
254
|
+
}
|
|
255
|
+
canonicalize(url, options) {
|
|
256
|
+
if (url.startsWith('file://')) {
|
|
257
|
+
return super.canonicalize(url, options);
|
|
258
|
+
}
|
|
259
|
+
let result = null;
|
|
260
|
+
for (const loadPath of this.loadPaths) {
|
|
261
|
+
result = super.canonicalize((0, node_url_1.pathToFileURL)((0, node_path_1.join)(loadPath, url)).href, options);
|
|
262
|
+
if (result !== null) {
|
|
263
|
+
break;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
return result;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
exports.LoadPathsUrlRebasingImporter = LoadPathsUrlRebasingImporter;
|
|
270
|
+
/**
|
|
271
|
+
* Workaround for Sass not calling instance methods with `this`.
|
|
272
|
+
* The `canonicalize` and `load` methods will be bound to the class instance.
|
|
273
|
+
* @param importer A Sass importer to bind.
|
|
274
|
+
* @returns The bound Sass importer.
|
|
275
|
+
*/
|
|
276
|
+
function sassBindWorkaround(importer) {
|
|
277
|
+
importer.canonicalize = importer.canonicalize.bind(importer);
|
|
278
|
+
importer.load = importer.load.bind(importer);
|
|
279
|
+
return importer;
|
|
280
|
+
}
|
|
281
|
+
exports.sassBindWorkaround = sassBindWorkaround;
|
|
@@ -23,12 +23,14 @@ export interface FileImporterWithRequestContextOptions extends FileImporterOptio
|
|
|
23
23
|
* the worker which can be up to two times faster than the asynchronous variant.
|
|
24
24
|
*/
|
|
25
25
|
export declare class SassWorkerImplementation {
|
|
26
|
+
private rebase;
|
|
26
27
|
private readonly workers;
|
|
27
28
|
private readonly availableWorkers;
|
|
28
29
|
private readonly requests;
|
|
29
30
|
private readonly workerPath;
|
|
30
31
|
private idCounter;
|
|
31
32
|
private nextWorkerIndex;
|
|
33
|
+
constructor(rebase?: boolean);
|
|
32
34
|
/**
|
|
33
35
|
* Provides information about the Sass implementation.
|
|
34
36
|
* This mimics enough of the `dart-sass` value to be used with the `sass-loader`.
|
package/src/sass/sass-service.js
CHANGED
|
@@ -23,7 +23,8 @@ const MAX_RENDER_WORKERS = environment_options_1.maxWorkers;
|
|
|
23
23
|
* the worker which can be up to two times faster than the asynchronous variant.
|
|
24
24
|
*/
|
|
25
25
|
class SassWorkerImplementation {
|
|
26
|
-
constructor() {
|
|
26
|
+
constructor(rebase = false) {
|
|
27
|
+
this.rebase = rebase;
|
|
27
28
|
this.workers = [];
|
|
28
29
|
this.availableWorkers = [];
|
|
29
30
|
this.requests = new Map();
|
|
@@ -73,8 +74,9 @@ class SassWorkerImplementation {
|
|
|
73
74
|
}
|
|
74
75
|
}
|
|
75
76
|
const callback = (error, result) => {
|
|
77
|
+
var _a;
|
|
76
78
|
if (error) {
|
|
77
|
-
const url = error === null ||
|
|
79
|
+
const url = (_a = error.span) === null || _a === void 0 ? void 0 : _a.url;
|
|
78
80
|
if (url) {
|
|
79
81
|
error.span.url = (0, node_url_1.pathToFileURL)(url);
|
|
80
82
|
}
|
|
@@ -94,6 +96,7 @@ class SassWorkerImplementation {
|
|
|
94
96
|
source,
|
|
95
97
|
hasImporter: !!(importers === null || importers === void 0 ? void 0 : importers.length),
|
|
96
98
|
hasLogger: !!logger,
|
|
99
|
+
rebase: this.rebase,
|
|
97
100
|
options: {
|
|
98
101
|
...serializableOptions,
|
|
99
102
|
// URL is not serializable so to convert to string here and back to URL in the worker.
|
package/src/sass/worker.js
CHANGED
|
@@ -6,46 +6,70 @@
|
|
|
6
6
|
* Use of this source code is governed by an MIT-style license that can be
|
|
7
7
|
* found in the LICENSE file at https://angular.io/license
|
|
8
8
|
*/
|
|
9
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
10
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
11
|
+
};
|
|
9
12
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
const remapping_1 = __importDefault(require("@ampproject/remapping"));
|
|
14
|
+
const node_path_1 = require("node:path");
|
|
15
|
+
const node_url_1 = require("node:url");
|
|
16
|
+
const node_worker_threads_1 = require("node:worker_threads");
|
|
10
17
|
const sass_1 = require("sass");
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
if (!worker_threads_1.parentPort || !worker_threads_1.workerData) {
|
|
18
|
+
const rebasing_importer_1 = require("./rebasing-importer");
|
|
19
|
+
if (!node_worker_threads_1.parentPort || !node_worker_threads_1.workerData) {
|
|
14
20
|
throw new Error('Sass worker must be executed as a Worker.');
|
|
15
21
|
}
|
|
16
22
|
// The importer variables are used to proxy import requests to the main thread
|
|
17
|
-
const { workerImporterPort, importerSignal } =
|
|
18
|
-
|
|
19
|
-
|
|
23
|
+
const { workerImporterPort, importerSignal } = node_worker_threads_1.workerData;
|
|
24
|
+
node_worker_threads_1.parentPort.on('message', (message) => {
|
|
25
|
+
var _a, _b;
|
|
26
|
+
if (!node_worker_threads_1.parentPort) {
|
|
20
27
|
throw new Error('"parentPort" is not defined. Sass worker must be executed as a Worker.');
|
|
21
28
|
}
|
|
22
|
-
const { id, hasImporter, hasLogger, source, options } = message;
|
|
29
|
+
const { id, hasImporter, hasLogger, source, options, rebase } = message;
|
|
30
|
+
const entryDirectory = (0, node_path_1.dirname)(options.url);
|
|
23
31
|
let warnings;
|
|
24
32
|
try {
|
|
33
|
+
const directoryCache = new Map();
|
|
34
|
+
const rebaseSourceMaps = options.sourceMap ? new Map() : undefined;
|
|
25
35
|
if (hasImporter) {
|
|
26
36
|
// When a custom importer function is present, the importer request must be proxied
|
|
27
37
|
// back to the main thread where it can be executed.
|
|
28
38
|
// This process must be synchronous from the perspective of dart-sass. The `Atomics`
|
|
29
39
|
// functions combined with the shared memory `importSignal` and the Node.js
|
|
30
40
|
// `receiveMessageOnPort` function are used to ensure synchronous behavior.
|
|
31
|
-
|
|
32
|
-
{
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
return result ? (0, url_1.pathToFileURL)(result) : null;
|
|
40
|
-
},
|
|
41
|
+
const proxyImporter = {
|
|
42
|
+
findFileUrl: (url, options) => {
|
|
43
|
+
var _a;
|
|
44
|
+
Atomics.store(importerSignal, 0, 0);
|
|
45
|
+
workerImporterPort.postMessage({ id, url, options });
|
|
46
|
+
Atomics.wait(importerSignal, 0, 0);
|
|
47
|
+
const result = (_a = (0, node_worker_threads_1.receiveMessageOnPort)(workerImporterPort)) === null || _a === void 0 ? void 0 : _a.message;
|
|
48
|
+
return result ? (0, node_url_1.pathToFileURL)(result) : null;
|
|
41
49
|
},
|
|
50
|
+
};
|
|
51
|
+
options.importers = [
|
|
52
|
+
rebase
|
|
53
|
+
? (0, rebasing_importer_1.sassBindWorkaround)(new rebasing_importer_1.ModuleUrlRebasingImporter(entryDirectory, directoryCache, rebaseSourceMaps, proxyImporter.findFileUrl))
|
|
54
|
+
: proxyImporter,
|
|
42
55
|
];
|
|
43
56
|
}
|
|
57
|
+
if (rebase && ((_a = options.loadPaths) === null || _a === void 0 ? void 0 : _a.length)) {
|
|
58
|
+
(_b = options.importers) !== null && _b !== void 0 ? _b : (options.importers = []);
|
|
59
|
+
options.importers.push((0, rebasing_importer_1.sassBindWorkaround)(new rebasing_importer_1.LoadPathsUrlRebasingImporter(entryDirectory, directoryCache, rebaseSourceMaps, options.loadPaths)));
|
|
60
|
+
options.loadPaths = undefined;
|
|
61
|
+
}
|
|
62
|
+
let relativeImporter;
|
|
63
|
+
if (rebase) {
|
|
64
|
+
relativeImporter = (0, rebasing_importer_1.sassBindWorkaround)(new rebasing_importer_1.RelativeUrlRebasingImporter(entryDirectory, directoryCache, rebaseSourceMaps));
|
|
65
|
+
}
|
|
44
66
|
// The synchronous Sass render function can be up to two times faster than the async variant
|
|
45
67
|
const result = (0, sass_1.compileString)(source, {
|
|
46
68
|
...options,
|
|
47
69
|
// URL is not serializable so to convert to string in the parent and back to URL here.
|
|
48
|
-
url:
|
|
70
|
+
url: (0, node_url_1.pathToFileURL)(options.url),
|
|
71
|
+
// The `importer` option (singular) handles relative imports
|
|
72
|
+
importer: relativeImporter,
|
|
49
73
|
logger: hasLogger
|
|
50
74
|
? {
|
|
51
75
|
warn(message, { deprecation, span, stack }) {
|
|
@@ -60,13 +84,21 @@ worker_threads_1.parentPort.on('message', (message) => {
|
|
|
60
84
|
}
|
|
61
85
|
: undefined,
|
|
62
86
|
});
|
|
63
|
-
|
|
87
|
+
if (result.sourceMap && (rebaseSourceMaps === null || rebaseSourceMaps === void 0 ? void 0 : rebaseSourceMaps.size)) {
|
|
88
|
+
// Merge the intermediate rebasing source maps into the final Sass generated source map.
|
|
89
|
+
// Casting is required due to small but compatible differences in typings between the packages.
|
|
90
|
+
result.sourceMap = (0, remapping_1.default)(result.sourceMap,
|
|
91
|
+
// To prevent an infinite lookup loop, skip getting the source when the rebasing source map
|
|
92
|
+
// is referencing its original self.
|
|
93
|
+
(file, context) => (file !== context.importer ? rebaseSourceMaps.get(file) : null));
|
|
94
|
+
}
|
|
95
|
+
node_worker_threads_1.parentPort.postMessage({
|
|
64
96
|
id,
|
|
65
97
|
warnings,
|
|
66
98
|
result: {
|
|
67
99
|
...result,
|
|
68
100
|
// URL is not serializable so to convert to string here and back to URL in the parent.
|
|
69
|
-
loadedUrls: result.loadedUrls.map((p) => (0,
|
|
101
|
+
loadedUrls: result.loadedUrls.map((p) => (0, node_url_1.fileURLToPath)(p)),
|
|
70
102
|
},
|
|
71
103
|
});
|
|
72
104
|
}
|
|
@@ -74,7 +106,7 @@ worker_threads_1.parentPort.on('message', (message) => {
|
|
|
74
106
|
// Needed because V8 will only serialize the message and stack properties of an Error instance.
|
|
75
107
|
if (error instanceof sass_1.Exception) {
|
|
76
108
|
const { span, message, stack, sassMessage, sassStack } = error;
|
|
77
|
-
|
|
109
|
+
node_worker_threads_1.parentPort.postMessage({
|
|
78
110
|
id,
|
|
79
111
|
warnings,
|
|
80
112
|
error: {
|
|
@@ -88,10 +120,10 @@ worker_threads_1.parentPort.on('message', (message) => {
|
|
|
88
120
|
}
|
|
89
121
|
else if (error instanceof Error) {
|
|
90
122
|
const { message, stack } = error;
|
|
91
|
-
|
|
123
|
+
node_worker_threads_1.parentPort.postMessage({ id, warnings, error: { message, stack } });
|
|
92
124
|
}
|
|
93
125
|
else {
|
|
94
|
-
|
|
126
|
+
node_worker_threads_1.parentPort.postMessage({
|
|
95
127
|
id,
|
|
96
128
|
warnings,
|
|
97
129
|
error: { message: 'An unknown error has occurred.' },
|
|
@@ -122,6 +154,6 @@ function convertSourceSpan(span) {
|
|
|
122
154
|
offset: span.start.offset,
|
|
123
155
|
line: span.start.line,
|
|
124
156
|
},
|
|
125
|
-
url: span.url ? (0,
|
|
157
|
+
url: span.url ? (0, node_url_1.fileURLToPath)(span.url) : undefined,
|
|
126
158
|
};
|
|
127
159
|
}
|
|
@@ -86,7 +86,7 @@ async function getCommonConfig(wco) {
|
|
|
86
86
|
if (isPlatformServer) {
|
|
87
87
|
// Fixes Critical dependency: the request of a dependency is an expression
|
|
88
88
|
extraPlugins.push(new webpack_2.ContextReplacementPlugin(/@?hapi|express[\\/]/));
|
|
89
|
-
if (Array.isArray(entryPoints['main'])) {
|
|
89
|
+
if ((0, helpers_1.isPlatformServerInstalled)(wco.root) && Array.isArray(entryPoints['main'])) {
|
|
90
90
|
// This import must come before any imports (direct or transitive) that rely on DOM built-ins being
|
|
91
91
|
// available, such as `@angular/elements`.
|
|
92
92
|
entryPoints['main'].unshift('@angular/platform-server/init');
|
|
@@ -48,7 +48,7 @@ const helpers_1 = require("../utils/helpers");
|
|
|
48
48
|
// eslint-disable-next-line max-lines-per-function
|
|
49
49
|
function getStylesConfig(wco) {
|
|
50
50
|
var _a, _b, _c;
|
|
51
|
-
const { root, buildOptions } = wco;
|
|
51
|
+
const { root, buildOptions, logger } = wco;
|
|
52
52
|
const extraPlugins = [];
|
|
53
53
|
extraPlugins.push(new plugins_1.AnyComponentStyleBudgetChecker(buildOptions.budgets));
|
|
54
54
|
const cssSourceMap = buildOptions.sourceMap.styles;
|
|
@@ -93,7 +93,7 @@ function getStylesConfig(wco) {
|
|
|
93
93
|
}
|
|
94
94
|
catch {
|
|
95
95
|
const relativeTailwindConfigPath = path.relative(wco.root, tailwindConfigPath);
|
|
96
|
-
|
|
96
|
+
logger.warn(`Tailwind CSS configuration file found (${relativeTailwindConfigPath})` +
|
|
97
97
|
` but the 'tailwindcss' package is not installed.` +
|
|
98
98
|
` To enable Tailwind CSS, please install the 'tailwindcss' package.`);
|
|
99
99
|
}
|
|
@@ -131,14 +131,21 @@ function getStylesConfig(wco) {
|
|
|
131
131
|
optionGenerator.config = false;
|
|
132
132
|
return optionGenerator;
|
|
133
133
|
};
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
134
|
+
let componentsSourceMap = !!cssSourceMap;
|
|
135
|
+
if (cssSourceMap) {
|
|
136
|
+
if (buildOptions.optimization.styles.minify) {
|
|
137
|
+
// Never use component css sourcemap when style optimizations are on.
|
|
138
|
+
// It will just increase bundle size without offering good debug experience.
|
|
139
|
+
logger.warn('Components styles sourcemaps are not generated when styles optimization is enabled.');
|
|
140
|
+
componentsSourceMap = false;
|
|
141
|
+
}
|
|
142
|
+
else if (buildOptions.sourceMap.hidden) {
|
|
143
|
+
// Inline all sourcemap types except hidden ones, which are the same as no sourcemaps
|
|
144
|
+
// for component css.
|
|
145
|
+
logger.warn('Components styles sourcemaps are not generated when sourcemaps are hidden.');
|
|
146
|
+
componentsSourceMap = false;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
142
149
|
// extract global css from js files into own css file.
|
|
143
150
|
extraPlugins.push(new mini_css_extract_plugin_1.default({ filename: `[name]${hashFormat.extract}.css` }));
|
|
144
151
|
if (!buildOptions.hmr) {
|
|
@@ -33,3 +33,8 @@ export declare function globalScriptsByBundleName(scripts: ScriptElement[]): {
|
|
|
33
33
|
}[];
|
|
34
34
|
export declare function assetPatterns(root: string, assets: AssetPatternClass[]): ObjectPattern[];
|
|
35
35
|
export declare function getStatsOptions(verbose?: boolean): WebpackStatsOptions;
|
|
36
|
+
/**
|
|
37
|
+
* @param root the workspace root
|
|
38
|
+
* @returns `true` when `@angular/platform-server` is installed.
|
|
39
|
+
*/
|
|
40
|
+
export declare function isPlatformServerInstalled(root: string): boolean;
|
|
@@ -33,7 +33,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
33
33
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
34
34
|
};
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.getStatsOptions = exports.assetPatterns = exports.globalScriptsByBundleName = exports.getCacheSettings = exports.normalizeGlobalStyles = exports.getInstrumentationExcludedPaths = exports.assetNameTemplateFactory = exports.normalizeExtraEntryPoints = exports.getOutputHashFormat = void 0;
|
|
36
|
+
exports.isPlatformServerInstalled = exports.getStatsOptions = exports.assetPatterns = exports.globalScriptsByBundleName = exports.getCacheSettings = exports.normalizeGlobalStyles = exports.getInstrumentationExcludedPaths = exports.assetNameTemplateFactory = exports.normalizeExtraEntryPoints = exports.getOutputHashFormat = void 0;
|
|
37
37
|
const crypto_1 = require("crypto");
|
|
38
38
|
const glob_1 = __importDefault(require("glob"));
|
|
39
39
|
const path = __importStar(require("path"));
|
|
@@ -278,3 +278,17 @@ function getStatsOptions(verbose = false) {
|
|
|
278
278
|
: webpackOutputOptions;
|
|
279
279
|
}
|
|
280
280
|
exports.getStatsOptions = getStatsOptions;
|
|
281
|
+
/**
|
|
282
|
+
* @param root the workspace root
|
|
283
|
+
* @returns `true` when `@angular/platform-server` is installed.
|
|
284
|
+
*/
|
|
285
|
+
function isPlatformServerInstalled(root) {
|
|
286
|
+
try {
|
|
287
|
+
require.resolve('@angular/platform-server', { paths: [root] });
|
|
288
|
+
return true;
|
|
289
|
+
}
|
|
290
|
+
catch {
|
|
291
|
+
return false;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
exports.isPlatformServerInstalled = isPlatformServerInstalled;
|