Skip to content

Commit 1972bd9

Browse files
clydinhansl
authored andcommitted
fix(@ngtools/webpack): ensure webpack handles module resolution
1 parent 14b36c9 commit 1972bd9

File tree

2 files changed

+96
-12
lines changed

2 files changed

+96
-12
lines changed

packages/@ngtools/webpack/src/paths-plugin.ts

Lines changed: 57 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -39,18 +39,66 @@ export function resolveWithPaths(
3939
cache
4040
);
4141

42-
let moduleFilePath = moduleResolver.resolvedModule
43-
&& moduleResolver.resolvedModule.resolvedFileName;
44-
45-
// If TypeScript gives us a .d.ts it's probably a node module and we need to let webpack
46-
// do the resolution.
47-
if (moduleFilePath) {
48-
moduleFilePath = moduleFilePath.replace(/\.d\.ts$/, '.js');
49-
if (host.fileExists(moduleFilePath)) {
50-
request.request = moduleFilePath;
42+
const moduleFilePath = moduleResolver.resolvedModule
43+
&& moduleResolver.resolvedModule.resolvedFileName;
44+
45+
// If there is no result, let webpack try to resolve
46+
if (!moduleFilePath) {
47+
callback(null, request);
48+
return;
49+
}
50+
51+
// If TypeScript gives us a `.d.ts`, it is probably a node module
52+
if (moduleFilePath.endsWith('.d.ts')) {
53+
// If in a package, let webpack resolve the package
54+
const packageRootPath = path.join(path.dirname(moduleFilePath), 'package.json');
55+
if (!host.fileExists(packageRootPath)) {
56+
// Otherwise, if there is a file with a .js extension use that
57+
const jsFilePath = moduleFilePath.slice(0, -5) + '.js';
58+
if (host.fileExists(jsFilePath)) {
59+
request.request = jsFilePath;
60+
}
61+
}
62+
63+
callback(null, request);
64+
return;
65+
}
66+
67+
// TypeScript gives `index.ts` and the request is not for the specific file,
68+
// check if it is a module
69+
const requestFilePath = path.basename(request.request);
70+
if (path.basename(moduleFilePath) === 'index.ts'
71+
&& requestFilePath !== 'index' && requestFilePath !== 'index.ts') {
72+
const packageRootPath = path.join(path.dirname(moduleFilePath), 'package.json');
73+
if (host.fileExists(packageRootPath)) {
74+
// potential module request
75+
let isPathMapped = false;
76+
if (compilerOptions.paths) {
77+
// check if any path mapping rules are relevant
78+
isPathMapped = Object.keys(compilerOptions.paths)
79+
.some(pattern => {
80+
// can only contain zero or one
81+
const starIndex = pattern.indexOf('*');
82+
if (starIndex === -1) {
83+
return pattern === request.request;
84+
} else if (starIndex === pattern.length - 1) {
85+
return request.request.startsWith(pattern.slice(0, -1));
86+
} else {
87+
const [prefix, suffix] = pattern.split('*');
88+
return request.request.startsWith(prefix) && request.request.endsWith(suffix);
89+
}
90+
});
91+
}
92+
if (!isPathMapped) {
93+
// path mapping not involved, let webpack handle the module request
94+
request.request = path.dirname(moduleFilePath);
95+
callback(null, request);
96+
return;
97+
}
5198
}
5299
}
53100

101+
request.request = moduleFilePath;
54102
callback(null, request);
55103
}
56104

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,49 @@
11
import { appendToFile, prependToFile } from '../../utils/fs';
22
import { ng, silentNpm } from '../../utils/process';
3+
import { updateJsonFile } from '../../utils/project';
4+
import { expectToFail } from '../../utils/utils';
35

46

57
export default async function () {
6-
await silentNpm('install', 'firebase@3.7.8');
7-
88
await prependToFile('src/app/app.module.ts', 'import * as firebase from \'firebase\';');
99
await appendToFile('src/app/app.module.ts', 'firebase.initializeApp({});');
1010

11-
await ng('build');
11+
await silentNpm('install', 'firebase@3.7.8');
1212
await ng('build', '--aot');
13+
await ng('test', '--single-run');
14+
15+
await silentNpm('install', 'firebase@4.9.0');
16+
await ng('build', '--aot');
17+
await ng('test', '--single-run');
18+
19+
// await prependToFile('src/app/app.module.ts', 'import * as firebase from \'firebase\';');
20+
// await appendToFile('src/app/app.module.ts', 'firebase.initializeApp({});');
21+
// await ng('build');
22+
23+
await updateJsonFile('src/tsconfig.app.json', tsconfig => {
24+
tsconfig.compilerOptions.paths = {};
25+
});
26+
await ng('build');
27+
28+
await updateJsonFile('src/tsconfig.app.json', tsconfig => {
29+
tsconfig.compilerOptions.paths = {
30+
'@app/*': ['*'],
31+
'@lib/*/test': ['*/test'],
32+
};
33+
});
34+
await ng('build');
35+
36+
await updateJsonFile('src/tsconfig.app.json', tsconfig => {
37+
tsconfig.compilerOptions.paths = {
38+
'@firebase/polyfill': ['@firebase/polyfill/index.ts'],
39+
};
40+
});
41+
await expectToFail(() => ng('build'));
42+
43+
await updateJsonFile('src/tsconfig.app.json', tsconfig => {
44+
tsconfig.compilerOptions.paths = {
45+
'@firebase/polyfill*': ['@firebase/polyfill/index.ts'],
46+
};
47+
});
48+
await expectToFail(() => ng('build'));
1349
}

0 commit comments

Comments
 (0)