@angular-devkit/build-angular 0.801.0-beta.3 → 0.801.2

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.
Files changed (31) hide show
  1. package/package.json +12 -13
  2. package/plugins/webpack/analytics.d.ts +2 -0
  3. package/plugins/webpack/analytics.js +25 -3
  4. package/src/angular-cli-files/models/es5-polyfills.js +1 -0
  5. package/src/angular-cli-files/models/webpack-configs/common.js +24 -29
  6. package/src/angular-cli-files/models/webpack-configs/styles.js +22 -16
  7. package/src/angular-cli-files/models/webpack-configs/utils.d.ts +3 -3
  8. package/src/angular-cli-files/models/webpack-configs/utils.js +21 -7
  9. package/src/angular-cli-files/plugins/index-html-webpack-plugin.d.ts +3 -0
  10. package/src/angular-cli-files/plugins/index-html-webpack-plugin.js +9 -4
  11. package/src/angular-cli-files/plugins/karma.js +0 -1
  12. package/src/angular-cli-files/plugins/single-test-transform.d.ts +28 -0
  13. package/src/angular-cli-files/plugins/single-test-transform.js +40 -0
  14. package/src/angular-cli-files/utilities/find-tests.d.ts +1 -0
  15. package/src/angular-cli-files/utilities/find-tests.js +55 -0
  16. package/src/angular-cli-files/utilities/index-file/augment-index-html.d.ts +3 -0
  17. package/src/angular-cli-files/utilities/index-file/augment-index-html.js +13 -6
  18. package/src/angular-cli-files/utilities/index-file/write-index-html.d.ts +3 -1
  19. package/src/angular-cli-files/utilities/index-file/write-index-html.js +6 -5
  20. package/src/angular-cli-files/utilities/package-chunk-sort.js +4 -2
  21. package/src/browser/index.js +20 -14
  22. package/src/browser/schema.d.ts +16 -0
  23. package/src/browser/schema.js +9 -0
  24. package/src/browser/schema.json +17 -1
  25. package/src/dev-server/index.js +46 -22
  26. package/src/karma/index.js +30 -2
  27. package/src/karma/schema.d.ts +13 -0
  28. package/src/karma/schema.json +14 -1
  29. package/src/utils/webpack-browser-config.js +1 -1
  30. package/test/utils.d.ts +2 -1
  31. package/test/utils.js +7 -2
package/package.json CHANGED
@@ -1,21 +1,21 @@
1
1
  {
2
2
  "name": "@angular-devkit/build-angular",
3
- "version": "0.801.0-beta.3",
3
+ "version": "0.801.2",
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.801.0-beta.3",
11
- "@angular-devkit/build-optimizer": "0.801.0-beta.3",
12
- "@angular-devkit/build-webpack": "0.801.0-beta.3",
13
- "@angular-devkit/core": "8.1.0-beta.3",
14
- "@ngtools/webpack": "8.1.0-beta.3",
10
+ "@angular-devkit/architect": "0.801.2",
11
+ "@angular-devkit/build-optimizer": "0.801.2",
12
+ "@angular-devkit/build-webpack": "0.801.2",
13
+ "@angular-devkit/core": "8.1.2",
14
+ "@ngtools/webpack": "8.1.2",
15
15
  "ajv": "6.10.0",
16
16
  "autoprefixer": "9.6.0",
17
17
  "browserslist": "4.6.3",
18
- "caniuse-lite": "1.0.30000974",
18
+ "caniuse-lite": "1.0.30000979",
19
19
  "circular-dependency-plugin": "5.0.2",
20
20
  "clean-css": "4.2.1",
21
21
  "copy-webpack-plugin": "5.0.3",
@@ -31,15 +31,15 @@
31
31
  "mini-css-extract-plugin": "0.7.0",
32
32
  "minimatch": "3.0.4",
33
33
  "parse5": "4.0.0",
34
- "open": "6.3.0",
34
+ "open": "6.4.0",
35
35
  "postcss": "7.0.17",
36
36
  "postcss-import": "12.0.1",
37
37
  "postcss-loader": "3.0.0",
38
38
  "raw-loader": "1.0.0",
39
39
  "rxjs": "6.4.0",
40
- "sass": "1.21.0",
40
+ "sass": "1.22.2",
41
41
  "sass-loader": "7.1.0",
42
- "semver": "6.1.1",
42
+ "semver": "6.2.0",
43
43
  "source-map-support": "0.5.12",
44
44
  "source-map-loader": "0.2.4",
45
45
  "speed-measure-webpack-plugin": "1.3.1",
@@ -48,7 +48,7 @@
48
48
  "stylus-loader": "3.0.2",
49
49
  "tree-kill": "1.2.1",
50
50
  "terser-webpack-plugin": "1.3.0",
51
- "webpack": "4.35.0",
51
+ "webpack": "4.35.2",
52
52
  "webpack-dev-middleware": "3.7.0",
53
53
  "webpack-dev-server": "3.7.2",
54
54
  "webpack-merge": "4.2.1",
@@ -57,7 +57,7 @@
57
57
  "worker-plugin": "3.1.0"
58
58
  },
