Skip to content

Commit 82c94f4

Browse files
committed
Fix e2e AOT serving
1 parent f288b47 commit 82c94f4

File tree

3 files changed

+61
-54
lines changed

3 files changed

+61
-54
lines changed

src/e2e-app/tsconfig-build.json

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,27 @@
1515
"moduleResolution": "node",
1616
"noEmitOnError": true,
1717
"noImplicitAny": true,
18-
"rootDir": ".",
19-
"outDir": ".",
18+
"rootDirs": [
19+
"../..",
20+
"./"
21+
],
22+
"outDir": "../../dist/",
2023
"sourceMap": true,
2124
"target": "es5",
2225
"typeRoots": [
2326
"../../node_modules/@types/!(node)"
2427
],
2528
"baseUrl": ".",
2629
"paths": {
27-
"@angular/cdk/*": ["./cdk/*"],
28-
"@angular/material": ["./material"],
29-
"@angular/material/*": ["./material/*"],
30-
"@angular/material-experimental/*": ["./material-experimental/*"],
31-
"@angular/material-experimental": ["./material-experimental/"],
32-
"@angular/cdk-experimental/*": ["./cdk-experimental/*"],
33-
"@angular/cdk-experimental": ["./cdk-experimental/"],
34-
"@angular/material-moment-adapter": ["./material-moment-adapter"],
35-
"@angular/material-examples": ["./material-examples"]
30+
"@angular/cdk/*": ["../../dist/releases/cdk/*"],
31+
"@angular/material": ["../../dist/releases/material"],
32+
"@angular/material/*": ["../../dist/releases/material/*"],
33+
"@angular/material-experimental/*": ["../../dist/releases/material-experimental/*"],
34+
"@angular/material-experimental": ["../../dist/releases/material-experimental/"],
35+
"@angular/cdk-experimental/*": ["../../dist/releases/cdk-experimental/*"],
36+
"@angular/cdk-experimental": ["../../dist/releases/cdk-experimental/"],
37+
"@angular/material-moment-adapter": ["../../dist/releases/material-moment-adapter"],
38+
"@angular/material-examples": ["../../dist/releases/material-examples"]
3639
}
3740
},
3841
"files": [
@@ -42,7 +45,7 @@
4245
"./system-config.ts"
4346
],
4447
"angularCompilerOptions": {
45-
"skipMetadataEmit": true,
46-
"fullTemplateTypeCheck": true
48+
"fullTemplateTypeCheck": true,
49+
"enableResourceInlining": true
4750
}
4851
}

tools/gulp/tasks/e2e.ts

Lines changed: 29 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,24 @@
11
import {task} from 'gulp';
2-
import {join} from 'path';
3-
import {ngcBuildTask, copyTask, execNodeTask, serverTask} from '../util/task_helpers';
4-
import {copySync} from 'fs-extra';
52
import {buildConfig, sequenceTask, triggerLivereload, watchFiles} from 'material2-build-tools';
3+
import {join} from 'path';
4+
import {copyTask, execNodeTask, ngcBuildTask, serverTask} from '../util/task_helpers';
65

76
// There are no type definitions available for these imports.
87
const gulpConnect = require('gulp-connect');
98

109
const {outputDir, packagesDir, projectDir} = buildConfig;
1110

12-
/** Path to the directory where all releases are created. */
13-
const releasesDir = join(outputDir, 'releases');
14-
1511
const appDir = join(packagesDir, 'e2e-app');
1612
const e2eTestDir = join(projectDir, 'e2e');
17-
const outDir = join(outputDir, 'packages', 'e2e-app');
1813

19-
const PROTRACTOR_CONFIG_PATH = join(projectDir, 'test/protractor.conf.js');
20-
const tsconfigPath = join(outDir, 'tsconfig-build.json');
14+
/**
15+
* The output of the e2e app will preserve the directory structure because otherwise NGC is not
16+
* able to generate factory files for the release output and node modules.
17+
*/
18+
const outDir = join(outputDir, 'src/e2e-app');
2119

22-
/** Glob that matches all files that need to be copied to the output folder. */
23-
const assetsGlob = join(appDir, '**/*.+(html|css|json|ts)');
20+
const PROTRACTOR_CONFIG_PATH = join(projectDir, 'test/protractor.conf.js');
21+
const tsconfigPath = join(appDir, 'tsconfig-build.json');
2422

