@angular-devkit/build-angular 0.803.25 → 0.803.29

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,28 +1,28 @@
1
1
  {
2
2
  "name": "@angular-devkit/build-angular",
3
- "version": "0.803.25",
3
+ "version": "0.803.29",
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.803.25",
11
- "@angular-devkit/build-optimizer": "0.803.25",
12
- "@angular-devkit/build-webpack": "0.803.25",
13
- "@angular-devkit/core": "8.3.25",
14
- "@babel/core": "7.8.3",
15
- "@babel/preset-env": "7.8.3",
16
- "@ngtools/webpack": "8.3.25",
17
- "ajv": "6.10.2",
10
+ "@angular-devkit/architect": "0.803.29",
11
+ "@angular-devkit/build-optimizer": "0.803.29",
12
+ "@angular-devkit/build-webpack": "0.803.29",
13
+ "@angular-devkit/core": "8.3.29",
14
+ "@babel/core": "7.8.7",
15
+ "@babel/preset-env": "7.8.7",
16
+ "@ngtools/webpack": "8.3.29",
17
+ "ajv": "6.12.3",
18
18
  "autoprefixer": "9.6.1",
19
- "browserslist": "4.8.6",
19
+ "browserslist": "4.10.0",
20
20
  "cacache": "12.0.2",
21
- "caniuse-lite": "1.0.30001024",
21
+ "caniuse-lite": "1.0.30001035",
22
22
  "circular-dependency-plugin": "5.2.0",
23
23
  "clean-css": "4.2.1",
24
24
  "coverage-istanbul-loader": "2.0.3",
25
- "copy-webpack-plugin": "5.1.1",
25
+ "copy-webpack-plugin": "6.0.3",
26
26
  "core-js": "3.6.4",
27
27
  "file-loader": "4.2.0",
28
28
  "find-cache-dir": "3.0.0",
@@ -55,10 +55,10 @@
55
55
  "stylus-loader": "3.0.2",
56
56
  "tree-kill": "1.2.2",
57
57
  "terser": "4.6.3",
58
- "terser-webpack-plugin": "1.4.3",
58
+ "terser-webpack-plugin": "3.0.3",
59
59
  "webpack": "4.39.2",
60
60
  "webpack-dev-middleware": "3.7.2",
61
- "webpack-dev-server": "3.9.0",
61
+ "webpack-dev-server": "3.11.0",
62
62
  "webpack-merge": "4.2.1",
63
63
  "webpack-sources": "1.4.3",
64
64
  "webpack-subresource-integrity": "1.1.0-rc.6",
@@ -141,30 +141,40 @@ function getCommonConfig(wco) {
141
141
  });
142
142
  }
143
143
  // process asset entries