59
59
  "peerDependencies": {
60
- "@angular/compiler-cli": ">=8.0.0-beta.0 < 9.0.0",
60
+ "@angular/compiler-cli": "^8.0.0-beta.0 || ^8.1.0-beta.0 || ^8.2.0-beta.0 || ^8.3.0-beta.0 || ^8.4.0-beta.0 || >=9.0.0-beta < 9",
61
61
  "typescript": ">=3.1 < 3.5"
62
62
  },
63
63
  "keywords": [
@@ -83,7 +83,6 @@
83
83
  "homepage": "https://github.com/angular/angular-cli",
84
84
  "husky": {
85
85
  "hooks": {
86
- "pre-commit": "lint-staged",
87
86
  "pre-push": "node ./bin/devkit-admin hooks/pre-push"
88
87
  }
89
88
  }
@@ -29,6 +29,7 @@ export declare function countOccurrences(source: string, match: string, wordBrea
29
29
  declare class AnalyticsBuildStats {
30
30
  errors: string[];
31
31
  numberOfNgOnInit: number;
32
+ numberOfComponents: number;
32
33
  initialChunkSize: number;
33
34
  totalChunkCount: number;
34
35
  totalChunkSize: number;
@@ -55,6 +56,7 @@ export declare class NgBuildAnalyticsPlugin {
55
56
  protected _reportBuildMetrics(stats: Stats): void;
56
57
  protected _reportRebuildMetrics(stats: Stats): void;
57
58
  protected _checkTsNormalModule(module: NormalModule): void;
59
+ protected _checkNgFactoryNormalModule(module: NormalModule): void;
58
60
  protected _collectErrors(stats: Stats): void;
59
61
  protected _collectBundleStats(json: any): void;
60
62
  /************************************************************************************************
@@ -56,6 +56,7 @@ class AnalyticsBuildStats {
56
56
  constructor() {
57
57
  this.errors = [];
58
58
  this.numberOfNgOnInit = 0;
59
+ this.numberOfComponents = 0;
59
60
  this.initialChunkSize = 0;
60
61
  this.totalChunkCount = 0;
61
62
  this.totalChunkSize = 0;
@@ -87,6 +88,7 @@ class NgBuildAnalyticsPlugin {
87
88
  const metrics = [];
88
89
  metrics[core_1.analytics.NgCliAnalyticsMetrics.BuildTime] = (endTime - startTime);
89
90
  metrics[core_1.analytics.NgCliAnalyticsMetrics.NgOnInitCount] = this._stats.numberOfNgOnInit;
91
+ metrics[core_1.analytics.NgCliAnalyticsMetrics.NgComponentCount] = this._stats.numberOfComponents;
90
92
  metrics[core_1.analytics.NgCliAnalyticsMetrics.InitialChunkSize] = this._stats.initialChunkSize;
91
93
  metrics[core_1.analytics.NgCliAnalyticsMetrics.TotalChunkCount] = this._stats.totalChunkCount;
92
94
  metrics[core_1.analytics.NgCliAnalyticsMetrics.TotalChunkSize] = this._stats.totalChunkSize;
@@ -100,8 +102,10 @@ class NgBuildAnalyticsPlugin {
100
102
  }
101
103
  _getDimensions(stats) {
102
104
  const dimensions = [];
103
- // Adding commas before and after so the regex are easier to define.
104
- dimensions[core_1.analytics.NgCliAnalyticsDimensions.BuildErrors] = `,${this._stats.errors.join()},`;
105
+ if (this._stats.errors.length) {
106
+ // Adding commas before and after so the regex are easier to define filters.
107
+ dimensions[core_1.analytics.NgCliAnalyticsDimensions.BuildErrors] = `,${this._stats.errors.join()},`;
108
+ }
105
109
  return dimensions;
106
110
  }
107
111
  _reportBuildMetrics(stats) {
@@ -116,10 +120,25 @@ class NgBuildAnalyticsPlugin {
116
120
  }
117
121
  _checkTsNormalModule(module) {
118
122
  if (module._source) {
123
+ // PLEASE REMEMBER:
119
124
  // We're dealing with ES5 _or_ ES2015 JavaScript at this point (we don't know for sure).
120
125
  // Just count the ngOnInit occurences. Comments/Strings/calls occurences should be sparse
121
126
  // so we just consider them within the margin of error. We do break on word break though.
122
127
  this._stats.numberOfNgOnInit += countOccurrences(module._source.source(), 'ngOnInit', true);
128
+ // Count the number of `Component({` strings (case sensitive), which happens in __decorate().
129
+ // This does not include View Engine AOT compilation, we use the ngfactory for it.
130
+ this._stats.numberOfComponents += countOccurrences(module._source.source(), ' Component({');
131
+ // For Ivy we just count ngComponentDef.
132
+ this._stats.numberOfComponents += countOccurrences(module._source.source(), 'ngComponentDef', true);
133
+ }
134
+ }
135
+ _checkNgFactoryNormalModule(module) {
136
+ if (module._source) {
137
+ // PLEASE REMEMBER:
138
+ // We're dealing with ES5 _or_ ES2015 JavaScript at this point (we don't know for sure).
139
+ // Count the number of `.ɵccf(` strings (case sensitive). They're calls to components
140
+ // factories.
141
+ this._stats.numberOfComponents += countOccurrences(module._source.source(), '.ɵccf(');
123
142
  }
124
143
  }
125
144
  _collectErrors(stats) {
@@ -198,9 +217,12 @@ class NgBuildAnalyticsPlugin {
198
217
  return;
199
218
  }
200
219
  // Check that it's a source file from the project.
201
- if (module.constructor === NormalModule && module.resource.endsWith('.ts')) {
220
+ if (module.resource.endsWith('.ts')) {
202
221
  this._checkTsNormalModule(module);
203
222
  }
223
+ else if (module.resource.endsWith('.ngfactory.js')) {
224
+ this._checkNgFactoryNormalModule(module);
225
+ }
204
226
  }
205
227
  _compilation(compiler, compilation) {
206
228
  this._reset();
@@ -8,6 +8,7 @@
8
8
 
9
9
  // ES2015 symbol capabilities
10
10
  import 'core-js/modules/es.symbol';
11
+ import 'core-js/modules/es.symbol.iterator';
11
12
 
12
13
  // ES2015 function capabilities
13
14
  import 'core-js/modules/es.function.bind';
@@ -48,8 +48,7 @@ function getCommonConfig(wco) {
48
48
  const buildBrowserFeatures = new build_browser_features_1.BuildBrowserFeatures(projectRoot, tsConfig.options.target || typescript_1.ScriptTarget.ES5);
49
49
  if ((buildOptions.scriptTargetOverride || tsConfig.options.target) === typescript_1.ScriptTarget.ES5) {
50
50
  if (buildOptions.es5BrowserSupport ||
51
- (buildOptions.es5BrowserSupport === undefined &&
52
- buildBrowserFeatures.isEs5SupportNeeded())) {
51
+ (buildOptions.es5BrowserSupport === undefined && buildBrowserFeatures.isEs5SupportNeeded())) {
53
52
  // The nomodule polyfill needs to be inject prior to any script and be
54
53
  // outside of webpack compilation because otherwise webpack will cause the
55
54
  // script to be wrapped in window["webpackJsonp"] which causes this to fail.
@@ -95,15 +94,14 @@ function getCommonConfig(wco) {
95
94
  const hashFormat = utils_1.getOutputHashFormat(buildOptions.outputHashing || 'none');
96
95
  // process global scripts
97
96
  if (buildOptions.scripts.length > 0) {
98
- const globalScriptsByBundleName = utils_1.normalizeExtraEntryPoints(buildOptions.scripts, 'scripts')
99
- .reduce((prev, curr) => {
97
+ const globalScriptsByBundleName = utils_1.normalizeExtraEntryPoints(buildOptions.scripts, 'scripts').reduce((prev, curr) => {
100
98
  const bundleName = curr.bundleName;
101
99
  const resolvedPath = path.resolve(root, curr.input);
102
- const existingEntry = prev.find((el) => el.bundleName === bundleName);
100
+ const existingEntry = prev.find(el => el.bundleName === bundleName);
103
101
  if (existingEntry) {
104
- if (existingEntry.lazy && !curr.lazy) {
102
+ if (existingEntry.inject && !curr.inject) {
105
103
  // All entries have to be lazy for the bundle to be lazy.
106
- throw new Error(`The ${curr.bundleName} bundle is mixing lazy and non-lazy scripts.`);
104
+ throw new Error(`The ${curr.bundleName} bundle is mixing injected and non-injected scripts.`);
107
105
  }
108
106
  existingEntry.paths.push(resolvedPath);
109
107
  }
@@ -111,15 +109,15 @@ function getCommonConfig(wco) {
111
109
  prev.push({
112
110
  bundleName,
113
111
  paths: [resolvedPath],
114
- lazy: curr.lazy || false,
112
+ inject: curr.inject,
115
113
  });
116
114
  }
117
115
  return prev;
118
116
  }, []);
119
117
  // Add a new asset for each entry.
120
- globalScriptsByBundleName.forEach((script) => {
118
+ globalScriptsByBundleName.forEach(script => {
121
119
  // Lazy scripts don't get a hash, otherwise they can't be loaded by name.
122
- const hash = script.lazy ? '' : hashFormat.script;
120
+ const hash = script.inject ? hashFormat.script : '';
123
121
  const bundleName = script.bundleName;
124
122
  extraPlugins.push(new scripts_webpack_plugin_1.ScriptsWebpackPlugin({
125
123
  name: bundleName,
@@ -165,14 +163,14 @@ function getCommonConfig(wco) {
165
163
  }));
166
164
  }
167
165
  if (buildOptions.statsJson) {
168
- extraPlugins.push(new class {
166
+ extraPlugins.push(new (class {
169
167
  apply(compiler) {
170
168
  compiler.hooks.emit.tap('angular-cli-stats', compilation => {
171
169
  const data = JSON.stringify(compilation.getStats().toJson('verbose'));
172
170
  compilation.assets[`stats${targetInFileName}.json`] = new webpack_sources_1.RawSource(data);
173
171
  });
174
172
  }
175
- });
173
+ })());
176
174
  }
177
175
  if (buildOptions.namedChunks) {
178
176
  extraPlugins.push(new named_chunks_plugin_1.NamedLazyChunksPlugin());
@@ -219,7 +217,7 @@ function getCommonConfig(wco) {
219
217
  extraMinimizers.push(new cleancss_webpack_plugin_1.CleanCssWebpackPlugin({
220
218
  sourceMap: stylesSourceMap,
221
219
  // component styles retain their original file name
222
- test: (file) => /\.(?:css|scss|sass|less|styl)$/.test(file),
220
+ test: file => /\.(?:css|scss|sass|less|styl)$/.test(file),
223
221
  }));
224
222
  }
225
223
  if (scriptsOptimization) {
@@ -249,15 +247,17 @@ function getCommonConfig(wco) {
249
247
  },
250
248
  // On server, we don't want to compress anything. We still set the ngDevMode = false for it
251
249
  // to remove dev code, and ngI18nClosureMode to remove Closure compiler i18n code
252
- compress: (buildOptions.platform == 'server' ? {
253
- global_defs: angularGlobalDefinitions,
254
- } : {
255
- pure_getters: buildOptions.buildOptimizer,
256
- // PURE comments work best with 3 passes.
257
- // See https://github.com/webpack/webpack/issues/2899#issuecomment-317425926.
258
- passes: buildOptions.buildOptimizer ? 3 : 1,
259
- global_defs: angularGlobalDefinitions,
260
- }),
250
+ compress: buildOptions.platform == 'server'
251
+ ? {
252
+ global_defs: angularGlobalDefinitions,
253
+ }
254
+ : {
255
+ pure_getters: buildOptions.buildOptimizer,
256
+ // PURE comments work best with 3 passes.
257
+ // See https://github.com/webpack/webpack/issues/2899#issuecomment-317425926.
258
+ passes: buildOptions.buildOptimizer ? 3 : 1,
259
+ global_defs: angularGlobalDefinitions,
260
+ },
261
261
  // We also want to avoid mangling on server.
262
262
  ...(buildOptions.platform == 'server' ? { mangle: false } : {}),
263
263
  };
@@ -277,18 +277,13 @@ function getCommonConfig(wco) {
277
277
  `);
278
278
  }
279
279
  return {
280
- mode: scriptsOptimization || stylesOptimization
281
- ? 'production'
282
- : 'development',
280
+ mode: scriptsOptimization || stylesOptimization ? 'production' : 'development',
283
281
  devtool: false,
284
282
  profile: buildOptions.statsJson,
285
283
  resolve: {
286
284
  extensions: ['.ts', '.tsx', '.mjs', '.js'],
287
285
  symlinks: !buildOptions.preserveSymlinks,
288
- modules: [
289
- wco.tsConfig.options.baseUrl || projectRoot,
290
- 'node_modules',
291
- ],
286
+ modules: [wco.tsConfig.options.baseUrl || projectRoot, 'node_modules'],
292
287
  alias,
293
288
  },
294
289
  resolveLoader: {
@@ -26,6 +26,7 @@ const postcssImports = require('postcss-import');
26
26
  * require('node-sass')
27
27
  * require('sass-loader')
28
28
  */
29
+ // tslint:disable-next-line:no-big-function
29
30
  function getStylesConfig(wco) {
30
31
  const { root, buildOptions } = wco;
31
32
  const entryPoints = {};
@@ -37,7 +38,7 @@ function getStylesConfig(wco) {
37
38
  const postcssPluginCreator = function (loader) {
38
39
  return [
39
40
  postcssImports({
40
- resolve: (url) => url.startsWith('~') ? url.substr(1) : url,
41
+ resolve: (url) => (url.startsWith('~') ? url.substr(1) : url),
41
42
  load: (filename) => {
42
43
  return new Promise((resolve, reject) => {
43
44
  loader.fs.readFile(filename, (err, data) => {
@@ -65,9 +66,9 @@ function getStylesConfig(wco) {
65
66
  // use includePaths from appConfig
66
67
  const includePaths = [];
67
68
  let lessPathOptions = {};
68
- if (buildOptions.stylePreprocessorOptions
69
- && buildOptions.stylePreprocessorOptions.includePaths
70
- && buildOptions.stylePreprocessorOptions.includePaths.length > 0) {
69
+ if (buildOptions.stylePreprocessorOptions &&
70
+ buildOptions.stylePreprocessorOptions.includePaths &&
71
+ buildOptions.stylePreprocessorOptions.includePaths.length > 0) {
71
72
  buildOptions.stylePreprocessorOptions.includePaths.forEach((includePath) => includePaths.push(path.resolve(root, includePath)));
72
73
  lessPathOptions = {
73
74
  paths: includePaths,
@@ -85,8 +86,8 @@ function getStylesConfig(wco) {
85
86
  else {
86
87
  entryPoints[style.bundleName] = [resolvedPath];
87
88
  }
88
- // Add lazy styles to the list.
89
- if (style.lazy) {
89
+ // Add non injected styles to the list.
90
+ if (!style.inject) {
90
91
  chunkNames.push(style.bundleName);
91
92
  }
92
93
  // Add global css paths.
@@ -116,7 +117,8 @@ function getStylesConfig(wco) {
116
117
  { test: /\.css$/, use: [] },
117
118
  {
118
119
  test: /\.scss$|\.sass$/,
119
- use: [{
120
+ use: [
121
+ {
120
122
  loader: 'sass-loader',
121
123
  options: {
122
124
  implementation: sassImplementation,
@@ -126,28 +128,33 @@ function getStylesConfig(wco) {
126
128
  precision: 8,
127
129
  includePaths,
128
130
  },
129
- }],
131
+ },
132
+ ],
130
133
  },
131
134
  {
132
135
  test: /\.less$/,
133
- use: [{
136
+ use: [
137
+ {
134
138
  loader: 'less-loader',
135
139
  options: {
136
140
  sourceMap: cssSourceMap,
137
141
  javascriptEnabled: true,
138
142
  ...lessPathOptions,
139
143
  },
140
- }],
144
+ },
145
+ ],
141
146
  },
142
147
  {
143
148
  test: /\.styl$/,
144
- use: [{
149
+ use: [
150
+ {
145
151
  loader: 'stylus-loader',
146
152
  options: {
147
153
  sourceMap: cssSourceMap,
148
154
  paths: includePaths,
149
155
  },
150
- }],
156
+ },
157
+ ],
151
158
  },
152
159
  ];
153
160
  // load component css as raw strings
@@ -181,10 +188,9 @@ function getStylesConfig(wco) {
181
188
  options: {
182
189
  ident: buildOptions.extractCss ? 'extracted' : 'embedded',
183
190
  plugins: postcssPluginCreator,
184
- sourceMap: cssSourceMap
185
- && !buildOptions.extractCss
186
- && !buildOptions.sourceMap.hidden
187
- ? 'inline' : cssSourceMap,
191
+ sourceMap: cssSourceMap && !buildOptions.extractCss && !buildOptions.sourceMap.hidden
192
+ ? 'inline'
193
+ : cssSourceMap,
188
194
  },
189
195
  },
190
196
  ...use,
@@ -15,9 +15,8 @@ export interface HashFormat {
15
15
  script: string;
16
16
  }
17
17
  export declare function getOutputHashFormat(option: string, length?: number): HashFormat;
18
- export declare type NormalizedEntryPoint = ExtraEntryPointClass & {
19
- bundleName: string;
20
- };
18
+ declare type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
19
+ export declare type NormalizedEntryPoint = Required<Omit<ExtraEntryPointClass, 'lazy'>>;
21
20
  export declare function normalizeExtraEntryPoints(extraEntryPoints: ExtraEntryPoint[], defaultBundleName: string): NormalizedEntryPoint[];
22
21
  export declare function getSourceMapDevTool(scriptsSourceMap: boolean, stylesSourceMap: boolean, hiddenSourceMap?: boolean, inlineSourceMap?: boolean): SourceMapDevToolPlugin;
23
22
  /**
@@ -25,3 +24,4 @@ export declare function getSourceMapDevTool(scriptsSourceMap: boolean, stylesSou
25
24
  */
26
25
  export declare function getEsVersionForFileName(scriptTargetOverride: ScriptTarget | undefined, esVersionInFileName?: boolean): string;
27
26
  export declare function isPolyfillsEntry(name: string): boolean;
27
+ export {};
@@ -17,8 +17,18 @@ function getOutputHashFormat(option, length = 20) {
17
17
  const hashFormats = {
18
18
  none: { chunk: '', extract: '', file: '', script: '' },
19
19
  media: { chunk: '', extract: '', file: `.[hash:${length}]`, script: '' },
20
- bundles: { chunk: `.[chunkhash:${length}]`, extract: `.[contenthash:${length}]`, file: '', script: `.[hash:${length}]` },
21
- all: { chunk: `.[chunkhash:${length}]`, extract: `.[contenthash:${length}]`, file: `.[hash:${length}]`, script: `.[hash:${length}]` },
20
+ bundles: {
21
+ chunk: `.[chunkhash:${length}]`,
22
+ extract: `.[contenthash:${length}]`,
23
+ file: '',
24
+ script: `.[hash:${length}]`,
25
+ },
26
+ all: {
27
+ chunk: `.[chunkhash:${length}]`,
28
+ extract: `.[contenthash:${length}]`,
29
+ file: `.[hash:${length}]`,
30
+ script: `.[hash:${length}]`,
31
+ },
22
32
  };
23
33
  /* tslint:enable:max-line-length */
24
34
  return hashFormats[option] || hashFormats['none'];
@@ -28,21 +38,23 @@ function normalizeExtraEntryPoints(extraEntryPoints, defaultBundleName) {
28
38
  return extraEntryPoints.map(entry => {
29
39
  let normalizedEntry;
30
40
  if (typeof entry === 'string') {
31
- normalizedEntry = { input: entry, lazy: false, bundleName: defaultBundleName };
41
+ normalizedEntry = { input: entry, inject: true, bundleName: defaultBundleName };
32
42
  }
33
43
  else {
44
+ const { lazy, inject = true, ...newEntry } = entry;
45
+ const injectNormalized = entry.lazy !== undefined ? !entry.lazy : inject;
34
46
  let bundleName;
35
47
  if (entry.bundleName) {
36
48
  bundleName = entry.bundleName;
37
49
  }
38
- else if (entry.lazy) {
50
+ else if (!injectNormalized) {
39
51
  // Lazy entry points use the file name as bundle name.
40
52
  bundleName = core_1.basename(core_1.normalize(entry.input.replace(/\.(js|css|scss|sass|less|styl)$/i, '')));
41
53
  }
42
54
  else {
43
55
  bundleName = defaultBundleName;
44
56
  }
45
- normalizedEntry = { ...entry, bundleName };
57
+ normalizedEntry = { ...newEntry, inject: injectNormalized, bundleName };
46
58
  }
47
59
  return normalizedEntry;
48
60
  });
@@ -59,6 +71,7 @@ function getSourceMapDevTool(scriptsSourceMap, stylesSourceMap, hiddenSourceMap
59
71
  return new webpack_1.SourceMapDevToolPlugin({
60
72
  filename: inlineSourceMap ? undefined : '[file].map',
61
73
  include,
74
+ moduleFilenameTemplate: '[namespace]/[resource-path]',
62
75
  append: hiddenSourceMap ? false : undefined,
63
76
  });
64
77
  }
@@ -67,8 +80,9 @@ exports.getSourceMapDevTool = getSourceMapDevTool;
67
80
  * Returns an ES version file suffix to differentiate between various builds.
68
81
  */
69
82
  function getEsVersionForFileName(scriptTargetOverride, esVersionInFileName = false) {
70
- return scriptTargetOverride && esVersionInFileName ?
71
- '-' + typescript_1.ScriptTarget[scriptTargetOverride].toLowerCase() : '';
83
+ return scriptTargetOverride && esVersionInFileName
84
+ ? '-' + typescript_1.ScriptTarget[scriptTargetOverride].toLowerCase()
85
+ : '';
72
86
  }
73
87
  exports.getEsVersionForFileName = getEsVersionForFileName;
74
88
  function isPolyfillsEntry(name) {
@@ -1,4 +1,5 @@
1
1
  import { Compiler } from 'webpack';
2
+ import { CrossOriginValue } from '../utilities/index-file/augment-index-html';
2
3
  import { IndexHtmlTransform } from '../utilities/index-file/write-index-html';
3
4
  export interface IndexHtmlWebpackPluginOptions {
4
5
  input: string;
@@ -8,7 +9,9 @@ export interface IndexHtmlWebpackPluginOptions {
8
9
  deployUrl?: string;
9
10
  sri: boolean;
10
11
  noModuleEntrypoints: string[];
12
+ moduleEntrypoints: string[];
11
13
  postTransform?: IndexHtmlTransform;
14
+ crossOrigin?: CrossOriginValue;
12
15
  }
13
16
  export declare class IndexHtmlWebpackPlugin {
14
17
  private _options;
@@ -29,6 +29,7 @@ class IndexHtmlWebpackPlugin {
29
29
  output: 'index.html',
30
30
  entrypoints: ['polyfills', 'main'],
31
31
  noModuleEntrypoints: [],
32
+ moduleEntrypoints: [],
32
33
  sri: false,
33
34
  ...options,
34
35
  };
@@ -37,14 +38,13 @@ class IndexHtmlWebpackPlugin {
37
38
  compiler.hooks.emit.tapPromise('index-html-webpack-plugin', async (compilation) => {
38
39
  // Get input html file
39
40
  const inputContent = await readFile(this._options.input, compilation);
40
- compilation
41
- .fileDependencies.add(this._options.input);
41
+ compilation.fileDependencies.add(this._options.input);
42
42
  // Get all files for selected entrypoints
43
43
  const files = [];
44
44
  const noModuleFiles = [];
45
+ const moduleFiles = [];
45
46
  for (const [entryName, entrypoint] of compilation.entrypoints) {
46
- const entryFiles = (entrypoint && entrypoint.getFiles() || [])
47
- .map((f) => ({
47
+ const entryFiles = ((entrypoint && entrypoint.getFiles()) || []).map((f) => ({
48
48
  name: entryName,
49
49
  file: f,
50
50
  extension: path.extname(f),
@@ -52,6 +52,9 @@ class IndexHtmlWebpackPlugin {
52
52
  if (this._options.noModuleEntrypoints.includes(entryName)) {
53
53
  noModuleFiles.push(...entryFiles);
54
54
  }
55
+ else if (this._options.moduleEntrypoints.includes(entryName)) {
56
+ moduleFiles.push(...entryFiles);
57
+ }
55
58
  else {
56
59
  files.push(...entryFiles);
57
60
  }
@@ -63,9 +66,11 @@ class IndexHtmlWebpackPlugin {
63
66
  baseHref: this._options.baseHref,
64
67
  deployUrl: this._options.deployUrl,
65
68
  sri: this._options.sri,
69
+ crossOrigin: this._options.crossOrigin,
66
70
  files,
67
71
  noModuleFiles,
68
72
  loadOutputFile,
73
+ moduleFiles,
69
74
  entrypoints: this._options.entrypoints,
70
75
  });
71
76
  if (this._options.postTransform) {
@@ -125,7 +125,6 @@ const init = (config, emitter, customFileHandlers) => {
125
125
  // Files need to be served from a custom path for Karma.
126
126
  webpackConfig.output.path = '/_karma_webpack_/';
127
127
  webpackConfig.output.publicPath = '/_karma_webpack_/';
128
- webpackConfig.output.devtoolModuleFilenameTemplate = '[namespace]/[resource-path]?[loaders]';
129
128
  let compiler;
130
129
  try {
131
130
  compiler = webpack(webpackConfig);
@@ -0,0 +1,28 @@
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
+ import { logging } from '@angular-devkit/core';
9
+ import { loader } from 'webpack';
10
+ export interface SingleTestTransformLoaderOptions {
11
+ files: string[];
12
+ logger: logging.Logger;
13
+ }
14
+ export declare const SingleTestTransformLoader: string;
15
+ /**
16
+ * This loader transforms the default test file to only run tests
17
+ * for some specs instead of all specs.
18
+ * It works by replacing the known content of the auto-generated test file:
19
+ * const context = require.context('./', true, /\.spec\.ts$/);
20
+ * context.keys().map(context);
21
+ * with:
22
+ * const context = { keys: () => ({ map: (_a) => { } }) };
23
+ * context.keys().map(context);
24
+ * So that it does nothing.
25
+ * Then it adds import statements for each file in the files options
26
+ * array to import them directly, and thus run the tests there.
27
+ */
28
+ export default function loader(this: loader.LoaderContext, source: string): string;
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const loader_utils_1 = require("loader-utils");
4
+ const path_1 = require("path");
5
+ exports.SingleTestTransformLoader = require.resolve(path_1.join(__dirname, 'single-test-transform'));
6
+ /**
7
+ * This loader transforms the default test file to only run tests
8
+ * for some specs instead of all specs.
9
+ * It works by replacing the known content of the auto-generated test file:
10
+ * const context = require.context('./', true, /\.spec\.ts$/);
11
+ * context.keys().map(context);
12
+ * with:
13
+ * const context = { keys: () => ({ map: (_a) => { } }) };
14
+ * context.keys().map(context);
15
+ * So that it does nothing.
16
+ * Then it adds import statements for each file in the files options
17
+ * array to import them directly, and thus run the tests there.
18
+ */
19
+ function loader(source) {
20
+ const options = loader_utils_1.getOptions(this);
21
+ const lineSeparator = process.platform === 'win32' ? '\r\n' : '\n';
22
+ const targettedImports = options.files
23
+ .map(path => `require('./${path.replace('.' + path_1.extname(path), '')}');`)
24
+ .join(lineSeparator);
25
+ // TODO: maybe a documented 'marker/comment' inside test.ts would be nicer?
26
+ const regex = /require\.context\(.*/;
27
+ // signal the user that expected content is not present
28
+ if (!regex.test(source)) {
29
+ const message = [
30
+ `The 'include' option requires that the 'main' file for tests include the line below:`,
31
+ `const context = require.context('./', true, /\.spec\.ts$/);`,
32
+ `Arguments passed to require.context are not strict and can be changed`,
33
+ ];
34
+ options.logger.error(message.join(lineSeparator));
35
+ }
36
+ const mockedRequireContext = '{ keys: () => ({ map: (_a) => { } }) };' + lineSeparator;
37
+ source = source.replace(regex, mockedRequireContext + targettedImports);
38
+ return source;
39
+ }
40
+ exports.default = loader;
@@ -0,0 +1 @@
1
+ export declare function findTests(patterns: string[], cwd: string, workspaceRoot: string): string[];