2523
/** Builds and serves the e2e-app and runs protractor once the e2e-app is ready. */
2624
task('e2e', sequenceTask(
@@ -68,12 +66,11 @@ task('e2e-app:build', sequenceTask(
6866
'material-moment-adapter:build-release',
6967
'material-examples:build-release'
7068
],
71-
['e2e-app:copy-release', 'e2e-app:copy-assets'],
72-
'e2e-app:build-ts'
69+
['e2e-app:copy-index-html', 'e2e-app:build-ts']
7370
));
7471

75-
/** Task that copies all required assets to the output folder. */
76-
task('e2e-app:copy-assets', copyTask(assetsGlob, outDir));
72+
/** Task that copies the e2e-app index HTML file to the output. */
73+
task('e2e-app:copy-index-html', copyTask(join(appDir, 'index.html'), outDir));
7774

7875
/** Task that builds the TypeScript sources. Those are compiled inside of the dist folder. */
7976
task('e2e-app:build-ts', ngcBuildTask(tsconfigPath));
@@ -92,8 +89,23 @@ task(':test:protractor:setup', execNodeTask(
9289
/** Runs protractor tests (assumes that server is already running. */
9390
task(':test:protractor', execNodeTask('protractor', [PROTRACTOR_CONFIG_PATH]));
9491

95-
/** Starts up the e2e app server. */
96-
task(':serve:e2eapp', serverTask(outDir, false));
92+
/** Starts up the e2e app server and rewrites the HTTP requests to properly work with AOT. */
93+
task(':serve:e2eapp', serverTask(outDir, false, [
94+
// Rewrite each request for .ngfactory files which are outside of the e2e-app to the **actual**
95+
// path. This is necessary because NGC cannot generate factory files for the node modules
96+
// and release output. If we work around it by adding multiple root directories, the directory
97+
// structure would be messed up, so we need to go this way for now (until Ivy).
98+
{ from: '^/((?:dist|node_modules)/.*\.ngfactory\.js)$', to: '/dist/$1' },
99+
// Rewrite the node_modules/ and dist/ folder to the real paths. Otherwise we would need
100+
// to copy the required modules to the serve output. If dist/ is explicitly requested, we
101+
// should redirect to the actual dist path because by default we fall back to the e2e output.
102+
{ from: '^/node_modules/(.*)$', to: '/node_modules/$1' },
103+
{ from: '^/dist/(.*)$', to: '/dist/$1' },
104+
// Rewrite every path that doesn't point to a specific file to the e2e output.
105+
// This is necessary for Angular's routing using the HTML5 History API.
106+
{ from: '^/[^.]+$', to: `/dist/src/e2e-app/index.html`},
107+
{ from: '^(.*)$', to: `/dist/src/e2e-app/$1` },
108+
]));
97109

98110
/** Terminates the e2e app server */
99111
task(':serve:e2eapp:stop', gulpConnect.serverClose);
@@ -106,14 +118,3 @@ task('serve:e2eapp', sequenceTask('e2e-app:build', ':serve:e2eapp'));
106118
* This should only be used when running e2e tests locally.
107119
*/
108120
task('serve:e2eapp:watch', ['serve:e2eapp', 'material:watch', ':watch:e2eapp']);
109-
110-
// As a workaround for https://github.com/angular/angular/issues/12249, we need to
111-
// copy the Material and CDK ESM output inside of the demo-app output.
112-
task('e2e-app:copy-release', () => {
113-
copySync(join(releasesDir, 'cdk'), join(outDir, 'cdk'));
114-
copySync(join(releasesDir, 'material'), join(outDir, 'material'));
115-
copySync(join(releasesDir, 'cdk-experimental'), join(outDir, 'cdk-experimental'));
116-
copySync(join(releasesDir, 'material-experimental'), join(outDir, 'material-experimental'));
117-
copySync(join(releasesDir, 'material-examples'), join(outDir, 'material-examples'));
118-
copySync(join(releasesDir, 'material-moment-adapter'), join(outDir, 'material-moment-adapter'));
119-
});

tools/gulp/util/task_helpers.ts

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -126,9 +126,22 @@ export function cleanTask(glob: string) {
126126
* Create a task that serves a given directory in the project.
127127
* The server rewrites all node_module/ or dist/ requests to the correct directory.
128128
*/
129-
export function serverTask(packagePath: string, livereload = true) {
130-
// The http-rewrite-middlware only supports relative paths as rewrite destinations.
129+
export function serverTask(packagePath: string, livereload = true,
130+
rewrites?: {from: string, to: string}[]) {
131+
132+
// The http-rewrite-middleware only supports relative paths as rewrite destinations.
131133
const relativePath = path.relative(projectDir, packagePath);
134+
const defaultHttpRewrites = [
135+
// Rewrite the node_modules/ and dist/ folder to the real paths. This is a trick to
136+
// avoid that those folders will be rewritten to the specified package path.
137+
{ from: '^/node_modules/(.*)$', to: '/node_modules/$1' },
138+
{ from: '^/dist/(.*)$', to: '/dist/$1' },
139+
// Rewrite every path that doesn't point to a specific file to the index.html file.
140+
// This is necessary for Angular's routing using the HTML5 History API.
141+
{ from: '^/[^.]+$', to: `/${relativePath}/index.html`},
142+
// Rewrite any path that didn't match a pattern before to the specified package path.
143+
{ from: '^(.*)$', to: `/${relativePath}/$1` },
144+
];
132145

133146
return () => {
134147
gulpConnect.server({
@@ -137,17 +150,7 @@ export function serverTask(packagePath: string, livereload = true) {
137150
port: 4200,
138151
host: '0.0.0.0',
139152
middleware: () => {
140-
return [httpRewrite.getMiddleware([
141-
// Rewrite the node_modules/ and dist/ folder to the real paths. This is a trick to
142-
// avoid that those folders will be rewritten to the specified package path.
143-
{ from: '^/node_modules/(.*)$', to: '/node_modules/$1' },
144-
{ from: '^/dist/(.*)$', to: '/dist/$1' },
145-
// Rewrite every path that doesn't point to a specific file to the index.html file.
146-
// This is necessary for Angular's routing using the HTML5 History API.
147-
{ from: '^/[^.]+$', to: `/${relativePath}/index.html`},
148-
// Rewrite any path that didn't match a pattern before to the specified package path.
149-
{ from: '^(.*)$', to: `/${relativePath}/$1` },
150-
])];
153+
return [httpRewrite.getMiddleware(rewrites || defaultHttpRewrites)];
151154
}
152155
});
153156
};

0 commit comments

Comments
 (0)