144
- if (buildOptions.assets) {
144
+ if (buildOptions.assets.length) {
145
145
  const copyWebpackPluginPatterns = buildOptions.assets.map((asset) => {
146
146
  // Resolve input paths relative to workspace root and add slash at the end.
147
- asset.input = path.resolve(root, asset.input).replace(/\\/g, '/');
148
- asset.input = asset.input.endsWith('/') ? asset.input : asset.input + '/';
149
- asset.output = asset.output.endsWith('/') ? asset.output : asset.output + '/';
150
- if (asset.output.startsWith('..')) {
151
- const message = 'An asset cannot be written to a location outside of the output path.';
152
- throw new Error(message);
147
+ // tslint:disable-next-line: prefer-const
148
+ let { input, output, ignore = [], glob } = asset;
149
+ input = path.resolve(root, input).replace(/\\/g, '/');
150
+ input = input.endsWith('/') ? input : input + '/';
151
+ output = output.endsWith('/') ? output : output + '/';
152
+ if (output.startsWith('..')) {
153
+ throw new Error('An asset cannot be written to a location outside of the output path.');
153
154
  }
154
155
  return {
155
- context: asset.input,
156
+ context: input,
156
157
  // Now we remove starting slash to make Webpack place it from the output root.
157
- to: asset.output.replace(/^\//, ''),
158
- ignore: asset.ignore,
159
- from: {
160
- glob: asset.glob,
158
+ to: output.replace(/^\//, ''),
159
+ from: glob,
160
+ noErrorOnMissing: true,
161
+ globOptions: {
161
162
  dot: true,
163
+ ignore: [
164
+ '.gitkeep',
165
+ '**/.DS_Store',
166
+ '**/Thumbs.db',
167
+ // Negate patterns needs to be absolute because copy-webpack-plugin uses absolute globs which
168
+ // causes negate patterns not to match.
169
+ // See: https://github.com/webpack-contrib/copy-webpack-plugin/issues/498#issuecomment-639327909
170
+ ...ignore,
171
+ ].map(i => path.posix.join(input, i)),
162
172
  },
163
173
  };
164
174
  });
165
- const copyWebpackPluginOptions = { ignore: ['.gitkeep', '**/.DS_Store', '**/Thumbs.db'] };
166
- const copyWebpackPluginInstance = new CopyWebpackPlugin(copyWebpackPluginPatterns, copyWebpackPluginOptions);
167
- extraPlugins.push(copyWebpackPluginInstance);
175
+ extraPlugins.push(new CopyWebpackPlugin({
176
+ patterns: copyWebpackPluginPatterns,
177
+ }));
168
178
  }
169
179
  if (buildOptions.progress) {
170
180
  extraPlugins.push(new ProgressPlugin({ profile: buildOptions.verbose }));
@@ -286,11 +296,12 @@ function getCommonConfig(wco) {
286
296
  buildOptions.platform !== 'server' &&
287
297
  (!differentialLoadingNeeded || (differentialLoadingNeeded && utils_1.fullDifferential)),
288
298
  };
299
+ const globalScriptsNames = globalScriptsByBundleName.map(s => s.bundleName);
289
300
  extraMinimizers.push(new TerserPlugin({
290
301
  sourceMap: scriptsSourceMap,
291
302
  parallel: true,
292
303
  cache: true,
293
- chunkFilter: (chunk) => !globalScriptsByBundleName.some(s => s.bundleName === chunk.name),
304
+ exclude: globalScriptsNames,
294
305
  terserOptions,
295
306
  }),
296
307
  // Script bundles are fully optimized here in one step since they are never downleveled.
@@ -299,7 +310,7 @@ function getCommonConfig(wco) {
299
310
  sourceMap: scriptsSourceMap,
300
311
  parallel: true,
301
312
  cache: true,
302
- chunkFilter: (chunk) => globalScriptsByBundleName.some(s => s.bundleName === chunk.name),
313
+ include: globalScriptsNames,
303
314
  terserOptions: {
304
315
  ...terserOptions,
305
316
  compress: {
@@ -53,6 +53,16 @@ async function process(options) {
53
53
  let downlevelCode;
54
54
  let downlevelMap;
55
55
  if (downlevel) {
56
+ const { supportedBrowsers: targets = [] } = options;
57
+ // todo: revisit this in version 10, when we update our defaults browserslist
58
+ // Without this workaround bundles will not be downlevelled because Babel doesn't know handle to 'op_mini all'
59
+ // See: https://github.com/babel/babel/issues/11155
60
+ if (Array.isArray(targets) && targets.includes('op_mini all')) {
61
+ targets.push('ie_mob 11');
62
+ }
63
+ else if ('op_mini' in targets) {
64
+ targets['ie_mob'] = '11';
65
+ }
56
66
  // Downlevel the bundle
57
67
  const transformResult = await core_1.transformAsync(sourceCode, {
58
68
  filename: options.filename,
@@ -64,7 +74,7 @@ async function process(options) {
64
74
  require.resolve('@babel/preset-env'),
65
75
  {
66
76
  // browserslist-compatible query or object of minimum environment versions to support
67
- targets: options.supportedBrowsers,
77
+ targets,
68
78
  // modules aren't needed since the bundles use webpack's custom module loading
69
79
  modules: false,
70
80
  // 'transform-typeof-symbol' generates slower code
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,236 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@angular-devkit/core");
4
+ const express = require("express"); // tslint:disable-line:no-implicit-dependencies
5
+ const utils_1 = require("../utils");
6
+ // This test is excluded by default and will need to be run explicitly.
7
+ // This is because App-Shell builder uses zone.js which patched the global Promise
8
+ // Currently there is no clean way to unload zone.js which causes tests that run after
9
+ // this to be extremly flaky.
10
+ // To run this test use:
11
+ // yarn test-large --full --glob packages/angular_devkit/build_angular/test/app-shell/app-shell_spec_large_disabled.ts --ivy=true
12
+ describe('AppShell Builder', () => {
13
+ const target = { project: 'app', target: 'app-shell' };
14
+ let architect;
15
+ beforeEach(async () => {
16
+ await utils_1.host.initialize().toPromise();
17
+ architect = (await utils_1.createArchitect(utils_1.host.root())).architect;
18
+ });
19
+ afterEach(async () => utils_1.host.restore().toPromise());
20
+ const appShellRouteFiles = {
21
+ 'src/app/app-shell/app-shell.component.html': `
22
+ <p>
23
+ app-shell works!
24
+ </p>
25
+ `,
26
+ 'src/app/app-shell/app-shell.component.ts': `
27
+ import { Component, OnInit } from '@angular/core';
28
+
29
+ @Component({
30
+ selector: 'app-app-shell',
31
+ templateUrl: './app-shell.component.html',
32
+ })
33
+ export class AppShellComponent implements OnInit {
34
+
35
+ constructor() { }
36
+
37
+ ngOnInit() {
38
+ }
39
+
40
+ }
41
+ `,
42
+ 'src/app/app.module.ts': `
43
+ import { BrowserModule } from '@angular/platform-browser';
44
+ import { NgModule } from '@angular/core';
45
+
46
+ import { AppRoutingModule } from './app-routing.module';
47
+ import { AppComponent } from './app.component';
48
+ import { environment } from '../environments/environment';
49
+ import { RouterModule } from '@angular/router';
50
+
51
+ @NgModule({
52
+ declarations: [
53
+ AppComponent
54
+ ],
55
+ imports: [
56
+ BrowserModule.withServerTransition({ appId: 'serverApp' }),
57
+ AppRoutingModule,
58
+ RouterModule
59
+ ],
60
+ providers: [],
61
+ bootstrap: [AppComponent]
62
+ })
63
+ export class AppModule { }
64
+ `,
65
+ 'src/app/app.server.module.ts': `
66
+ import { NgModule } from '@angular/core';
67
+ import { ServerModule } from '@angular/platform-server';
68
+
69
+ import { AppModule } from './app.module';
70
+ import { AppComponent } from './app.component';
71
+ import { Routes, RouterModule } from '@angular/router';
72
+ import { AppShellComponent } from './app-shell/app-shell.component';
73
+
74
+ const routes: Routes = [ { path: 'shell', component: AppShellComponent }];
75
+
76
+ @NgModule({
77
+ imports: [
78
+ AppModule,
79
+ ServerModule,
80
+ RouterModule.forRoot(routes),
81
+ ],
82
+ bootstrap: [AppComponent],
83
+ declarations: [AppShellComponent],
84
+ })
85
+ export class AppServerModule {}
86
+ `,
87
+ 'src/main.ts': `
88
+ import { enableProdMode } from '@angular/core';
89
+ import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
90
+
91
+ import { AppModule } from './app/app.module';
92
+ import { environment } from './environments/environment';
93
+
94
+ if (environment.production) {
95
+ enableProdMode();
96
+ }
97
+
98
+ document.addEventListener('DOMContentLoaded', () => {
99
+ platformBrowserDynamic().bootstrapModule(AppModule)
100
+ .catch(err => console.log(err));
101
+ });
102
+ `,
103
+ 'src/app/app-routing.module.ts': `
104
+ import { NgModule } from '@angular/core';
105
+ import { Routes, RouterModule } from '@angular/router';
106
+
107
+ const routes: Routes = [];
108
+
109
+ @NgModule({
110
+ imports: [RouterModule.forRoot(routes)],
111
+ exports: [RouterModule]
112
+ })
113
+ export class AppRoutingModule { }
114
+ `,
115
+ 'src/app/app.component.html': `
116
+ <router-outlet></router-outlet>
117
+ `,
118
+ };
119
+ it('works (basic)', async () => {
120
+ utils_1.host.replaceInFile('src/app/app.module.ts', / BrowserModule/, `
121
+ BrowserModule.withServerTransition({ appId: 'some-app' })
122
+ `);
123
+ const run = await architect.scheduleTarget(target);
124
+ const output = await run.result;
125
+ await run.stop();
126
+ expect(output.success).toBe(true);
127
+ const fileName = 'dist/index.html';
128
+ const content = core_1.virtualFs.fileBufferToString(utils_1.host.scopedSync().read(core_1.normalize(fileName)));
129
+ expect(content).toMatch(/Welcome to app!/);
130
+ });
131
+ it('works with route', async () => {
132
+ utils_1.host.writeMultipleFiles(appShellRouteFiles);
133
+ const overrides = { route: 'shell' };
134
+ const run = await architect.scheduleTarget(target, overrides);
135
+ const output = await run.result;
136
+ await run.stop();
137
+ expect(output.success).toBe(true);
138
+ const fileName = 'dist/index.html';
139
+ const content = core_1.virtualFs.fileBufferToString(utils_1.host.scopedSync().read(core_1.normalize(fileName)));
140
+ expect(content).toContain('app-shell works!');
141
+ });
142
+ it('works with route and service-worker', async () => {
143
+ utils_1.host.writeMultipleFiles(appShellRouteFiles);
144
+ utils_1.host.writeMultipleFiles({
145
+ 'src/ngsw-config.json': `
146
+ {
147
+ "index": "/index.html",
148
+ "assetGroups": [{
149
+ "name": "app",
150
+ "installMode": "prefetch",
151
+ "resources": {
152
+ "files": [
153
+ "/favicon.ico",
154
+ "/index.html",
155
+ "/*.css",
156
+ "/*.js"
157
+ ]
158
+ }
159
+ }, {
160
+ "name": "assets",
161
+ "installMode": "lazy",
162
+ "updateMode": "prefetch",
163
+ "resources": {
164
+ "files": [
165
+ "/assets/**"
166
+ ]
167
+ }
168
+ }]
169
+ }
170
+ `,
171
+ 'src/app/app.module.ts': `
172
+ import { BrowserModule } from '@angular/platform-browser';
173
+ import { NgModule } from '@angular/core';
174
+
175
+ import { AppRoutingModule } from './app-routing.module';
176
+ import { AppComponent } from './app.component';
177
+ import { ServiceWorkerModule } from '@angular/service-worker';
178
+ import { environment } from '../environments/environment';
179
+ import { RouterModule } from '@angular/router';
180
+
181
+ @NgModule({
182
+ declarations: [
183
+ AppComponent
184
+ ],
185
+ imports: [
186
+ BrowserModule.withServerTransition({ appId: 'serverApp' }),
187
+ AppRoutingModule,
188
+ ServiceWorkerModule.register('/ngsw-worker.js', { enabled: environment.production }),
189
+ RouterModule
190
+ ],
191
+ providers: [],
192
+ bootstrap: [AppComponent]
193
+ })
194
+ export class AppModule { }
195
+ `,
196
+ 'e2e/app.e2e-spec.ts': `
197
+ import { browser, by, element } from 'protractor';
198
+
199
+ it('should have ngsw in normal state', () => {
200
+ browser.get('/');
201
+ // Wait for service worker to load.
202
+ browser.sleep(2000);
203
+ browser.waitForAngularEnabled(false);
204
+ browser.get('/ngsw/state');
205
+ // Should have updated, and be in normal state.
206
+ expect(element(by.css('pre')).getText()).not.toContain('Last update check: never');
207
+ expect(element(by.css('pre')).getText()).toContain('Driver state: NORMAL');
208
+ });
209
+ `,
210
+ });
211
+ // This should match the browser target prod config.
212
+ utils_1.host.replaceInFile('angular.json', '"buildOptimizer": true', '"buildOptimizer": true, "serviceWorker": true');
213
+ // We're changing the workspace file so we need to recreate the Architect instance.
214
+ architect = (await utils_1.createArchitect(utils_1.host.root())).architect;
215
+ const overrides = { route: 'shell' };
216
+ const run = await architect.scheduleTarget({ ...target, configuration: 'production' }, overrides);
217
+ const output = await run.result;
218
+ await run.stop();
219
+ expect(output.success).toBe(true);
220
+ // Make sure the index is pre-rendering the route.
221
+ const fileName = 'dist/index.html';
222
+ const content = core_1.virtualFs.fileBufferToString(utils_1.host.scopedSync().read(core_1.normalize(fileName)));
223
+ expect(content).toContain('app-shell works!');
224
+ // Serve the app using a simple static server.
225
+ const app = express();
226
+ app.use('/', express.static(core_1.getSystemPath(core_1.join(utils_1.host.root(), 'dist')) + '/'));
227
+ const server = app.listen(4200);
228
+ // Load app in protractor, then check service worker status.
229
+ const protractorRun = await architect.scheduleTarget({ project: 'app-e2e', target: 'e2e' }, { devServerTarget: undefined });
230
+ const protractorOutput = await protractorRun.result;
231
+ await protractorRun.stop();
232
+ expect(protractorOutput.success).toBe(true);
233
+ // Close the express server.
234
+ server.close();
235
+ });
236
+ });