@angular-devkit/build-angular 0.1102.2 → 0.1102.6

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 CHANGED
@@ -1,16 +1,16 @@
1
1
  {
2
2
  "name": "@angular-devkit/build-angular",
3
- "version": "0.1102.2",
3
+ "version": "0.1102.6",
4
4
  "description": "Angular Webpack Build Facade",
5
5
  "experimental": true,
6
6
  "main": "src/index.js",
7
7
  "typings": "src/index.d.ts",
8
8
  "builders": "builders.json",
9
9
  "dependencies": {
10
- "@angular-devkit/architect": "0.1102.2",
11
- "@angular-devkit/build-optimizer": "0.1102.2",
12
- "@angular-devkit/build-webpack": "0.1102.2",
13
- "@angular-devkit/core": "11.2.2",
10
+ "@angular-devkit/architect": "0.1102.6",
11
+ "@angular-devkit/build-optimizer": "0.1102.6",
12
+ "@angular-devkit/build-webpack": "0.1102.6",
13
+ "@angular-devkit/core": "11.2.6",
14
14
  "@babel/core": "7.12.10",
15
15
  "@babel/generator": "7.12.11",
16
16
  "@babel/plugin-transform-async-to-generator": "7.12.1",
@@ -18,8 +18,9 @@
18
18
  "@babel/preset-env": "7.12.11",
19
19
  "@babel/runtime": "7.12.5",
20
20
  "@babel/template": "7.12.7",
21
+ "@discoveryjs/json-ext": "0.5.2",
21
22
  "@jsdevtools/coverage-istanbul-loader": "3.0.5",
22
- "@ngtools/webpack": "11.2.2",
23
+ "@ngtools/webpack": "11.2.6",
23
24
  "ansi-colors": "4.1.1",
24
25
  "autoprefixer": "10.2.4",
25
26
  "babel-loader": "8.2.2",
@@ -49,57 +49,71 @@ exports.default = babel_loader_1.custom(() => {
49
49
  compact: false,
50
50
  cacheCompression: false,
51
51
  sourceType: 'unambiguous',
52
+ inputSourceMap: false,
52
53
  });
53
54
  return {
54
- async customOptions({ scriptTarget, ...loaderOptions }, { source }) {
55
+ async customOptions({ i18n, scriptTarget, ...rawOptions }, { source }) {
55
56
  // Must process file if plugins are added
56
- let shouldProcess = Array.isArray(loaderOptions.plugins) && loaderOptions.plugins.length > 0;
57
+ let shouldProcess = Array.isArray(rawOptions.plugins) && rawOptions.plugins.length > 0;
58
+ const customOptions = {
59
+ forceAsyncTransformation: false,
60
+ forceES5: false,
61
+ shouldLink: false,
62
+ i18n: undefined,
63
+ };
57
64
  // Analyze file for linking
58
- let shouldLink = false;
59
65
  const { hasLinkerSupport, requiresLinking } = await checkLinking(this.resourcePath, source);
60
66
  if (requiresLinking && !hasLinkerSupport) {
61
67
  // Cannot link if there is no linker support
62
68
  this.emitError('File requires the Angular linker. "@angular/compiler-cli" version 11.1.0 or greater is needed.');
63
69
  }
64
70
  else {
65
- shouldLink = requiresLinking;
71
+ customOptions.shouldLink = requiresLinking;
66
72
  }
67
- shouldProcess || (shouldProcess = shouldLink);
73
+ shouldProcess || (shouldProcess = customOptions.shouldLink);
68
74
  // Analyze for ES target processing
69
- let forceES5 = false;
70
- let forceAsyncTransformation = false;
71
75
  const esTarget = scriptTarget;
72
- if (esTarget < typescript_1.ScriptTarget.ES2015) {
73
- // TypeScript files will have already been downlevelled
74
- forceES5 = !/\.tsx?$/.test(this.resourcePath);
76
+ if (esTarget !== undefined) {
77
+ if (esTarget < typescript_1.ScriptTarget.ES2015) {
78
+ // TypeScript files will have already been downlevelled
79
+ customOptions.forceES5 = !/\.tsx?$/.test(this.resourcePath);
80
+ }
81
+ else if (esTarget >= typescript_1.ScriptTarget.ES2017) {
82
+ customOptions.forceAsyncTransformation = !/[\\\/]fesm2015[\\\/]/.test(this.resourcePath) && source.includes('async');
83
+ }
84
+ shouldProcess || (shouldProcess = customOptions.forceAsyncTransformation || customOptions.forceES5);
75
85
  }
76
- else if (esTarget >= typescript_1.ScriptTarget.ES2017) {
77
- forceAsyncTransformation = source.includes('async');
86
+ // Analyze for i18n inlining
87
+ if (i18n &&
88
+ !/[\\\/]@angular[\\\/](?:compiler|localize)/.test(this.resourcePath) &&
89
+ source.includes('$localize')) {
90
+ customOptions.i18n = i18n;
91
+ shouldProcess = true;
78
92
  }
79
- shouldProcess || (shouldProcess = forceAsyncTransformation || forceES5);
80
93
  // Add provided loader options to default base options
81
- const options = {
94
+ const loaderOptions = {
82
95
  ...baseOptions,
83
- ...loaderOptions,
96
+ ...rawOptions,
84
97
  cacheIdentifier: JSON.stringify({
85
98
  buildAngular: require('../../package.json').version,
86
- forceAsyncTransformation,
87
- forceES5,
88
- shouldLink,
99
+ customOptions,
89
100
  baseOptions,
90
- loaderOptions,
101
+ rawOptions,
91
102
  }),
92
103
  };
93
104
  // Skip babel processing if no actions are needed
94
105
  if (!shouldProcess) {
95
106
  // Force the current file to be ignored
96
- options.ignore = [() => true];
107
+ loaderOptions.ignore = [() => true];
97
108
  }
98
- return { custom: { forceAsyncTransformation, forceES5, shouldLink }, loader: options };
109
+ return { custom: customOptions, loader: loaderOptions };
99
110
  },
100
111
  config(configuration, { customOptions }) {
101
112
  return {
102
113
  ...configuration.options,
114
+ // Workaround for https://github.com/babel/babel-loader/pull/896 is available
115
+ // Delete once the above PR is released
116
+ inputSourceMap: (configuration.options.inputSourceMap || false),
103
117
  presets: [
104
118
  ...(configuration.options.presets || []),
105
119
  [
@@ -108,6 +122,7 @@ exports.default = babel_loader_1.custom(() => {
108
122
  angularLinker: customOptions.shouldLink,
109
123
  forceES5: customOptions.forceES5,
110
124
  forceAsyncTransformation: customOptions.forceAsyncTransformation,
125
+ i18n: customOptions.i18n,
111
126
  diagnosticReporter: (type, message) => {
112
127
  switch (type) {
113
128
  case 'error':
@@ -0,0 +1,22 @@
1
+ /**
2
+ * @license
3
+ * Copyright Google Inc. 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
+
9
+ // Workaround for https://github.com/bazelbuild/rules_nodejs/issues/1033
10
+ // Alternative approach instead of https://github.com/angular/angular/pull/33226
11
+ declare module '@babel/core' {
12
+ export * from '@types/babel__core';
13
+ }
14
+ declare module '@babel/generator' {
15
+ export { default } from '@types/babel__generator';
16
+ }
17
+ declare module '@babel/traverse' {
18
+ export { default } from '@types/babel__traverse';
19
+ }
20
+ declare module '@babel/template' {
21
+ export { default } from '@types/babel__template';
22
+ }
@@ -27,7 +27,6 @@ const package_chunk_sort_1 = require("../utils/package-chunk-sort");
27
27
  const read_tsconfig_1 = require("../utils/read-tsconfig");
28
28
  const version_1 = require("../utils/version");
29
29
  const webpack_browser_config_1 = require("../utils/webpack-browser-config");
30
- const webpack_diagnostics_1 = require("../utils/webpack-diagnostics");
31
30
  const configs_1 = require("../webpack/configs");
32
31
  const index_html_webpack_plugin_1 = require("../webpack/plugins/index-html-webpack-plugin");
33
32
  const stats_1 = require("../webpack/utils/stats");
@@ -255,7 +254,6 @@ exports.serveWebpackBrowser = serveWebpackBrowser;
255
254
  async function setupLocalize(locale, i18n, browserOptions, webpackConfig) {
256
255
  var _a;
257
256
  const localeDescription = i18n.locales[locale];
258
- const i18nDiagnostics = [];
259
257
  // Modify main entrypoint to include locale data
260
258
  if ((localeDescription === null || localeDescription === void 0 ? void 0 : localeDescription.dataPath) &&
261
259
  typeof webpackConfig.entry === 'object' &&
@@ -274,37 +272,24 @@ async function setupLocalize(locale, i18n, browserOptions, webpackConfig) {
274
272
  missingTranslationBehavior = 'ignore';
275
273
  translation = {};
276
274
  }
275
+ const i18nLoaderOptions = {
276
+ locale,
277
+ missingTranslationBehavior,
278
+ translation: i18n.shouldInline ? translation : undefined,
279
+ };
277
280
  const i18nRule = {
278
- test: /\.(?:m?js|ts)$/,
281
+ test: /\.(?:[cm]?js|ts)$/,
279
282
  enforce: 'post',
280
283
  use: [
281
284
  {
282
- loader: require.resolve('babel-loader'),
285
+ loader: require.resolve('../babel/webpack-loader'),
283
286
  options: {
284
- babelrc: false,
285
- configFile: false,
286
- compact: false,
287
- cacheCompression: false,
288
- cacheDirectory: cache_path_1.findCachePath('babel-loader'),
287
+ cacheDirectory: cache_path_1.findCachePath('babel-dev-server-i18n'),
289
288
  cacheIdentifier: JSON.stringify({
290
- buildAngular: require('../../package.json').version,
291
289
  locale,
292
290
  translationIntegrity: localeDescription === null || localeDescription === void 0 ? void 0 : localeDescription.files.map((file) => file.integrity),
293
291
  }),
294
- sourceType: 'unambiguous',
295
- presets: [
296
- [
297
- require.resolve('../babel/presets/application'),
298
- {
299
- i18n: {
300
- locale,
301
- translation: i18n.shouldInline ? translation : undefined,
302
- missingTranslationBehavior,
303
- },
304
- diagnosticReporter: (type, message) => i18nDiagnostics.push({ type, message }),
305
- },
306
- ],
307
- ],
292
+ i18n: i18nLoaderOptions,
308
293
  },
309
294
  },
310
295
  ],
@@ -318,24 +303,5 @@ async function setupLocalize(locale, i18n, browserOptions, webpackConfig) {
318
303
  webpackConfig.module.rules = rules;
319
304
  }
320
305
  rules.push(i18nRule);
321
- // Add a plugin to inject the i18n diagnostics
322
- // tslint:disable-next-line: no-non-null-assertion
323
- webpackConfig.plugins.push({
324
- apply: (compiler) => {
325
- compiler.hooks.thisCompilation.tap('build-angular', compilation => {
326
- compilation.hooks.finishModules.tap('build-angular', () => {
327
- for (const diagnostic of i18nDiagnostics) {
328
- if (diagnostic.type === 'error') {
329
- webpack_diagnostics_1.addError(compilation, diagnostic.message);
330
- }
331
- else {
332
- webpack_diagnostics_1.addWarning(compilation, diagnostic.message);
333
- }
334
- }
335
- i18nDiagnostics.length = 0;
336
- });
337
- });
338
- },
339
- });
340
306
  }
341
307
  exports.default = architect_1.createBuilder(serveWebpackBrowser);
package/src/test-utils.js CHANGED
@@ -47,6 +47,13 @@ async function browserBuild(architect, host, target, overrides, scheduleOptions)
47
47
  const run = await architect.scheduleTarget(target, overrides, scheduleOptions);
48
48
  const output = (await run.result);
49
49
  expect(output.success).toBe(true);
50
+ if (!output.success) {
51
+ await run.stop();
52
+ return {
53
+ output,
54
+ files: {},
55
+ };
56
+ }
50
57
  expect(output.outputPaths[0]).not.toBeUndefined();
51
58
  const outputPath = core_1.normalize(output.outputPaths[0]);
52
59
  const fileNames = await host.list(outputPath).toPromise();
package/src/typings.d.ts CHANGED
@@ -5,18 +5,6 @@
5
5
  * Use of this source code is governed by an MIT-style license that can be
6
6
  * found in the LICENSE file at https://angular.io/license
7
7
  */
8
-
9
- // Workaround for https://github.com/bazelbuild/rules_nodejs/issues/1033
10
- // Alternative approach instead of https://github.com/angular/angular/pull/33226
11
- declare module '@babel/core' {
12
- export * from '@types/babel__core';
13
- }
14
- declare module '@babel/generator' {
15
- export { default } from '@types/babel__generator';
16
- }
17
- declare module '@babel/traverse' {
18
- export { default } from '@types/babel__traverse';
19
- }
20
- declare module '@babel/template' {
21
- export { default } from '@types/babel__template';
8
+ declare module '@discoveryjs/json-ext' {
9
+ export function stringifyStream(value: unknown): import('stream').Readable;
22
10
  }
@@ -23,9 +23,8 @@ var ThresholdSeverity;
23
23
  })(ThresholdSeverity = exports.ThresholdSeverity || (exports.ThresholdSeverity = {}));
24
24
  var DifferentialBuildType;
25
25
  (function (DifferentialBuildType) {
26
- // FIXME: this should match the actual file suffix and not hardcoded.
27
- DifferentialBuildType["ORIGINAL"] = "es2015";
28
- DifferentialBuildType["DOWNLEVEL"] = "es5";
26
+ DifferentialBuildType["ORIGINAL"] = "original";
27
+ DifferentialBuildType["DOWNLEVEL"] = "downlevel";
29
28
  })(DifferentialBuildType || (DifferentialBuildType = {}));
30
29
  function* calculateThresholds(budget) {
31
30
  if (budget.maximumWarning) {
@@ -161,14 +160,15 @@ class BundleCalculator extends Calculator {
161
160
  if (!budgetName) {
162
161
  return [];
163
162
  }
163
+ const buildTypeLabels = getBuildTypeLabels(this.processResults);
164
164
  // The chunk may or may not have differential builds. Compute the size for
165
165
  // each then check afterwards if they are all the same.
166
166
  const buildSizes = Object.values(DifferentialBuildType).map((buildType) => {
167
167
  const size = this.chunks
168
- .filter(chunk => chunk.names.indexOf(budgetName) !== -1)
168
+ .filter(chunk => chunk.names.includes(budgetName))
169
169
  .map(chunk => this.calculateChunkSize(chunk, buildType))
170
170
  .reduce((l, r) => l + r, 0);
171
- return { size, label: `bundle ${this.budget.name}-${buildType}` };
171
+ return { size, label: `bundle ${this.budget.name}-${buildTypeLabels[buildType]}` };
172
172
  });
173
173
  // If this bundle was not actually generated by a differential build, then
174
174
  // merge the results into a single value.
@@ -185,9 +185,10 @@ class BundleCalculator extends Calculator {
185
185
  */
186
186
  class InitialCalculator extends Calculator {
187
187
  calculate() {
188
+ const buildTypeLabels = getBuildTypeLabels(this.processResults);
188
189
  const buildSizes = Object.values(DifferentialBuildType).map((buildType) => {
189
190
  return {
190
- label: `bundle initial-${buildType}`,
191
+ label: `bundle initial-${buildTypeLabels[buildType]}`,
191
192
  size: this.chunks
192
193
  .filter(chunk => chunk.initial)
193
194
  .map(chunk => this.calculateChunkSize(chunk, buildType))
@@ -353,3 +354,17 @@ function mergeDifferentialBuildSizes(buildSizes, mergeLabel) {
353
354
  function allEquivalent(items) {
354
355
  return new Set(items).size < 2;
355
356
  }
357
+ function getBuildTypeLabels(processResults) {
358
+ var _a, _b, _c;
359
+ const fileNameSuffixRegExp = /\-(es20\d{2}|esnext)\./;
360
+ const originalFileName = (_b = (_a = processResults
361
+ .find(({ original }) => (original === null || original === void 0 ? void 0 : original.filename) && fileNameSuffixRegExp.test(original.filename))) === null || _a === void 0 ? void 0 : _a.original) === null || _b === void 0 ? void 0 : _b.filename;
362
+ let originalSuffix;
363
+ if (originalFileName) {
364
+ originalSuffix = (_c = fileNameSuffixRegExp.exec(originalFileName)) === null || _c === void 0 ? void 0 : _c[1];
365
+ }
366
+ return {
367
+ [DifferentialBuildType.DOWNLEVEL]: 'es5',
368
+ [DifferentialBuildType.ORIGINAL]: originalSuffix || 'es2015',
369
+ };
370
+ }
@@ -27,6 +27,7 @@ class CrittersExtended extends Critters {
27
27
  mergeStylesheets: false,
28
28
  preload: 'media',
29
29
  noscriptFallback: true,
30
+ inlineFonts: true,
30
31
  });
31
32
  this.optionsExtended = optionsExtended;
32
33
  this.warnings = [];
@@ -48,7 +49,7 @@ class InlineCriticalCssProcessor {
48
49
  // Clean up value from value less attributes.
49
50
  // This is caused because parse5 always requires attributes to have a string value.
50
51
  // nomodule="" defer="" -> nomodule defer.
51
- content: content.replace(/(\s[a-z]+)=""/g, '$1'),
52
+ content: content.replace(/(\s(?:defer|nomodule))=""/g, '$1'),
52
53
  errors: critters.errors,
53
54
  warnings: critters.warnings,
54
55
  };
@@ -1,3 +1,4 @@
1
+ /// <reference types="packages/angular_devkit/build_angular/src/babel-bazel" />
1
2
  /**
2
3
  * @license
3
4
  * Copyright Google Inc. All Rights Reserved.
@@ -14,12 +14,12 @@ const fs_1 = require("fs");
14
14
  const path = require("path");
15
15
  const typescript_1 = require("typescript");
16
16
  const webpack_1 = require("webpack");
17
- const webpack_sources_1 = require("webpack-sources");
18
17
  const utils_1 = require("../../utils");
19
18
  const cache_path_1 = require("../../utils/cache-path");
20
19
  const environment_options_1 = require("../../utils/environment-options");
21
20
  const find_up_1 = require("../../utils/find-up");
22
21
  const spinner_1 = require("../../utils/spinner");
22
+ const webpack_diagnostics_1 = require("../../utils/webpack-diagnostics");
23
23
  const webpack_version_1 = require("../../utils/webpack-version");
24
24
  const plugins_1 = require("../plugins");
25
25
  const helpers_1 = require("../utils/helpers");
@@ -257,9 +257,20 @@ function getCommonConfig(wco) {
257
257
  if (buildOptions.statsJson) {
258
258
  extraPlugins.push(new (class {
259
259
  apply(compiler) {
260
- compiler.hooks.emit.tap('angular-cli-stats', compilation => {
261
- const data = JSON.stringify(compilation.getStats().toJson('verbose'), undefined, 2);
262
- compilation.assets['stats.json'] = new webpack_sources_1.RawSource(data);
260
+ compiler.hooks.done.tapPromise('angular-cli-stats', async (stats) => {
261
+ const { stringifyStream } = await Promise.resolve().then(() => require('@discoveryjs/json-ext'));
262
+ const data = stats.toJson('verbose');
263
+ const statsOutputPath = path.join(stats.compilation.outputOptions.path, 'stats.json');
264
+ try {
265
+ await fs_1.promises.mkdir(path.dirname(statsOutputPath), { recursive: true });
266
+ await new Promise((resolve, reject) => stringifyStream(data)
267
+ .pipe(fs_1.createWriteStream(statsOutputPath))
268
+ .on('close', resolve)
269
+ .on('error', reject));
270
+ }
271
+ catch (error) {
272
+ webpack_diagnostics_1.addError(stats.compilation, `Unable to write stats file: ${error.message || 'unknown error'}`);
273
+ }
263
274
  });
264
275
  }
265
276
  })());
@@ -58,7 +58,7 @@ export declare class NgBuildAnalyticsPlugin {
58
58
  protected _checkTsNormalModule(module: NormalModule): void;
59
59
  protected _checkNgFactoryNormalModule(module: NormalModule): void;
60
60
  protected _collectErrors(stats: Stats): void;
61
- protected _collectBundleStats(json: any): void;
61
+ protected _collectBundleStats(compilation: compilation.Compilation): void;
62
62
  /************************************************************************************************
63
63
  * The next section is all the different Webpack hooks for this plugin.
64
64
  */
@@ -164,15 +164,15 @@ class NgBuildAnalyticsPlugin {
164
164
  }
165
165
  }
166
166
  }
167
- // We can safely disable no any here since we know the format of the JSON output from webpack.
168
- // tslint:disable-next-line:no-any
169
- _collectBundleStats(json) {
170
- json.chunks
167
+ _collectBundleStats(compilation) {
168
+ // `compilation.chunks` is a Set in Webpack 5
169
+ const chunks = Array.from(compilation.chunks);
170
+ chunks
171
171
  .filter((chunk) => chunk.rendered)
172
172
  .forEach((chunk) => {
173
- const asset = json.assets.find((x) => x.name == chunk.files[0]);
174
- const size = asset ? asset.size : 0;
175
- if (chunk.entry || chunk.initial) {
173
+ const asset = compilation.assets[chunk.files[0]];
174
+ const size = asset ? asset.size() : 0;
175
+ if (chunk.canBeInitial()) {
176
176
  this._stats.initialChunkSize += size;
177
177
  }
178
178
  else {
@@ -182,23 +182,25 @@ class NgBuildAnalyticsPlugin {
182
182
  this._stats.totalChunkCount++;
183
183
  this._stats.totalChunkSize += size;
184
184
  });
185
- json.assets
185
+ Object.entries(compilation.assets)
186
186
  // Filter out chunks. We only count assets that are not JS.
187
- .filter((a) => {
188
- return json.chunks.every((chunk) => chunk.files[0] != a.name);
187
+ .filter(([name]) => {
188
+ return chunks.every((chunk) => chunk.files[0] != name);
189
189
  })
190
- .forEach((a) => {
191
- this._stats.assetSize += (a.size || 0);
190
+ .forEach(([, asset]) => {
191
+ this._stats.assetSize += asset.size();
192
192
  this._stats.assetCount++;
193
193
  });
194
- for (const asset of json.assets) {
195
- if (asset.name == 'polyfill') {
196
- this._stats.polyfillSize += asset.size || 0;
194
+ for (const [name, asset] of Object.entries(compilation.assets)) {
195
+ if (name == 'polyfill') {
196
+ this._stats.polyfillSize += asset.size();
197
197
  }
198
198
  }
199
- for (const chunk of json.chunks) {
199
+ for (const chunk of compilation.chunks) {
200
200
  if (chunk.files[0] && chunk.files[0].endsWith('.css')) {
201
- this._stats.cssSize += chunk.size || 0;
201
+ const asset = compilation.assets[chunk.files[0]];
202
+ const size = asset ? asset.size() : 0;
203
+ this._stats.cssSize += size;
202
204
  }
203
205
  }
204
206
  }
@@ -237,7 +239,7 @@ class NgBuildAnalyticsPlugin {
237
239
  }
238
240
  _done(stats) {
239
241
  this._collectErrors(stats);
240
- this._collectBundleStats(stats.toJson());
242
+ this._collectBundleStats(stats.compilation);
241
243
  if (this._built) {
242
244
  this._reportRebuildMetrics(stats);
243
245
  }
@@ -164,10 +164,9 @@ const init = (config, emitter) => {
164
164
  let lastCompilationHash;
165
165
  const statsConfig = stats_2.getWebpackStatsConfig();
166
166
  compiler.hooks.done.tap('karma', (stats) => {
167
- if (stats.compilation.errors.length > 0) {
168
- const json = stats.toJson(config.stats);
167
+ if (stats.hasErrors()) {
169
168
  // Print compilation errors.
170
- logger.error(stats_1.statsErrorsToString(json, statsConfig));
169
+ logger.error(stats_1.statsErrorsToString(stats.compilation, statsConfig));
171
170
  lastCompilationHash = undefined;
172
171
  // Emit a failure build event if there are compilation errors.
173
172
  failureCb();