Skip to content

Commit ba82d75

Browse files
author
US\khoi.pham
committed
fix(@angular/cli): Lazy loading module from library package located in node_modules fails to build. (angular#6373)
1 parent a7668e0 commit ba82d75

File tree

1 file changed

+53
-33
lines changed

1 file changed

+53
-33
lines changed

Diff for: packages/@ngtools/webpack/src/loader.ts

+53-33
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import * as path from 'path';
22
import * as ts from 'typescript';
3-
import {AotPlugin} from './plugin';
4-
import {TypeScriptFileRefactor} from './refactor';
5-
import {LoaderContext, ModuleReason} from './webpack';
3+
import { AotPlugin } from './plugin';
4+
import { TypeScriptFileRefactor } from './refactor';
5+
import { LoaderContext, ModuleReason } from './webpack';
66

77
interface Platform {
88
name: string;
@@ -11,9 +11,10 @@ interface Platform {
1111

1212
const loaderUtils = require('loader-utils');
1313
const NormalModule = require('webpack/lib/NormalModule');
14+
const fs = require('fs');
1415

1516
// This is a map of changes which need to be made
16-
const changeMap: {[key: string]: Platform} = {
17+
const changeMap: { [key: string]: Platform } = {
1718
platformBrowserDynamic: {
1819
name: 'platformBrowser',
1920
importLocation: '@angular/platform-browser'
@@ -77,8 +78,8 @@ function _angularImportsFromNode(node: ts.ImportDeclaration, _sourceFile: ts.Sou
7778

7879

7980
function _ctorParameterFromTypeReference(paramNode: ts.ParameterDeclaration,
80-
angularImports: string[],
81-
refactor: TypeScriptFileRefactor) {
81+
angularImports: string[],
82+
refactor: TypeScriptFileRefactor) {
8283
let typeName = 'undefined';
8384

8485
if (paramNode.type) {
@@ -134,8 +135,8 @@ function _ctorParameterFromTypeReference(paramNode: ts.ParameterDeclaration,
134135

135136

136137
function _addCtorParameters(classNode: ts.ClassDeclaration,
137-
angularImports: string[],
138-
refactor: TypeScriptFileRefactor) {
138+
angularImports: string[],
139+
refactor: TypeScriptFileRefactor) {
139140
// For every classes with constructors, output the ctorParameters function which contains a list
140141
// of injectable types.
141142
const ctor = (
@@ -212,7 +213,7 @@ function _replaceBootstrap(plugin: AotPlugin, refactor: TypeScriptFileRefactor)
212213
.map(call => call.expression as ts.PropertyAccessExpression)
213214
.filter(access => {
214215
return access.name.kind == ts.SyntaxKind.Identifier
215-
&& access.name.text == 'bootstrapModule';
216+
&& access.name.text == 'bootstrapModule';
216217
});
217218

218219
const calls: ts.CallExpression[] = bootstraps
@@ -273,13 +274,13 @@ function _removeModuleId(refactor: TypeScriptFileRefactor) {
273274
.filter((node: ts.ObjectLiteralExpression) => {
274275
return node.properties.some(prop => {
275276
return prop.kind == ts.SyntaxKind.PropertyAssignment
276-
&& _getContentOfKeyLiteral(sourceFile, prop.name) == 'moduleId';
277+
&& _getContentOfKeyLiteral(sourceFile, prop.name) == 'moduleId';
277278
});
278279
})
279280
.forEach((node: ts.ObjectLiteralExpression) => {
280281
const moduleIdProp = node.properties.filter((prop: ts.ObjectLiteralElement, _idx: number) => {
281282
return prop.kind == ts.SyntaxKind.PropertyAssignment
282-
&& _getContentOfKeyLiteral(sourceFile, prop.name) == 'moduleId';
283+
&& _getContentOfKeyLiteral(sourceFile, prop.name) == 'moduleId';
283284
})[0];
284285
// Get the trailing comma.
285286
const moduleIdCommaProp = moduleIdProp.parent
@@ -299,6 +300,19 @@ function _getResourceRequest(element: ts.Expression, sourceFile: ts.SourceFile)
299300
}
300301
}
301302

303+
function _getPrecompiledResult(fileName: string) {
304+
const basePath = fileName.substr(0, fileName.lastIndexOf('\\') + 1),
305+
packageJson = require(basePath + "package.json"),
306+
precompiledFileName = basePath + packageJson.es2015,
307+
output = fs.readFileSync(precompiledFileName, 'utf8'),
308+
sourceMap = fs.readFileSync(precompiledFileName + '.map', 'utf8');
309+
310+
return {
311+
outputText: output,
312+
sourceMap: sourceMap
313+
};
314+
}
315+
302316
function _replaceResources(refactor: TypeScriptFileRefactor): void {
303317
const sourceFile = refactor.sourceFile;
304318

@@ -331,7 +345,7 @@ function _getResourceNodes(refactor: TypeScriptFileRefactor) {
331345

332346
// Find all object literals.
333347
return refactor.findAstNodes(sourceFile, ts.SyntaxKind.ObjectLiteralExpression, true)
334-
// Get all their property assignments.
348+
// Get all their property assignments.
335349
.map(node => refactor.findAstNodes(node, ts.SyntaxKind.PropertyAssignment))
336350
// Flatten into a single array (from an array of array<property assignments>).
337351
.reduce((prev, curr) => curr ? prev.concat(curr) : prev, [])
@@ -398,6 +412,7 @@ function _diagnoseDeps(reasons: ModuleReason[], plugin: AotPlugin, checked: Set<
398412
export function ngcLoader(this: LoaderContext & { _compilation: any }) {
399413
const cb = this.async();
400414
const sourceFileName: string = this.resourcePath;
415+
const regex = /\.d\.ts/ig;
401416

402417
const plugin = this._compilation._ngToolsWebpackPluginInstance as AotPlugin;
403418
// We must verify that AotPlugin is an instance of the right class.
@@ -442,33 +457,38 @@ export function ngcLoader(this: LoaderContext & { _compilation: any }) {
442457
sourceRoot: plugin.basePath
443458
});
444459

445-
const result = refactor.transpile(compilerOptions);
460+
const result = (regex.test(sourceFileName)) ? _getPrecompiledResult(sourceFileName) : refactor.transpile(compilerOptions);
446461
cb(null, result.outputText, result.sourceMap);
447462
})
448463
.catch(err => cb(err));
449464
} else {
450-
const options = loaderUtils.getOptions(this) || {};
451-
const tsConfigPath = options.tsConfigPath;
452-
const tsConfig = ts.readConfigFile(tsConfigPath, ts.sys.readFile);
453-
454-
if (tsConfig.error) {
455-
throw tsConfig.error;
456-
}
465+
if (regex.test(sourceFileName)) {
466+
const result = _getPrecompiledResult(sourceFileName);
467+
cb(null, result.outputText, result.sourceMap);
468+
} else {
469+
const options = loaderUtils.getOptions(this) || {};
470+
const tsConfigPath = options.tsConfigPath;
471+
const tsConfig = ts.readConfigFile(tsConfigPath, ts.sys.readFile);
472+
473+
if (tsConfig.error) {
474+
throw tsConfig.error;
475+
}
457476

458-
const compilerOptions: ts.CompilerOptions = tsConfig.config.compilerOptions;
459-
for (const key of Object.keys(options)) {
460-
if (key == 'tsConfigPath') {
461-
continue;
477+
const compilerOptions: ts.CompilerOptions = tsConfig.config.compilerOptions;
478+
for (const key of Object.keys(options)) {
479+
if (key == 'tsConfigPath') {
480+
continue;
481+
}
482+
compilerOptions[key] = options[key];
462483
}
463-
compilerOptions[key] = options[key];
484+
const compilerHost = ts.createCompilerHost(compilerOptions);
485+
const refactor = new TypeScriptFileRefactor(sourceFileName, compilerHost);
486+
_replaceResources(refactor);
487+
488+
const result = refactor.transpile(compilerOptions);
489+
// Webpack is going to take care of this.
490+
result.outputText = result.outputText.replace(/^\/\/# sourceMappingURL=[^\r\n]*/gm, '');
491+
cb(null, result.outputText, result.sourceMap);
464492
}
465-
const compilerHost = ts.createCompilerHost(compilerOptions);
466-
const refactor = new TypeScriptFileRefactor(sourceFileName, compilerHost);
467-
_replaceResources(refactor);
468-
469-
const result = refactor.transpile(compilerOptions);
470-
// Webpack is going to take care of this.
471-
result.outputText = result.outputText.replace(/^\/\/# sourceMappingURL=[^\r\n]*/gm, '');
472-
cb(null, result.outputText, result.sourceMap);
473493
}
474494
}

0 commit comments

Comments
 (0)