@angular-devkit/build-angular 12.0.1 → 12.0.5
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 +10 -10
- package/src/browser/index.js +1 -3
- package/src/browser/schema.d.ts +1 -1
- package/src/browser/schema.json +1 -1
- package/src/dev-server/index.js +38 -37
- package/src/extract-i18n/index.js +6 -4
- package/src/karma/index.js +1 -0
- package/src/karma/schema.d.ts +1 -1
- package/src/karma/schema.json +1 -1
- package/src/karma/tests/setup.d.ts +18 -0
- package/src/karma/tests/setup.js +29 -0
- package/src/sass/sass-service.d.ts +0 -3
- package/src/sass/sass-service.js +17 -7
- package/src/sass/worker.js +13 -4
- package/src/server/schema.d.ts +1 -1
- package/src/server/schema.json +1 -1
- package/src/utils/service-worker.js +1 -1
- package/src/utils/spinner.d.ts +2 -0
- package/src/utils/spinner.js +14 -0
- package/src/webpack/configs/common.js +26 -52
- package/src/webpack/configs/server.js +8 -0
- package/src/webpack/configs/stats.d.ts +6 -14
- package/src/webpack/configs/stats.js +5 -8
- package/src/webpack/configs/styles.js +49 -5
- package/src/webpack/configs/test.js +11 -1
- package/src/webpack/plugins/index-html-webpack-plugin.js +1 -1
- package/src/webpack/plugins/karma/karma-context.html +1 -1
- package/src/webpack/plugins/karma/karma-debug.html +1 -1
- package/src/webpack/plugins/karma/karma.js +1 -1
- package/src/webpack/plugins/postcss-cli-resources.js +1 -1
- package/src/webpack/utils/async-chunks.js +9 -5
- package/src/webpack/utils/stats.d.ts +2 -2
- package/src/webpack/utils/stats.js +15 -3
package/package.json
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@angular-devkit/build-angular",
|
|
3
|
-
"version": "12.0.
|
|
3
|
+
"version": "12.0.5",
|
|
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
|
-
"@angular-devkit/architect": "0.1200.
|
|
10
|
-
"@angular-devkit/build-optimizer": "0.1200.
|
|
11
|
-
"@angular-devkit/build-webpack": "0.1200.
|
|
12
|
-
"@angular-devkit/core": "12.0.
|
|
9
|
+
"@angular-devkit/architect": "0.1200.5",
|
|
10
|
+
"@angular-devkit/build-optimizer": "0.1200.5",
|
|
11
|
+
"@angular-devkit/build-webpack": "0.1200.5",
|
|
12
|
+
"@angular-devkit/core": "12.0.5",
|
|
13
13
|
"@babel/core": "7.14.3",
|
|
14
14
|
"@babel/generator": "7.14.3",
|
|
15
15
|
"@babel/plugin-transform-async-to-generator": "7.13.0",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"@babel/template": "7.12.13",
|
|
20
20
|
"@discoveryjs/json-ext": "0.5.2",
|
|
21
21
|
"@jsdevtools/coverage-istanbul-loader": "3.0.5",
|
|
22
|
-
"@ngtools/webpack": "12.0.
|
|
22
|
+
"@ngtools/webpack": "12.0.5",
|
|
23
23
|
"ansi-colors": "4.1.1",
|
|
24
24
|
"babel-loader": "8.2.2",
|
|
25
25
|
"browserslist": "^4.9.1",
|
|
@@ -39,14 +39,14 @@
|
|
|
39
39
|
"karma-source-map-support": "1.4.0",
|
|
40
40
|
"less": "4.1.1",
|
|
41
41
|
"less-loader": "8.1.1",
|
|
42
|
-
"license-webpack-plugin": "2.3.
|
|
42
|
+
"license-webpack-plugin": "2.3.19",
|
|
43
43
|
"loader-utils": "2.0.0",
|
|
44
44
|
"mini-css-extract-plugin": "1.5.1",
|
|
45
45
|
"minimatch": "3.0.4",
|
|
46
46
|
"open": "8.0.2",
|
|
47
47
|
"ora": "5.4.0",
|
|
48
48
|
"parse5-html-rewriting-stream": "6.0.1",
|
|
49
|
-
"postcss": "8.
|
|
49
|
+
"postcss": "8.3.0",
|
|
50
50
|
"postcss-import": "14.0.1",
|
|
51
51
|
"postcss-loader": "5.2.0",
|
|
52
52
|
"postcss-preset-env": "6.7.0",
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
"terser-webpack-plugin": "5.1.2",
|
|
69
69
|
"text-table": "0.2.0",
|
|
70
70
|
"tree-kill": "1.2.2",
|
|
71
|
-
"webpack": "5.
|
|
71
|
+
"webpack": "5.39.1",
|
|
72
72
|
"webpack-dev-middleware": "4.1.0",
|
|
73
73
|
"webpack-dev-server": "3.11.2",
|
|
74
74
|
"webpack-merge": "5.7.3",
|
|
@@ -120,7 +120,7 @@
|
|
|
120
120
|
"url": "https://github.com/angular/angular-cli.git"
|
|
121
121
|
},
|
|
122
122
|
"engines": {
|
|
123
|
-
"node": "^12.14.1 ||
|
|
123
|
+
"node": "^12.14.1 || >=14.0.0",
|
|
124
124
|
"npm": "^6.11.0 || ^7.5.6",
|
|
125
125
|
"yarn": ">= 1.13.0"
|
|
126
126
|
},
|
package/src/browser/index.js
CHANGED
|
@@ -69,7 +69,7 @@ async function initialize(options, context, differentialLoadingNeeded, webpackCo
|
|
|
69
69
|
const originalOutputPath = options.outputPath;
|
|
70
70
|
// Assets are processed directly by the builder except when watching
|
|
71
71
|
const adjustedOptions = options.watch ? options : { ...options, assets: [] };
|
|
72
|
-
const { config, projectRoot, projectSourceRoot, i18n
|
|
72
|
+
const { config, projectRoot, projectSourceRoot, i18n } = await webpack_browser_config_1.generateI18nBrowserWebpackConfigFromContext(adjustedOptions, context, (wco) => [
|
|
73
73
|
configs_1.getCommonConfig(wco),
|
|
74
74
|
configs_1.getBrowserConfig(wco),
|
|
75
75
|
configs_1.getStylesConfig(wco),
|
|
@@ -544,12 +544,10 @@ function assertNever(input) {
|
|
|
544
544
|
throw new Error(`Unexpected call to assertNever() with input: ${JSON.stringify(input, null /* replacer */, 4 /* tabSize */)}`);
|
|
545
545
|
}
|
|
546
546
|
function generateBundleInfoStats(bundle, chunk, chunkType) {
|
|
547
|
-
var _a;
|
|
548
547
|
return stats_1.generateBundleStats({
|
|
549
548
|
size: bundle.size,
|
|
550
549
|
files: bundle.map ? [bundle.filename, bundle.map.filename] : [bundle.filename],
|
|
551
550
|
names: chunk === null || chunk === void 0 ? void 0 : chunk.names,
|
|
552
|
-
entry: !!((_a = chunk === null || chunk === void 0 ? void 0 : chunk.names) === null || _a === void 0 ? void 0 : _a.includes('runtime')),
|
|
553
551
|
initial: !!(chunk === null || chunk === void 0 ? void 0 : chunk.initial),
|
|
554
552
|
rendered: true,
|
|
555
553
|
chunkType,
|
package/src/browser/schema.d.ts
CHANGED
|
@@ -407,7 +407,7 @@ export interface SourceMapClass {
|
|
|
407
407
|
*/
|
|
408
408
|
export interface StylePreprocessorOptions {
|
|
409
409
|
/**
|
|
410
|
-
* Paths to include. Paths will be resolved to
|
|
410
|
+
* Paths to include. Paths will be resolved to workspace root.
|
|
411
411
|
*/
|
|
412
412
|
includePaths?: string[];
|
|
413
413
|
}
|
package/src/browser/schema.json
CHANGED
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"type": "object",
|
|
52
52
|
"properties": {
|
|
53
53
|
"includePaths": {
|
|
54
|
-
"description": "Paths to include. Paths will be resolved to
|
|
54
|
+
"description": "Paths to include. Paths will be resolved to workspace root.",
|
|
55
55
|
"type": "array",
|
|
56
56
|
"items": {
|
|
57
57
|
"type": "string"
|
package/src/dev-server/index.js
CHANGED
|
@@ -84,11 +84,47 @@ function serveWebpackBrowser(options, context, transforms = {}) {
|
|
|
84
84
|
overrides.outputHashing = schema_1.OutputHashing.None;
|
|
85
85
|
logger.warn(`Warning: 'outputHashing' option is disabled when using the dev-server.`);
|
|
86
86
|
}
|
|
87
|
+
if (options.hmr) {
|
|
88
|
+
logger.warn(core_1.tags.stripIndents `NOTICE: Hot Module Replacement (HMR) is enabled for the dev server.
|
|
89
|
+
See https://webpack.js.org/guides/hot-module-replacement for information on working with HMR for Webpack.`);
|
|
90
|
+
}
|
|
91
|
+
if (!options.disableHostCheck &&
|
|
92
|
+
options.host &&
|
|
93
|
+
!/^127\.\d+\.\d+\.\d+/g.test(options.host) &&
|
|
94
|
+
options.host !== 'localhost') {
|
|
95
|
+
logger.warn(core_1.tags.stripIndent `
|
|
96
|
+
Warning: This is a simple server for use in testing or debugging Angular applications
|
|
97
|
+
locally. It hasn't been reviewed for security issues.
|
|
98
|
+
|
|
99
|
+
Binding this server to an open connection can result in compromising your application or
|
|
100
|
+
computer. Using a different host than the one passed to the "--host" flag might result in
|
|
101
|
+
websocket connection issues. You might need to use "--disableHostCheck" if that's the
|
|
102
|
+
case.
|
|
103
|
+
`);
|
|
104
|
+
}
|
|
105
|
+
if (options.disableHostCheck) {
|
|
106
|
+
logger.warn(core_1.tags.oneLine `
|
|
107
|
+
Warning: Running a server with --disable-host-check is a security risk.
|
|
108
|
+
See https://medium.com/webpack/webpack-dev-server-middleware-security-issues-1489d950874a
|
|
109
|
+
for more information.
|
|
110
|
+
`);
|
|
111
|
+
}
|
|
87
112
|
// Webpack's live reload functionality adds the `strip-ansi` package which is commonJS
|
|
88
113
|
(_b = rawBrowserOptions.allowedCommonJsDependencies) !== null && _b !== void 0 ? _b : (rawBrowserOptions.allowedCommonJsDependencies = []);
|
|
89
114
|
rawBrowserOptions.allowedCommonJsDependencies.push('strip-ansi');
|
|
90
115
|
const browserName = await context.getBuilderNameForTarget(browserTarget);
|
|
91
116
|
const browserOptions = (await context.validateOptions({ ...rawBrowserOptions, ...overrides }, browserName));
|
|
117
|
+
const { styles, scripts } = utils_1.normalizeOptimization(browserOptions.optimization);
|
|
118
|
+
if (scripts || styles.minify) {
|
|
119
|
+
logger.error(core_1.tags.stripIndents `
|
|
120
|
+
****************************************************************************************
|
|
121
|
+
This is a simple server for use in testing or debugging Angular applications locally.
|
|
122
|
+
It hasn't been reviewed for security issues.
|
|
123
|
+
|
|
124
|
+
DON'T USE IT FOR PRODUCTION!
|
|
125
|
+
****************************************************************************************
|
|
126
|
+
`);
|
|
127
|
+
}
|
|
92
128
|
const { config, projectRoot, i18n } = await webpack_browser_config_1.generateI18nBrowserWebpackConfigFromContext(browserOptions, context, (wco) => [
|
|
93
129
|
configs_1.getDevServerConfig(wco),
|
|
94
130
|
configs_1.getCommonConfig(wco),
|
|
@@ -129,30 +165,6 @@ function serveWebpackBrowser(options, context, transforms = {}) {
|
|
|
129
165
|
}
|
|
130
166
|
}
|
|
131
167
|
}
|
|
132
|
-
if (options.hmr) {
|
|
133
|
-
logger.warn(core_1.tags.stripIndents `NOTICE: Hot Module Replacement (HMR) is enabled for the dev server.
|
|
134
|
-
See https://webpack.js.org/guides/hot-module-replacement for information on working with HMR for Webpack.`);
|
|
135
|
-
}
|
|
136
|
-
if (options.host &&
|
|
137
|
-
!/^127\.\d+\.\d+\.\d+/g.test(options.host) &&
|
|
138
|
-
options.host !== 'localhost') {
|
|
139
|
-
logger.warn(core_1.tags.stripIndent `
|
|
140
|
-
Warning: This is a simple server for use in testing or debugging Angular applications
|
|
141
|
-
locally. It hasn't been reviewed for security issues.
|
|
142
|
-
|
|
143
|
-
Binding this server to an open connection can result in compromising your application or
|
|
144
|
-
computer. Using a different host than the one passed to the "--host" flag might result in
|
|
145
|
-
websocket connection issues. You might need to use "--disableHostCheck" if that's the
|
|
146
|
-
case.
|
|
147
|
-
`);
|
|
148
|
-
}
|
|
149
|
-
if (options.disableHostCheck) {
|
|
150
|
-
logger.warn(core_1.tags.oneLine `
|
|
151
|
-
Warning: Running a server with --disable-host-check is a security risk.
|
|
152
|
-
See https://medium.com/webpack/webpack-dev-server-middleware-security-issues-1489d950874a
|
|
153
|
-
for more information.
|
|
154
|
-
`);
|
|
155
|
-
}
|
|
156
168
|
let locale;
|
|
157
169
|
if (i18n.shouldInline) {
|
|
158
170
|
// Dev-server only supports one locale
|
|
@@ -185,7 +197,6 @@ function serveWebpackBrowser(options, context, transforms = {}) {
|
|
|
185
197
|
};
|
|
186
198
|
}
|
|
187
199
|
return rxjs_1.from(setup()).pipe(operators_1.switchMap(({ browserOptions, webpackConfig, projectRoot, locale }) => {
|
|
188
|
-
const normalizedOptimization = utils_1.normalizeOptimization(browserOptions.optimization);
|
|
189
200
|
if (browserOptions.index) {
|
|
190
201
|
const { scripts = [], styles = [], baseHref, tsConfig } = browserOptions;
|
|
191
202
|
const { options: compilerOptions } = read_tsconfig_1.readTsconfig(tsConfig, workspaceRoot);
|
|
@@ -206,24 +217,14 @@ function serveWebpackBrowser(options, context, transforms = {}) {
|
|
|
206
217
|
deployUrl: browserOptions.deployUrl,
|
|
207
218
|
sri: browserOptions.subresourceIntegrity,
|
|
208
219
|
postTransform: transforms.indexHtml,
|
|
209
|
-
optimization:
|
|
220
|
+
optimization: utils_1.normalizeOptimization(browserOptions.optimization),
|
|
210
221
|
WOFFSupportNeeded: !buildBrowserFeatures.isFeatureSupported('woff2'),
|
|
211
222
|
crossOrigin: browserOptions.crossOrigin,
|
|
212
223
|
lang: locale,
|
|
213
224
|
}));
|
|
214
225
|
}
|
|
215
|
-
if (normalizedOptimization.scripts || normalizedOptimization.styles.minify) {
|
|
216
|
-
logger.error(core_1.tags.stripIndents `
|
|
217
|
-
****************************************************************************************
|
|
218
|
-
This is a simple server for use in testing or debugging Angular applications locally.
|
|
219
|
-
It hasn't been reviewed for security issues.
|
|
220
|
-
|
|
221
|
-
DON'T USE IT FOR PRODUCTION!
|
|
222
|
-
****************************************************************************************
|
|
223
|
-
`);
|
|
224
|
-
}
|
|
225
226
|
return build_webpack_1.runWebpackDevServer(webpackConfig, context, {
|
|
226
|
-
logging: transforms.logging || stats_1.createWebpackLoggingCallback(
|
|
227
|
+
logging: transforms.logging || stats_1.createWebpackLoggingCallback(browserOptions, logger),
|
|
227
228
|
webpackFactory: require('webpack'),
|
|
228
229
|
webpackDevServerFactory: require('webpack-dev-server'),
|
|
229
230
|
}).pipe(operators_1.concatMap(async (buildEvent, index) => {
|
|
@@ -118,7 +118,7 @@ async function execute(options, context, transforms) {
|
|
|
118
118
|
const i18n = i18n_options_1.createI18nOptions(metadata);
|
|
119
119
|
let useLegacyIds = true;
|
|
120
120
|
const ivyMessages = [];
|
|
121
|
-
const
|
|
121
|
+
const builderOptions = {
|
|
122
122
|
...browserOptions,
|
|
123
123
|
optimization: false,
|
|
124
124
|
sourceMap: {
|
|
@@ -138,7 +138,8 @@ async function execute(options, context, transforms) {
|
|
|
138
138
|
subresourceIntegrity: false,
|
|
139
139
|
outputHashing: schema_1.OutputHashing.None,
|
|
140
140
|
namedChunks: true,
|
|
141
|
-
}
|
|
141
|
+
};
|
|
142
|
+
const { config, projectRoot } = await webpack_browser_config_1.generateBrowserWebpackConfigFromContext(builderOptions, context, (wco) => {
|
|
142
143
|
var _a;
|
|
143
144
|
if (wco.tsConfig.options.enableIvy === false) {
|
|
144
145
|
context.logger.warn('Ivy extraction enabled but application is not Ivy enabled. Extraction may fail.');
|
|
@@ -150,6 +151,7 @@ async function execute(options, context, transforms) {
|
|
|
150
151
|
configs_1.getCommonConfig(wco),
|
|
151
152
|
configs_1.getBrowserConfig(wco),
|
|
152
153
|
configs_1.getTypeScriptConfig(wco),
|
|
154
|
+
configs_1.getWorkerConfig(wco),
|
|
153
155
|
configs_1.getStatsConfig(wco),
|
|
154
156
|
];
|
|
155
157
|
// Add Ivy application file extractor support
|
|
@@ -170,7 +172,7 @@ async function execute(options, context, transforms) {
|
|
|
170
172
|
partials.push({
|
|
171
173
|
plugins: [
|
|
172
174
|
new webpack.NormalModuleReplacementPlugin(/\.(css|scss|sass|styl|less)$/, path.join(__dirname, 'empty-export-default.js')),
|
|
173
|
-
new webpack.NormalModuleReplacementPlugin(/^angular-resource
|
|
175
|
+
new webpack.NormalModuleReplacementPlugin(/^angular-resource:style,/, path.join(__dirname, 'empty-export-default.js')),
|
|
174
176
|
],
|
|
175
177
|
});
|
|
176
178
|
return partials;
|
|
@@ -186,7 +188,7 @@ async function execute(options, context, transforms) {
|
|
|
186
188
|
};
|
|
187
189
|
}
|
|
188
190
|
const webpackResult = await build_webpack_1.runWebpack((await ((_a = transforms === null || transforms === void 0 ? void 0 : transforms.webpackConfiguration) === null || _a === void 0 ? void 0 : _a.call(transforms, config))) || config, context, {
|
|
189
|
-
logging: stats_1.createWebpackLoggingCallback(
|
|
191
|
+
logging: stats_1.createWebpackLoggingCallback(builderOptions, context.logger),
|
|
190
192
|
webpackFactory: webpack,
|
|
191
193
|
}).toPromise();
|
|
192
194
|
// Set the outputPath to the extraction output location for downstream consumers
|
package/src/karma/index.js
CHANGED
|
@@ -40,6 +40,7 @@ async function initialize(options, context, webpackConfigurationTransformer) {
|
|
|
40
40
|
// https://github.com/webpack/webpack-dev-middleware/blob/698c9ae5e9bb9a013985add6189ff21c1a1ec185/src/index.js#L65
|
|
41
41
|
// https://github.com/webpack/webpack/blob/cde1b73e12eb8a77eb9ba42e7920c9ec5d29c2c9/lib/Compiler.js#L379-L388
|
|
42
42
|
watch: true,
|
|
43
|
+
extractCss: true,
|
|
43
44
|
}, context, (wco) => [
|
|
44
45
|
configs_1.getCommonConfig(wco),
|
|
45
46
|
configs_1.getStylesConfig(wco),
|
package/src/karma/schema.d.ts
CHANGED
|
@@ -167,7 +167,7 @@ export interface SourceMapClass {
|
|
|
167
167
|
*/
|
|
168
168
|
export interface StylePreprocessorOptions {
|
|
169
169
|
/**
|
|
170
|
-
* Paths to include. Paths will be resolved to
|
|
170
|
+
* Paths to include. Paths will be resolved to workspace root.
|
|
171
171
|
*/
|
|
172
172
|
includePaths?: string[];
|
|
173
173
|
}
|
package/src/karma/schema.json
CHANGED
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"type": "object",
|
|
56
56
|
"properties": {
|
|
57
57
|
"includePaths": {
|
|
58
|
-
"description": "Paths to include. Paths will be resolved to
|
|
58
|
+
"description": "Paths to include. Paths will be resolved to workspace root.",
|
|
59
59
|
"type": "array",
|
|
60
60
|
"items": {
|
|
61
61
|
"type": "string"
|
|
@@ -0,0 +1,18 @@
|
|
|
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
|
+
import { Schema } from '../schema';
|
|
9
|
+
export { describeBuilder } from '../../testing';
|
|
10
|
+
export declare const KARMA_BUILDER_INFO: Readonly<{
|
|
11
|
+
name: string;
|
|
12
|
+
schemaPath: string;
|
|
13
|
+
}>;
|
|
14
|
+
/**
|
|
15
|
+
* Contains all required karma builder fields.
|
|
16
|
+
* Also disables progress reporting to minimize logging output.
|
|
17
|
+
*/
|
|
18
|
+
export declare const BASE_OPTIONS: Readonly<Schema>;
|
|
@@ -0,0 +1,29 @@
|
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.BASE_OPTIONS = exports.KARMA_BUILDER_INFO = exports.describeBuilder = void 0;
|
|
11
|
+
var testing_1 = require("../../testing");
|
|
12
|
+
Object.defineProperty(exports, "describeBuilder", { enumerable: true, get: function () { return testing_1.describeBuilder; } });
|
|
13
|
+
exports.KARMA_BUILDER_INFO = Object.freeze({
|
|
14
|
+
name: '@angular-devkit/build-angular:karma',
|
|
15
|
+
schemaPath: __dirname + '/../schema.json',
|
|
16
|
+
});
|
|
17
|
+
/**
|
|
18
|
+
* Contains all required karma builder fields.
|
|
19
|
+
* Also disables progress reporting to minimize logging output.
|
|
20
|
+
*/
|
|
21
|
+
exports.BASE_OPTIONS = Object.freeze({
|
|
22
|
+
main: 'src/test.ts',
|
|
23
|
+
polyfills: 'src/polyfills.ts',
|
|
24
|
+
tsConfig: 'src/tsconfig.spec.json',
|
|
25
|
+
karmaConfig: 'karma.conf.js',
|
|
26
|
+
browsers: 'ChromeHeadlessCI',
|
|
27
|
+
progress: false,
|
|
28
|
+
watch: false,
|
|
29
|
+
});
|
|
@@ -41,9 +41,6 @@ export declare class SassWorkerImplementation {
|
|
|
41
41
|
/**
|
|
42
42
|
* Shutdown the Sass render worker.
|
|
43
43
|
* Executing this method will stop any pending render requests.
|
|
44
|
-
*
|
|
45
|
-
* The worker is unreferenced upon creation and will not block application exit. This method
|
|
46
|
-
* is only needed if early cleanup is needed.
|
|
47
44
|
*/
|
|
48
45
|
close(): void;
|
|
49
46
|
private createWorker;
|
package/src/sass/sass-service.js
CHANGED
|
@@ -14,6 +14,14 @@ const environment_options_1 = require("../utils/environment-options");
|
|
|
14
14
|
* The maximum number of Workers that will be created to execute render requests.
|
|
15
15
|
*/
|
|
16
16
|
const MAX_RENDER_WORKERS = environment_options_1.maxWorkers;
|
|
17
|
+
/**
|
|
18
|
+
* Workaround required for lack of new Worker transfer list support in Node.js prior to 12.17
|
|
19
|
+
*/
|
|
20
|
+
let transferListWorkaround = false;
|
|
21
|
+
const version = process.versions.node.split('.').map((part) => Number(part));
|
|
22
|
+
if (version[0] === 12 && version[1] < 17) {
|
|
23
|
+
transferListWorkaround = true;
|
|
24
|
+
}
|
|
17
25
|
/**
|
|
18
26
|
* A Sass renderer implementation that provides an interface that can be used by Webpack's
|
|
19
27
|
* `sass-loader`. The implementation uses a Worker thread to perform the Sass rendering
|
|
@@ -79,13 +87,13 @@ class SassWorkerImplementation {
|
|
|
79
87
|
/**
|
|
80
88
|
* Shutdown the Sass render worker.
|
|
81
89
|
* Executing this method will stop any pending render requests.
|
|
82
|
-
*
|
|
83
|
-
* The worker is unreferenced upon creation and will not block application exit. This method
|
|
84
|
-
* is only needed if early cleanup is needed.
|
|
85
90
|
*/
|
|
86
91
|
close() {
|
|
87
92
|
for (const worker of this.workers) {
|
|
88
|
-
|
|
93
|
+
try {
|
|
94
|
+
void worker.terminate();
|
|
95
|
+
}
|
|
96
|
+
catch { }
|
|
89
97
|
}
|
|
90
98
|
this.requests.clear();
|
|
91
99
|
}
|
|
@@ -94,9 +102,12 @@ class SassWorkerImplementation {
|
|
|
94
102
|
const importerSignal = new Int32Array(new SharedArrayBuffer(4));
|
|
95
103
|
const workerPath = require.resolve('./worker');
|
|
96
104
|
const worker = new worker_threads_1.Worker(workerPath, {
|
|
97
|
-
workerData: { workerImporterPort, importerSignal },
|
|
98
|
-
transferList: [workerImporterPort],
|
|
105
|
+
workerData: transferListWorkaround ? undefined : { workerImporterPort, importerSignal },
|
|
106
|
+
transferList: transferListWorkaround ? undefined : [workerImporterPort],
|
|
99
107
|
});
|
|
108
|
+
if (transferListWorkaround) {
|
|
109
|
+
worker.postMessage({ init: true, workerImporterPort, importerSignal }, [workerImporterPort]);
|
|
110
|
+
}
|
|
100
111
|
worker.on('message', (response) => {
|
|
101
112
|
const request = this.requests.get(response.id);
|
|
102
113
|
if (!request) {
|
|
@@ -143,7 +154,6 @@ class SassWorkerImplementation {
|
|
|
143
154
|
Atomics.notify(importerSignal, 0);
|
|
144
155
|
});
|
|
145
156
|
});
|
|
146
|
-
worker.unref();
|
|
147
157
|
mainImporterPort.unref();
|
|
148
158
|
return worker;
|
|
149
159
|
}
|
package/src/sass/worker.js
CHANGED
|
@@ -9,12 +9,19 @@
|
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
10
|
const sass_1 = require("sass");
|
|
11
11
|
const worker_threads_1 = require("worker_threads");
|
|
12
|
-
if (!worker_threads_1.parentPort
|
|
12
|
+
if (!worker_threads_1.parentPort) {
|
|
13
13
|
throw new Error('Sass worker must be executed as a Worker.');
|
|
14
14
|
}
|
|
15
15
|
// The importer variables are used to proxy import requests to the main thread
|
|
16
|
-
|
|
17
|
-
worker_threads_1.parentPort.on('message', (
|
|
16
|
+
let { workerImporterPort, importerSignal } = (worker_threads_1.workerData || {});
|
|
17
|
+
worker_threads_1.parentPort.on('message', (message) => {
|
|
18
|
+
// The init message is only needed to support Node.js < 12.17 and can be removed once support is dropped
|
|
19
|
+
if (message.init) {
|
|
20
|
+
workerImporterPort = message.workerImporterPort;
|
|
21
|
+
importerSignal = message.importerSignal;
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
const { id, hasImporter, options } = message;
|
|
18
25
|
try {
|
|
19
26
|
if (hasImporter) {
|
|
20
27
|
// When a custom importer function is present, the importer request must be proxied
|
|
@@ -35,6 +42,8 @@ worker_threads_1.parentPort.on('message', ({ id, hasImporter, options }) => {
|
|
|
35
42
|
worker_threads_1.parentPort === null || worker_threads_1.parentPort === void 0 ? void 0 : worker_threads_1.parentPort.postMessage({ id, result });
|
|
36
43
|
}
|
|
37
44
|
catch (error) {
|
|
38
|
-
|
|
45
|
+
// Needed because V8 will only serialize the message and stack properties of an Error instance.
|
|
46
|
+
const { formatted, file, line, column, message, stack } = error;
|
|
47
|
+
worker_threads_1.parentPort === null || worker_threads_1.parentPort === void 0 ? void 0 : worker_threads_1.parentPort.postMessage({ id, error: { formatted, file, line, column, message, stack } });
|
|
39
48
|
}
|
|
40
49
|
});
|
package/src/server/schema.d.ts
CHANGED
|
@@ -198,7 +198,7 @@ export interface SourceMapClass {
|
|
|
198
198
|
*/
|
|
199
199
|
export interface StylePreprocessorOptions {
|
|
200
200
|
/**
|
|
201
|
-
* Paths to include. Paths will be resolved to
|
|
201
|
+
* Paths to include. Paths will be resolved to workspace root.
|
|
202
202
|
*/
|
|
203
203
|
includePaths?: string[];
|
|
204
204
|
}
|
package/src/server/schema.json
CHANGED
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"type": "object",
|
|
25
25
|
"properties": {
|
|
26
26
|
"includePaths": {
|
|
27
|
-
"description": "Paths to include. Paths will be resolved to
|
|
27
|
+
"description": "Paths to include. Paths will be resolved to workspace root.",
|
|
28
28
|
"type": "array",
|
|
29
29
|
"items": {
|
|
30
30
|
"type": "string"
|
|
@@ -40,7 +40,7 @@ class CliFilesystem {
|
|
|
40
40
|
for await (const entry of await fs_1.promises.opendir(dir)) {
|
|
41
41
|
if (entry.isFile()) {
|
|
42
42
|
// Uses posix paths since the service worker expects URLs
|
|
43
|
-
items.push('/' + path.
|
|
43
|
+
items.push('/' + path.relative(this.base, path.join(dir, entry.name)).replace(/\\/g, '/'));
|
|
44
44
|
}
|
|
45
45
|
else if (entry.isDirectory()) {
|
|
46
46
|
subdirectories.push(path.join(dir, entry.name));
|
package/src/utils/spinner.d.ts
CHANGED
|
@@ -6,11 +6,13 @@
|
|
|
6
6
|
* found in the LICENSE file at https://angular.io/license
|
|
7
7
|
*/
|
|
8
8
|
export declare class Spinner {
|
|
9
|
+
#private;
|
|
9
10
|
private readonly spinner;
|
|
10
11
|
/** When false, only fail messages will be displayed. */
|
|
11
12
|
enabled: boolean;
|
|
12
13
|
constructor(text?: string);
|
|
13
14
|
set text(text: string);
|
|
15
|
+
get isSpinning(): boolean;
|
|
14
16
|
succeed(text?: string): void;
|
|
15
17
|
fail(text?: string): void;
|
|
16
18
|
stop(): void;
|
package/src/utils/spinner.js
CHANGED
|
@@ -6,25 +6,38 @@
|
|
|
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 __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, privateMap) {
|
|
10
|
+
if (!privateMap.has(receiver)) {
|
|
11
|
+
throw new TypeError("attempted to get private field on non-instance");
|
|
12
|
+
}
|
|
13
|
+
return privateMap.get(receiver);
|
|
14
|
+
};
|
|
15
|
+
var _isTTY;
|
|
9
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
17
|
exports.Spinner = void 0;
|
|
11
18
|
const ora = require("ora");
|
|
12
19
|
const color_1 = require("./color");
|
|
20
|
+
const tty_1 = require("./tty");
|
|
13
21
|
class Spinner {
|
|
14
22
|
constructor(text) {
|
|
15
23
|
/** When false, only fail messages will be displayed. */
|
|
16
24
|
this.enabled = true;
|
|
25
|
+
_isTTY.set(this, tty_1.isTTY());
|
|
17
26
|
this.spinner = ora({
|
|
18
27
|
text,
|
|
19
28
|
// The below 2 options are needed because otherwise CTRL+C will be delayed
|
|
20
29
|
// when the underlying process is sync.
|
|
21
30
|
hideCursor: false,
|
|
22
31
|
discardStdin: false,
|
|
32
|
+
isEnabled: __classPrivateFieldGet(this, _isTTY),
|
|
23
33
|
});
|
|
24
34
|
}
|
|
25
35
|
set text(text) {
|
|
26
36
|
this.spinner.text = text;
|
|
27
37
|
}
|
|
38
|
+
get isSpinning() {
|
|
39
|
+
return this.spinner.isSpinning || !__classPrivateFieldGet(this, _isTTY);
|
|
40
|
+
}
|
|
28
41
|
succeed(text) {
|
|
29
42
|
if (this.enabled) {
|
|
30
43
|
this.spinner.succeed(text);
|
|
@@ -43,3 +56,4 @@ class Spinner {
|
|
|
43
56
|
}
|
|
44
57
|
}
|
|
45
58
|
exports.Spinner = Spinner;
|
|
59
|
+
_isTTY = new WeakMap();
|
|
@@ -25,7 +25,7 @@ const helpers_1 = require("../utils/helpers");
|
|
|
25
25
|
const stats_1 = require("../utils/stats");
|
|
26
26
|
// eslint-disable-next-line max-lines-per-function
|
|
27
27
|
function getCommonConfig(wco) {
|
|
28
|
-
var _a;
|
|
28
|
+
var _a, _b;
|
|
29
29
|
const { root, projectRoot, buildOptions, tsConfig } = wco;
|
|
30
30
|
const { platform = 'browser', sourceMap: { styles: stylesSourceMap, scripts: scriptsSourceMap, vendor: vendorSourceMap }, optimization: { styles: stylesOptimization, scripts: scriptsOptimization }, } = buildOptions;
|
|
31
31
|
const extraPlugins = [];
|
|
@@ -35,6 +35,28 @@ function getCommonConfig(wco) {
|
|
|
35
35
|
const hashFormat = helpers_1.getOutputHashFormat(buildOptions.outputHashing || 'none');
|
|
36
36
|
const buildBrowserFeatures = new utils_1.BuildBrowserFeatures(projectRoot);
|
|
37
37
|
const targetInFileName = helpers_1.getEsVersionForFileName(tsConfig.options.target, buildOptions.differentialLoadingNeeded);
|
|
38
|
+
if (buildOptions.progress) {
|
|
39
|
+
const spinner = new spinner_1.Spinner();
|
|
40
|
+
spinner.start(`Generating ${platform} application bundles (phase: setup)...`);
|
|
41
|
+
extraPlugins.push(new webpack_1.ProgressPlugin({
|
|
42
|
+
handler: (percentage, message) => {
|
|
43
|
+
const phase = message ? ` (phase: ${message})` : '';
|
|
44
|
+
spinner.text = `Generating ${platform} application bundles${phase}...`;
|
|
45
|
+
switch (percentage) {
|
|
46
|
+
case 1:
|
|
47
|
+
if (spinner.isSpinning) {
|
|
48
|
+
spinner.succeed(`${platform.replace(/^\w/, (s) => s.toUpperCase())} application bundle generation complete.`);
|
|
49
|
+
}
|
|
50
|
+
break;
|
|
51
|
+
case 0:
|
|
52
|
+
if (!spinner.isSpinning) {
|
|
53
|
+
spinner.start();
|
|
54
|
+
}
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
}));
|
|
59
|
+
}
|
|
38
60
|
if (buildOptions.main) {
|
|
39
61
|
const mainPath = path.resolve(root, buildOptions.main);
|
|
40
62
|
entryPoints['main'] = [mainPath];
|
|
@@ -161,32 +183,6 @@ function getCommonConfig(wco) {
|
|
|
161
183
|
patterns: copyWebpackPluginPatterns,
|
|
162
184
|
}));
|
|
163
185
|
}
|
|
164
|
-
if (buildOptions.progress) {
|
|
165
|
-
const spinner = new spinner_1.Spinner();
|
|
166
|
-
let previousPercentage;
|
|
167
|
-
extraPlugins.push(new webpack_1.ProgressPlugin({
|
|
168
|
-
handler: (percentage, message) => {
|
|
169
|
-
if (previousPercentage === 1 && percentage !== 0) {
|
|
170
|
-
// In some scenarios in Webpack 5 percentage goes from 1 back to 0.99.
|
|
171
|
-
// Ex: 0.99 -> 1 -> 0.99 -> 1
|
|
172
|
-
// This causes the "complete" message to be displayed multiple times.
|
|
173
|
-
return;
|
|
174
|
-
}
|
|
175
|
-
switch (percentage) {
|
|
176
|
-
case 0:
|
|
177
|
-
spinner.start(`Generating ${platform} application bundles...`);
|
|
178
|
-
break;
|
|
179
|
-
case 1:
|
|
180
|
-
spinner.succeed(`${platform.replace(/^\w/, (s) => s.toUpperCase())} application bundle generation complete.`);
|
|
181
|
-
break;
|
|
182
|
-
default:
|
|
183
|
-
spinner.text = `Generating ${platform} application bundles (phase: ${message})...`;
|
|
184
|
-
break;
|
|
185
|
-
}
|
|
186
|
-
previousPercentage = percentage;
|
|
187
|
-
},
|
|
188
|
-
}));
|
|
189
|
-
}
|
|
190
186
|
if (buildOptions.showCircularDependencies) {
|
|
191
187
|
const CircularDependencyPlugin = require('circular-dependency-plugin');
|
|
192
188
|
extraPlugins.push(new CircularDependencyPlugin({
|
|
@@ -199,7 +195,7 @@ function getCommonConfig(wco) {
|
|
|
199
195
|
compiler.hooks.done.tapPromise('angular-cli-stats', async (stats) => {
|
|
200
196
|
const { stringifyStream } = await Promise.resolve().then(() => require('@discoveryjs/json-ext'));
|
|
201
197
|
const data = stats.toJson('verbose');
|
|
202
|
-
const statsOutputPath = path.
|
|
198
|
+
const statsOutputPath = path.resolve(root, buildOptions.outputPath, 'stats.json');
|
|
203
199
|
try {
|
|
204
200
|
await fs_1.promises.mkdir(path.dirname(statsOutputPath), { recursive: true });
|
|
205
201
|
await new Promise((resolve, reject) => stringifyStream(data)
|
|
@@ -233,28 +229,6 @@ function getCommonConfig(wco) {
|
|
|
233
229
|
];
|
|
234
230
|
}
|
|
235
231
|
const extraMinimizers = [];
|
|
236
|
-
if (stylesOptimization.minify) {
|
|
237
|
-
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
|
|
238
|
-
extraMinimizers.push(new CssMinimizerPlugin({
|
|
239
|
-
// component styles retain their original file name
|
|
240
|
-
test: /\.(?:css|scss|sass|less|styl)$/,
|
|
241
|
-
parallel: environment_options_1.maxWorkers,
|
|
242
|
-
minify: [CssMinimizerPlugin.cssnanoMinify],
|
|
243
|
-
minimizerOptions: {
|
|
244
|
-
preset: [
|
|
245
|
-
'default',
|
|
246
|
-
{
|
|
247
|
-
// Disable SVG optimizations, as this can cause optimizations which are not compatible in all browsers.
|
|
248
|
-
svgo: false,
|
|
249
|
-
// Disable `calc` optimizations, due to several issues. #16910, #16875, #17890
|
|
250
|
-
calc: false,
|
|
251
|
-
// Disable CSS rules sorted due to several issues #20693, https://github.com/ionic-team/ionic-framework/issues/23266 and https://github.com/cssnano/cssnano/issues/1054
|
|
252
|
-
cssDeclarationSorter: false,
|
|
253
|
-
},
|
|
254
|
-
],
|
|
255
|
-
},
|
|
256
|
-
}));
|
|
257
|
-
}
|
|
258
232
|
if (scriptsOptimization) {
|
|
259
233
|
const TerserPlugin = require('terser-webpack-plugin');
|
|
260
234
|
const { GLOBAL_DEFS_FOR_TERSER, GLOBAL_DEFS_FOR_TERSER_WITH_AOT, } = require('@angular/compiler-cli');
|
|
@@ -348,9 +322,9 @@ function getCommonConfig(wco) {
|
|
|
348
322
|
context: root,
|
|
349
323
|
entry: entryPoints,
|
|
350
324
|
output: {
|
|
351
|
-
clean: buildOptions.deleteOutputPath,
|
|
325
|
+
clean: (_a = buildOptions.deleteOutputPath) !== null && _a !== void 0 ? _a : true,
|
|
352
326
|
path: path.resolve(root, buildOptions.outputPath),
|
|
353
|
-
publicPath: (
|
|
327
|
+
publicPath: (_b = buildOptions.deployUrl) !== null && _b !== void 0 ? _b : '',
|
|
354
328
|
filename: ({ chunk }) => {
|
|
355
329
|
if ((chunk === null || chunk === void 0 ? void 0 : chunk.name) === 'polyfills-es5') {
|
|
356
330
|
return `polyfills-es5${hashFormat.chunk}.js`;
|
|
@@ -34,6 +34,14 @@ function getServerConfig(wco) {
|
|
|
34
34
|
output: {
|
|
35
35
|
libraryTarget: 'commonjs',
|
|
36
36
|
},
|
|
37
|
+
module: {
|
|
38
|
+
parser: {
|
|
39
|
+
javascript: {
|
|
40
|
+
worker: false,
|
|
41
|
+
url: false,
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
},
|
|
37
45
|
plugins: [
|
|
38
46
|
// Fixes Critical dependency: the request of a dependency is an expression
|
|
39
47
|
new webpack_1.ContextReplacementPlugin(/@?hapi(\\|\/)/),
|
|
@@ -13,16 +13,12 @@ export declare function getWebpackStatsConfig(verbose?: boolean): {
|
|
|
13
13
|
timings: boolean;
|
|
14
14
|
chunks: boolean;
|
|
15
15
|
builtAt: boolean;
|
|
16
|
-
chunkModules: boolean;
|
|
17
|
-
children: boolean;
|
|
18
|
-
modules: boolean;
|
|
19
|
-
reasons: boolean;
|
|
20
16
|
warnings: boolean;
|
|
21
17
|
errors: boolean;
|
|
22
18
|
assets: boolean;
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
19
|
+
cachedAssets: boolean;
|
|
20
|
+
ids: boolean;
|
|
21
|
+
entrypoints: boolean;
|
|
26
22
|
};
|
|
27
23
|
export declare function getStatsConfig(wco: WebpackConfigOptions): {
|
|
28
24
|
stats: {
|
|
@@ -32,15 +28,11 @@ export declare function getStatsConfig(wco: WebpackConfigOptions): {
|
|
|
32
28
|
timings: boolean;
|
|
33
29
|
chunks: boolean;
|
|
34
30
|
builtAt: boolean;
|
|
35
|
-
chunkModules: boolean;
|
|
36
|
-
children: boolean;
|
|
37
|
-
modules: boolean;
|
|
38
|
-
reasons: boolean;
|
|
39
31
|
warnings: boolean;
|
|
40
32
|
errors: boolean;
|
|
41
33
|
assets: boolean;
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
34
|
+
cachedAssets: boolean;
|
|
35
|
+
ids: boolean;
|
|
36
|
+
entrypoints: boolean;
|
|
45
37
|
};
|
|
46
38
|
};
|
|
@@ -15,16 +15,13 @@ const webpackOutputOptions = {
|
|
|
15
15
|
timings: true,
|
|
16
16
|
chunks: true,
|
|
17
17
|
builtAt: true,
|
|
18
|
-
chunkModules: false,
|
|
19
|
-
children: false,
|
|
20
|
-
modules: false,
|
|
21
|
-
reasons: false,
|
|
22
18
|
warnings: true,
|
|
23
19
|
errors: true,
|
|
24
20
|
assets: true,
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
21
|
+
cachedAssets: true,
|
|
22
|
+
// Needed for markAsyncChunksNonInitial.
|
|
23
|
+
ids: true,
|
|
24
|
+
entrypoints: true,
|
|
28
25
|
};
|
|
29
26
|
const verboseWebpackOutputOptions = {
|
|
30
27
|
// The verbose output will most likely be piped to a file, so colors just mess it up.
|
|
@@ -39,8 +36,8 @@ const verboseWebpackOutputOptions = {
|
|
|
39
36
|
errorDetails: true,
|
|
40
37
|
moduleTrace: true,
|
|
41
38
|
logging: 'verbose',
|
|
39
|
+
modulesSpace: Infinity,
|
|
42
40
|
};
|
|
43
|
-
verboseWebpackOutputOptions['modulesSpace'] = Infinity;
|
|
44
41
|
function getWebpackStatsConfig(verbose = false) {
|
|
45
42
|
return verbose
|
|
46
43
|
? { ...webpackOutputOptions, ...verboseWebpackOutputOptions }
|
|
@@ -12,6 +12,7 @@ const fs = require("fs");
|
|
|
12
12
|
const path = require("path");
|
|
13
13
|
const sass_service_1 = require("../../sass/sass-service");
|
|
14
14
|
const build_browser_features_1 = require("../../utils/build-browser-features");
|
|
15
|
+
const environment_options_1 = require("../../utils/environment-options");
|
|
15
16
|
const plugins_1 = require("../plugins");
|
|
16
17
|
const helpers_1 = require("../utils/helpers");
|
|
17
18
|
function resolveGlobalStyles(styleEntrypoints, root, preserveSymlinks) {
|
|
@@ -80,6 +81,13 @@ function getStylesConfig(wco) {
|
|
|
80
81
|
}
|
|
81
82
|
catch {
|
|
82
83
|
sassImplementation = new sass_service_1.SassWorkerImplementation();
|
|
84
|
+
extraPlugins.push({
|
|
85
|
+
apply(compiler) {
|
|
86
|
+
compiler.hooks.shutdown.tap('sass-worker', () => {
|
|
87
|
+
sassImplementation === null || sassImplementation === void 0 ? void 0 : sassImplementation.close();
|
|
88
|
+
});
|
|
89
|
+
},
|
|
90
|
+
});
|
|
83
91
|
}
|
|
84
92
|
const assetNameTemplate = helpers_1.assetNameTemplateFactory(hashFormat);
|
|
85
93
|
const extraPostcssPlugins = [];
|
|
@@ -116,6 +124,11 @@ function getStylesConfig(wco) {
|
|
|
116
124
|
}
|
|
117
125
|
}
|
|
118
126
|
const { supportedBrowsers } = new build_browser_features_1.BuildBrowserFeatures(wco.projectRoot);
|
|
127
|
+
const postcssPresetEnvPlugin = postcssPresetEnv({
|
|
128
|
+
browsers: supportedBrowsers,
|
|
129
|
+
autoprefixer: true,
|
|
130
|
+
stage: 3,
|
|
131
|
+
});
|
|
119
132
|
const postcssOptionsCreator = (inlineSourcemaps, extracted) => {
|
|
120
133
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
121
134
|
const optionGenerator = (loader) => ({
|
|
@@ -151,11 +164,7 @@ function getStylesConfig(wco) {
|
|
|
151
164
|
extracted,
|
|
152
165
|
}),
|
|
153
166
|
...extraPostcssPlugins,
|
|
154
|
-
|
|
155
|
-
browsers: supportedBrowsers,
|
|
156
|
-
autoprefixer: true,
|
|
157
|
-
stage: 3,
|
|
158
|
-
}),
|
|
167
|
+
postcssPresetEnvPlugin,
|
|
159
168
|
],
|
|
160
169
|
});
|
|
161
170
|
// postcss-loader fails when trying to determine configuration files for data URIs
|
|
@@ -343,11 +352,46 @@ function getStylesConfig(wco) {
|
|
|
343
352
|
],
|
|
344
353
|
});
|
|
345
354
|
}
|
|
355
|
+
const extraMinimizers = [];
|
|
356
|
+
if (buildOptions.optimization.styles.minify) {
|
|
357
|
+
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
|
|
358
|
+
const minimizerOptions = {
|
|
359
|
+
preset: [
|
|
360
|
+
'default',
|
|
361
|
+
{
|
|
362
|
+
// Disable SVG optimizations, as this can cause optimizations which are not compatible in all browsers.
|
|
363
|
+
svgo: false,
|
|
364
|
+
// Disable `calc` optimizations, due to several issues. #16910, #16875, #17890
|
|
365
|
+
calc: false,
|
|
366
|
+
// Disable CSS rules sorted due to several issues #20693, https://github.com/ionic-team/ionic-framework/issues/23266 and https://github.com/cssnano/cssnano/issues/1054
|
|
367
|
+
cssDeclarationSorter: false,
|
|
368
|
+
},
|
|
369
|
+
],
|
|
370
|
+
};
|
|
371
|
+
const globalBundlesRegExp = new RegExp(`^(${Object.keys(entryPoints).join('|')})(\.[0-9a-f]{20})?.css$`);
|
|
372
|
+
extraMinimizers.push(new CssMinimizerPlugin({
|
|
373
|
+
// Component styles retain their original file name
|
|
374
|
+
test: /\.(?:css|scss|sass|less|styl)$/,
|
|
375
|
+
parallel: false,
|
|
376
|
+
exclude: globalBundlesRegExp,
|
|
377
|
+
minify: [CssMinimizerPlugin.cssnanoMinify],
|
|
378
|
+
minimizerOptions,
|
|
379
|
+
}), new CssMinimizerPlugin({
|
|
380
|
+
test: /\.css$/,
|
|
381
|
+
include: globalBundlesRegExp,
|
|
382
|
+
parallel: environment_options_1.maxWorkers,
|
|
383
|
+
minify: [CssMinimizerPlugin.cssnanoMinify],
|
|
384
|
+
minimizerOptions,
|
|
385
|
+
}));
|
|
386
|
+
}
|
|
346
387
|
return {
|
|
347
388
|
entry: entryPoints,
|
|
348
389
|
module: {
|
|
349
390
|
rules: [...fileLanguageRules, ...inlineLanguageRules],
|
|
350
391
|
},
|
|
392
|
+
optimization: {
|
|
393
|
+
minimizer: extraMinimizers,
|
|
394
|
+
},
|
|
351
395
|
plugins: extraPlugins,
|
|
352
396
|
};
|
|
353
397
|
}
|
|
@@ -10,9 +10,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
10
10
|
exports.getTestConfig = void 0;
|
|
11
11
|
const glob = require("glob");
|
|
12
12
|
const path = require("path");
|
|
13
|
+
const typescript_1 = require("typescript");
|
|
13
14
|
const helpers_1 = require("../utils/helpers");
|
|
14
15
|
function getTestConfig(wco) {
|
|
15
|
-
const { buildOptions: { codeCoverage, codeCoverageExclude, main, sourceMap }, root, sourceRoot, } = wco;
|
|
16
|
+
const { buildOptions: { codeCoverage, codeCoverageExclude, main, sourceMap, webWorkerTsConfig }, root, sourceRoot, } = wco;
|
|
16
17
|
const extraRules = [];
|
|
17
18
|
const extraPlugins = [];
|
|
18
19
|
if (codeCoverage) {
|
|
@@ -38,6 +39,7 @@ function getTestConfig(wco) {
|
|
|
38
39
|
}
|
|
39
40
|
return {
|
|
40
41
|
mode: 'development',
|
|
42
|
+
target: wco.tsConfig.options.target === typescript_1.ScriptTarget.ES5 ? ['web', 'es5'] : 'web',
|
|
41
43
|
resolve: {
|
|
42
44
|
mainFields: ['es2015', 'browser', 'module', 'main'],
|
|
43
45
|
},
|
|
@@ -47,6 +49,14 @@ function getTestConfig(wco) {
|
|
|
47
49
|
},
|
|
48
50
|
module: {
|
|
49
51
|
rules: extraRules,
|
|
52
|
+
parser: webWorkerTsConfig === undefined
|
|
53
|
+
? undefined
|
|
54
|
+
: {
|
|
55
|
+
javascript: {
|
|
56
|
+
worker: false,
|
|
57
|
+
url: false,
|
|
58
|
+
},
|
|
59
|
+
},
|
|
50
60
|
},
|
|
51
61
|
plugins: extraPlugins,
|
|
52
62
|
optimization: {
|
|
@@ -40,7 +40,7 @@ class IndexHtmlWebpackPlugin extends index_html_generator_1.IndexHtmlGenerator {
|
|
|
40
40
|
const moduleFiles = [];
|
|
41
41
|
try {
|
|
42
42
|
for (const [entryName, entrypoint] of this.compilation.entrypoints) {
|
|
43
|
-
const entryFiles = (_a = entrypoint === null || entrypoint === void 0 ? void 0 : entrypoint.getFiles()) === null || _a === void 0 ? void 0 : _a.map((f) => ({
|
|
43
|
+
const entryFiles = (_a = entrypoint === null || entrypoint === void 0 ? void 0 : entrypoint.getFiles()) === null || _a === void 0 ? void 0 : _a.filter((f) => !f.endsWith('.hot-update.js')).map((f) => ({
|
|
44
44
|
name: entryName,
|
|
45
45
|
file: f,
|
|
46
46
|
extension: path_1.extname(f),
|
|
@@ -9,6 +9,7 @@ Reloaded before every execution run.
|
|
|
9
9
|
<title></title>
|
|
10
10
|
<base href="/" />
|
|
11
11
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
|
12
|
+
<link rel="stylesheet" href="_karma_webpack_/styles.css" crossorigin="anonymous" />
|
|
12
13
|
<meta
|
|
13
14
|
name="viewport"
|
|
14
15
|
content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"
|
|
@@ -34,7 +35,6 @@ Reloaded before every execution run.
|
|
|
34
35
|
<script src="_karma_webpack_/polyfills.js" crossorigin="anonymous"></script>
|
|
35
36
|
<!-- Dynamically replaced with <script> tags -->
|
|
36
37
|
%SCRIPTS%
|
|
37
|
-
<script src="_karma_webpack_/styles.js" crossorigin="anonymous"></script>
|
|
38
38
|
<script src="_karma_webpack_/scripts.js" crossorigin="anonymous"></script>
|
|
39
39
|
<script src="_karma_webpack_/vendor.js" crossorigin="anonymous"></script>
|
|
40
40
|
<script src="_karma_webpack_/main.js" crossorigin="anonymous"></script>
|
|
@@ -10,6 +10,7 @@ just for immediate execution, without reporting to Karma server.
|
|
|
10
10
|
<title>Karma DEBUG RUNNER</title>
|
|
11
11
|
<base href="/" />
|
|
12
12
|
<link href="favicon.ico" rel="icon" type="image/x-icon" />
|
|
13
|
+
<link rel="stylesheet" href="_karma_webpack_/styles.css" crossorigin="anonymous" />
|
|
13
14
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
|
14
15
|
<meta
|
|
15
16
|
name="viewport"
|
|
@@ -36,7 +37,6 @@ just for immediate execution, without reporting to Karma server.
|
|
|
36
37
|
<script src="_karma_webpack_/polyfills.js" crossorigin="anonymous"></script>
|
|
37
38
|
<!-- Dynamically replaced with <script> tags -->
|
|
38
39
|
%SCRIPTS%
|
|
39
|
-
<script src="_karma_webpack_/styles.js" crossorigin="anonymous"></script>
|
|
40
40
|
<script src="_karma_webpack_/scripts.js" crossorigin="anonymous"></script>
|
|
41
41
|
<script src="_karma_webpack_/vendor.js" crossorigin="anonymous"></script>
|
|
42
42
|
<script src="_karma_webpack_/main.js" crossorigin="anonymous"></script>
|
|
@@ -248,7 +248,7 @@ function fallbackMiddleware() {
|
|
|
248
248
|
`/${KARMA_APPLICATION_PATH}/polyfills.js`,
|
|
249
249
|
`/${KARMA_APPLICATION_PATH}/polyfills-es5.js`,
|
|
250
250
|
`/${KARMA_APPLICATION_PATH}/scripts.js`,
|
|
251
|
-
`/${KARMA_APPLICATION_PATH}/styles.
|
|
251
|
+
`/${KARMA_APPLICATION_PATH}/styles.css`,
|
|
252
252
|
`/${KARMA_APPLICATION_PATH}/vendor.js`,
|
|
253
253
|
];
|
|
254
254
|
if (request.url && alwaysServe.includes(request.url)) {
|
|
@@ -83,7 +83,7 @@ function default_1(options) {
|
|
|
83
83
|
}
|
|
84
84
|
loader.addDependency(result);
|
|
85
85
|
if (emitFile) {
|
|
86
|
-
loader.emitFile(outputPath, content, undefined);
|
|
86
|
+
loader.emitFile(outputPath, content, undefined, { sourceFilename: result });
|
|
87
87
|
}
|
|
88
88
|
let outputUrl = outputPath.replace(/\\/g, '/');
|
|
89
89
|
if (hash || search) {
|
|
@@ -22,7 +22,7 @@ function markAsyncChunksNonInitial(webpackStats, extraEntryPoints) {
|
|
|
22
22
|
// **cannot** be loaded in main bundle.
|
|
23
23
|
const asyncChunkIds = extraEntryPoints
|
|
24
24
|
.filter((entryPoint) => !entryPoint.inject)
|
|
25
|
-
.flatMap((entryPoint) => entryPoints[entryPoint.bundleName].chunks);
|
|
25
|
+
.flatMap((entryPoint) => { var _a; return (_a = entryPoints[entryPoint.bundleName].chunks) === null || _a === void 0 ? void 0 : _a.filter((n) => n !== 'runtime'); });
|
|
26
26
|
// Find chunks for each ID.
|
|
27
27
|
const asyncChunks = asyncChunkIds.map((chunkId) => {
|
|
28
28
|
const chunk = chunks.find((chunk) => chunk.id === chunkId);
|
|
@@ -33,9 +33,13 @@ function markAsyncChunksNonInitial(webpackStats, extraEntryPoints) {
|
|
|
33
33
|
});
|
|
34
34
|
// A chunk is considered `initial` only if Webpack already belives it to be initial
|
|
35
35
|
// and the application developer did not mark it async via an extra entry point.
|
|
36
|
-
return chunks.map((chunk) =>
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
36
|
+
return chunks.map((chunk) => {
|
|
37
|
+
return asyncChunks.find((asyncChunk) => asyncChunk === chunk)
|
|
38
|
+
? {
|
|
39
|
+
...chunk,
|
|
40
|
+
initial: false,
|
|
41
|
+
}
|
|
42
|
+
: chunk;
|
|
43
|
+
});
|
|
40
44
|
}
|
|
41
45
|
exports.markAsyncChunksNonInitial = markAsyncChunksNonInitial;
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
import { WebpackLoggingCallback } from '@angular-devkit/build-webpack';
|
|
9
9
|
import { logging } from '@angular-devkit/core';
|
|
10
10
|
import { Configuration, StatsCompilation } from 'webpack';
|
|
11
|
+
import { Schema as BrowserBuilderOptions } from '../../browser/schema';
|
|
11
12
|
export declare function formatSize(size: number): string;
|
|
12
13
|
export declare type BundleStatsData = [files: string, names: string, size: number | string];
|
|
13
14
|
export declare type ChunkType = 'modern' | 'legacy' | 'unknown';
|
|
@@ -20,7 +21,6 @@ export declare function generateBundleStats(info: {
|
|
|
20
21
|
size?: number;
|
|
21
22
|
files?: string[];
|
|
22
23
|
names?: string[];
|
|
23
|
-
entry?: boolean;
|
|
24
24
|
initial?: boolean;
|
|
25
25
|
rendered?: boolean;
|
|
26
26
|
chunkType?: ChunkType;
|
|
@@ -30,5 +30,5 @@ export declare function statsWarningsToString(json: StatsCompilation, statsConfi
|
|
|
30
30
|
export declare function statsErrorsToString(json: StatsCompilation, statsConfig: any): string;
|
|
31
31
|
export declare function statsHasErrors(json: StatsCompilation): boolean;
|
|
32
32
|
export declare function statsHasWarnings(json: StatsCompilation): boolean;
|
|
33
|
-
export declare function createWebpackLoggingCallback(
|
|
33
|
+
export declare function createWebpackLoggingCallback(options: BrowserBuilderOptions, logger: logging.LoggerApi): WebpackLoggingCallback;
|
|
34
34
|
export declare function webpackStatsLogger(logger: logging.LoggerApi, json: StatsCompilation, config: Configuration, bundleStats?: BundleStats[]): void;
|
|
@@ -13,6 +13,8 @@ const path = require("path");
|
|
|
13
13
|
const textTable = require("text-table");
|
|
14
14
|
const color_1 = require("../../utils/color");
|
|
15
15
|
const stats_1 = require("../configs/stats");
|
|
16
|
+
const async_chunks_1 = require("./async-chunks");
|
|
17
|
+
const helpers_1 = require("./helpers");
|
|
16
18
|
function formatSize(size) {
|
|
17
19
|
if (size <= 0) {
|
|
18
20
|
return '0 bytes';
|
|
@@ -30,7 +32,7 @@ function generateBundleStats(info) {
|
|
|
30
32
|
const size = typeof info.size === 'number' ? info.size : '-';
|
|
31
33
|
const files = (_b = (_a = info.files) === null || _a === void 0 ? void 0 : _a.filter((f) => !f.endsWith('.map')).map((f) => path.basename(f)).join(', ')) !== null && _b !== void 0 ? _b : '';
|
|
32
34
|
const names = ((_c = info.names) === null || _c === void 0 ? void 0 : _c.length) ? info.names.join(', ') : '-';
|
|
33
|
-
const initial = !!
|
|
35
|
+
const initial = !!info.initial;
|
|
34
36
|
const chunkType = info.chunkType || 'unknown';
|
|
35
37
|
return {
|
|
36
38
|
chunkType,
|
|
@@ -255,12 +257,22 @@ function statsHasWarnings(json) {
|
|
|
255
257
|
return !!(((_a = json.warnings) === null || _a === void 0 ? void 0 : _a.length) || ((_b = json.children) === null || _b === void 0 ? void 0 : _b.some((c) => { var _a; return (_a = c.warnings) === null || _a === void 0 ? void 0 : _a.length; })));
|
|
256
258
|
}
|
|
257
259
|
exports.statsHasWarnings = statsHasWarnings;
|
|
258
|
-
function createWebpackLoggingCallback(
|
|
260
|
+
function createWebpackLoggingCallback(options, logger) {
|
|
261
|
+
const { verbose = false, scripts = [], styles = [] } = options;
|
|
262
|
+
const extraEntryPoints = [
|
|
263
|
+
...helpers_1.normalizeExtraEntryPoints(styles, 'styles'),
|
|
264
|
+
...helpers_1.normalizeExtraEntryPoints(scripts, 'scripts'),
|
|
265
|
+
];
|
|
259
266
|
return (stats, config) => {
|
|
260
267
|
if (verbose) {
|
|
261
268
|
logger.info(stats.toString(config.stats));
|
|
262
269
|
}
|
|
263
|
-
|
|
270
|
+
const rawStats = stats.toJson(stats_1.getWebpackStatsConfig(false));
|
|
271
|
+
const webpackStats = {
|
|
272
|
+
...rawStats,
|
|
273
|
+
chunks: async_chunks_1.markAsyncChunksNonInitial(rawStats, extraEntryPoints),
|
|
274
|
+
};
|
|
275
|
+
webpackStatsLogger(logger, webpackStats, config);
|
|
264
276
|
};
|
|
265
277
|
}
|
|
266
278
|
exports.createWebpackLoggingCallback = createWebpackLoggingCallback;
|