Skip to content

Commit 7cdf56b

Browse files
committed
fix(@ngtools/webpack): add template/styles as dependencies
So they are rebuilt when the resource changes. This PR refactor _replaceResources into _getResourceNodes which returns the AST nodes for templateUrl or styleUrls, then use that to get the URLs (values). For values that are not computable, we simply ignores.
1 parent f2241a8 commit 7cdf56b

File tree

2 files changed

+57
-12
lines changed

2 files changed

+57
-12
lines changed

packages/@ngtools/webpack/src/loader.ts

+56-12
Original file line numberDiff line numberDiff line change
@@ -278,9 +278,36 @@ function _getResourceRequest(element: ts.Expression, sourceFile: ts.SourceFile)
278278
function _replaceResources(refactor: TypeScriptFileRefactor): void {
279279
const sourceFile = refactor.sourceFile;
280280

281+
_getResourceNodes(refactor)
282+
// Get the full text of the initializer.
283+
.forEach((node: ts.PropertyAssignment) => {
284+
const key = _getContentOfKeyLiteral(sourceFile, node.name);
285+
286+
if (key == 'templateUrl') {
287+
refactor.replaceNode(node,
288+
`template: require(${_getResourceRequest(node.initializer, sourceFile)})`);
289+
} else if (key == 'styleUrls') {
290+
const arr = <ts.ArrayLiteralExpression[]>(
291+
refactor.findAstNodes(node, ts.SyntaxKind.ArrayLiteralExpression, false));
292+
if (!arr || arr.length == 0 || arr[0].elements.length == 0) {
293+
return;
294+
}
295+
296+
const initializer = arr[0].elements.map((element: ts.Expression) => {
297+
return _getResourceRequest(element, sourceFile);
298+
});
299+
refactor.replaceNode(node, `styles: [require(${initializer.join('), require(')})]`);
300+
}
301+
});
302+
}
303+
304+
305+
function _getResourceNodes(refactor: TypeScriptFileRefactor) {
306+
const { sourceFile } = refactor;
307+
281308
// Find all object literals.
282-
refactor.findAstNodes(sourceFile, ts.SyntaxKind.ObjectLiteralExpression, true)
283-
// Get all their property assignments.
309+
return refactor.findAstNodes(sourceFile, ts.SyntaxKind.ObjectLiteralExpression, true)
310+
// Get all their property assignments.
284311
.map(node => refactor.findAstNodes(node, ts.SyntaxKind.PropertyAssignment))
285312
// Flatten into a single array (from an array of array<property assignments>).
286313
.reduce((prev, curr) => curr ? prev.concat(curr) : prev, [])
@@ -292,27 +319,38 @@ function _replaceResources(refactor: TypeScriptFileRefactor): void {
292319
return false;
293320
}
294321
return key == 'templateUrl' || key == 'styleUrls';
295-
})
296-
// Get the full text of the initializer.
297-
.forEach((node: ts.PropertyAssignment) => {
298-
const key = _getContentOfKeyLiteral(sourceFile, node.name);
322+
});
323+
}
324+
325+
326+
function _getResourcesUrls(refactor: TypeScriptFileRefactor): string[] {
327+
return _getResourceNodes(refactor)
328+
.reduce((acc: string[], node: ts.PropertyAssignment) => {
329+
const key = _getContentOfKeyLiteral(refactor.sourceFile, node.name);
299330

300331
if (key == 'templateUrl') {
301-
refactor.replaceNode(node,
302-
`template: require(${_getResourceRequest(node.initializer, sourceFile)})`);
332+
const url = (node.initializer as ts.StringLiteral).text;
333+
if (url) {
334+
acc.push(url);
335+
}
303336
} else if (key == 'styleUrls') {
304337
const arr = <ts.ArrayLiteralExpression[]>(
305338
refactor.findAstNodes(node, ts.SyntaxKind.ArrayLiteralExpression, false));
306339
if (!arr || arr.length == 0 || arr[0].elements.length == 0) {
307340
return;
308341
}
309342

310-
const initializer = arr[0].elements.map((element: ts.Expression) => {
311-
return _getResourceRequest(element, sourceFile);
343+
arr[0].elements.forEach((element: ts.Expression) => {
344+
if (element.kind == ts.SyntaxKind.StringLiteral) {
345+
const url = (element as ts.StringLiteral).text;
346+
if (url) {
347+
acc.push(url);
348+
}
349+
}
312350
});
313-
refactor.replaceNode(node, `styles: [require(${initializer.join('), require(')})]`);
314351
}
315-
});
352+
return acc;
353+
}, []);
316354
}
317355

318356

@@ -366,6 +404,12 @@ export function ngcLoader(this: LoaderContext & { _compilation: any }) {
366404
plugin.diagnose(sourceFileName);
367405
}
368406
})
407+
.then(() => {
408+
// Add resources as dependencies.
409+
_getResourcesUrls(refactor).forEach((url: string) => {
410+
this.addDependency(path.resolve(path.dirname(sourceFileName), url));
411+
});
412+
})
369413
.then(() => {
370414
// Force a few compiler options to make sure we get the result we want.
371415
const compilerOptions: ts.CompilerOptions = Object.assign({}, plugin.compilerOptions, {

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

+1
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ export interface NormalModule {
4242
export interface LoaderContext {
4343
_module: NormalModule;
4444

45+
addDependency(path: string): void;
4546
async(): LoaderCallback;
4647
cacheable(): void;
4748

0 commit comments

Comments
 (0)