Skip to content

Commit 3ec0629

Browse files
Broccohansl
authored andcommitted
fix(@ngtools/webpack): Handle factory files for the LAZY_MODULE_MAP
Fixes: 7901
1 parent 7e7d75d commit 3ec0629

File tree

3 files changed

+167
-4
lines changed

3 files changed

+167
-4
lines changed

packages/@ngtools/webpack/src/transformers/export_lazy_module_map.spec.ts

+26-2
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ import { oneLine, stripIndent } from 'common-tags';
33
import { transformTypescript } from './ast_helpers';
44
import { exportLazyModuleMap } from './export_lazy_module_map';
55

6-
describe('@ngtools/webpack transformers', () => {
7-
describe('replace_resources', () => {
6+
describe('export_lazy_module_map', () => {
7+
it('should create module map for JIT', () => {
88
it('should replace resources', () => {
99
const input = stripIndent`
1010
export { AppModule } from './app/app.module';
@@ -27,4 +27,28 @@ describe('@ngtools/webpack transformers', () => {
2727
expect(oneLine`${result}`).toEqual(oneLine`${output}`);
2828
});
2929
});
30+
31+
it('should create module map for AOT', () => {
32+
const input = stripIndent`
33+
export { AppModule } from './app/app.module';
34+
`;
35+
// tslint:disable:max-line-length
36+
const output = stripIndent`
37+
import * as __lazy_0__ from "app/lazy/lazy.module.ts";
38+
import * as __lazy_1__ from "app/lazy2/lazy2.module.ts";
39+
export { AppModule } from './app/app.module';
40+
export var LAZY_MODULE_MAP = { "./lazy/lazy.module#LazyModule": __lazy_0__.LazyModule, "./lazy2/lazy2.module#LazyModule2": __lazy_1__.LazyModule2 };
41+
`;
42+
// tslint:enable:max-line-length
43+
44+
const transformOpsCb = (sourceFile: ts.SourceFile) => exportLazyModuleMap(sourceFile, {
45+
'./lazy/lazy.module.ngfactory#LazyModuleNgFactory':
46+
'/project/src/app/lazy/lazy.module.ngfactory.ts',
47+
'./lazy2/lazy2.module.ngfactory#LazyModule2NgFactory':
48+
'/project/src/app/lazy2/lazy2.module.ngfactory.ts',
49+
});
50+
const result = transformTypescript(input, transformOpsCb);
51+
52+
expect(oneLine`${result}`).toEqual(oneLine`${output}`);
53+
});
3054
});

packages/@ngtools/webpack/src/transformers/export_lazy_module_map.ts

+10-2
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,16 @@ export function exportLazyModuleMap(
1717

1818
const modules = Object.keys(lazyRoutes)
1919
.map((loadChildrenString) => {
20-
const [, moduleName] = loadChildrenString.split('#');
21-
const modulePath = lazyRoutes[loadChildrenString];
20+
let [, moduleName] = loadChildrenString.split('#');
21+
let modulePath = lazyRoutes[loadChildrenString];
22+
23+
if (modulePath.endsWith('.ngfactory.ts')) {
24+
modulePath = modulePath.replace('.ngfactory', '');
25+
moduleName = moduleName.replace('NgFactory', '');
26+
loadChildrenString = loadChildrenString
27+
.replace('.ngfactory', '')
28+
.replace('NgFactory', '');
29+
}
2230

2331
return {
2432
modulePath,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
import { normalize } from 'path';
2+
3+
import { updateJsonFile, updateTsConfig } from '../../utils/project';
4+
import {
5+
expectFileToMatch,
6+
writeFile,
7+
replaceInFile,
8+
prependToFile,
9+
appendToFile,
10+
} from '../../utils/fs';
11+
import { ng, silentNpm, exec } from '../../utils/process';
12+
import { getGlobalVariable } from '../../utils/env';
13+
import { expectToFail } from '../../utils/utils';
14+
15+
export default function () {
16+
// Skip this in Appveyor tests.
17+
if (getGlobalVariable('argv').appveyor) {
18+
return Promise.resolve();
19+
}
20+
21+
// Skip this for ejected tests.
22+
if (getGlobalVariable('argv').eject) {
23+
return Promise.resolve();
24+
}
25+
26+
let platformServerVersion = '^4.0.0';
27+
28+
if (getGlobalVariable('argv').nightly) {
29+
platformServerVersion = 'github:angular/platform-server-builds';
30+
}
31+
32+
return Promise.resolve()
33+
.then(() => updateJsonFile('.angular-cli.json', configJson => {
34+
const app = configJson['apps'][0];
35+
delete app['polyfills'];
36+
delete app['styles'];
37+
app['platform'] = 'server';
38+
}))
39+
.then(() => updateJsonFile('package.json', packageJson => {
40+
const dependencies = packageJson['dependencies'];
41+
dependencies['@angular/platform-server'] = platformServerVersion;
42+
}))
43+
.then(() => updateTsConfig(tsConfig => {
44+
tsConfig.compilerOptions.types = ['node'];
45+
tsConfig['angularCompilerOptions'] = {
46+
entryModule: 'app/app.module#AppModule'
47+
};
48+
}))
49+
.then(() => writeFile('./src/main.ts', 'export { AppModule } from \'./app/app.module\';'))
50+
.then(() => prependToFile('./src/app/app.module.ts',
51+
'import { ServerModule } from \'@angular/platform-server\';'))
52+
.then(() => replaceInFile('./src/app/app.module.ts', /\[\s*BrowserModule/g,
53+
`[BrowserModule.withServerTransition(\{ appId: 'app' \}), ServerModule`))
54+
.then(() => silentNpm('install'))
55+
.then(() => ng('build'))
56+
// files were created successfully
57+
.then(() => expectFileToMatch('dist/main.bundle.js',
58+
/__webpack_exports__, "AppModule"/))
59+
.then(() => writeFile('./index.js', `
60+
require('zone.js/dist/zone-node');
61+
require('reflect-metadata');
62+
const fs = require('fs');
63+
const \{ AppModule \} = require('./dist/main.bundle');
64+
const \{ renderModule \} = require('@angular/platform-server');
65+
66+
renderModule(AppModule, \{
67+
url: '/',
68+
document: '<app-root></app-root>'
69+
\}).then(html => \{
70+
fs.writeFileSync('dist/index.html', html);
71+
\});
72+
`))
73+
.then(() => exec(normalize('node'), 'index.js'))
74+
.then(() => expectFileToMatch('dist/index.html',
75+
new RegExp('<h2 _ngcontent-c0="">Here are some links to help you start: </h2>')))
76+
.then(() => ng('build', '--aot'))
77+
// files were created successfully
78+
.then(() => replaceInFile('./index.js', /AppModule/g, 'AppModuleNgFactory'))
79+
.then(() => replaceInFile('./index.js', /renderModule/g, 'renderModuleFactory'))
80+
.then(() => exec(normalize('node'), 'index.js'))
81+
82+
// Check externals.
83+
.then(() => prependToFile('./src/app/app.module.ts', `
84+
import 'zone.js/dist/zone-node';
85+
import 'reflect-metadata';
86+
`)
87+
.then(() => appendToFile('./src/app/app.module.ts', `
88+
import * as fs from 'fs';
89+
import { renderModule } from '@angular/platform-server';
90+
91+
renderModule(AppModule, \{
92+
url: '/',
93+
document: '<app-root></app-root>'
94+
\}).then(html => \{
95+
fs.writeFileSync('dist/index.html', html);
96+
\});
97+
`)))
98+
.then(() => ng('generate', 'module', 'lazy', '--routing'))
99+
.then(() =>
100+
writeFile('src/app/app.module.ts', `
101+
import { BrowserModule } from '@angular/platform-browser';
102+
import { NgModule } from '@angular/core';
103+
import { FormsModule } from '@angular/forms';
104+
import { HttpModule } from '@angular/http';
105+
106+
import { AppComponent } from './app.component';
107+
import { RouterModule } from '@angular/router';
108+
109+
@NgModule({
110+
declarations: [
111+
AppComponent
112+
],
113+
imports: [
114+
BrowserModule,
115+
FormsModule,
116+
HttpModule,
117+
RouterModule.forRoot([
118+
{ path: 'lazy', loadChildren: './lazy/lazy.module#LazyModule' }
119+
])
120+
],
121+
providers: [],
122+
bootstrap: [AppComponent]
123+
})
124+
export class AppModule { }
125+
`
126+
))
127+
.then(() => ng('build', '--aot'))
128+
// should not contain ".ngfactory#" or "NgFactory"
129+
.then(() => expectFileToMatch('dist/main.bundle.js',
130+
'var LAZY_MODULE_MAP = { "./lazy/lazy.module#LazyModule"'));
131+
}

0 commit comments

Comments
 (0)