Skip to content

Commit bfcdc68

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 9b52253 commit bfcdc68

File tree

3 files changed

+58
-12
lines changed

3 files changed

+58
-12
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@
131131
"conventional-changelog": "^1.1.0",
132132
"dtsgenerator": "^0.9.1",
133133
"eslint": "^3.11.0",
134+
"eslint-plugin-standard": "^2.1.1",
134135
"exists-sync": "0.0.4",
135136
"express": "^4.14.0",
136137
"jasmine": "^2.4.1",

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

Lines changed: 56 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -274,9 +274,36 @@ function _getResourceRequest(element: ts.Expression, sourceFile: ts.SourceFile)
274274
function _replaceResources(refactor: TypeScriptFileRefactor): void {
275275
const sourceFile = refactor.sourceFile;
276276

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

296327
if (key == 'templateUrl') {
297-
refactor.replaceNode(node,
298-
`template: require(${_getResourceRequest(node.initializer, sourceFile)})`);
328+
const url = (node.initializer as ts.StringLiteral).text;
329+
if (url) {
330+
acc.push(url);
331+
}
299332
} else if (key == 'styleUrls') {
300333
const arr = <ts.ArrayLiteralExpression[]>(
301334
refactor.findAstNodes(node, ts.SyntaxKind.ArrayLiteralExpression, false));
302335
if (!arr || arr.length == 0 || arr[0].elements.length == 0) {
303336
return;
304337
}
305338

306-
const initializer = arr[0].elements.map((element: ts.Expression) => {
307-
return _getResourceRequest(element, sourceFile);
339+
arr[0].elements.forEach((element: ts.Expression) => {
340+
if (element.kind == ts.SyntaxKind.StringLiteral) {
341+
const url = (element as ts.StringLiteral).text;
342+
if (url) {
343+
acc.push(url);
344+
}
345+
}
308346
});
309-
refactor.replaceNode(node, `styles: [require(${initializer.join('), require(')})]`);
310347
}
311-
});
348+
return acc;
349+
}, []);
312350
}
313351

314352

@@ -362,6 +400,12 @@ export function ngcLoader(this: LoaderContext & { _compilation: any }) {
362400
plugin.diagnose(sourceFileName);
363401
}
364402
})
403+
.then(() => {
404+
// Add resources as dependencies.
405+
_getResourcesUrls(refactor).forEach((url: string) => {
406+
this.addDependency(path.resolve(path.dirname(sourceFileName), url));
407+
});
408+
})
365409
.then(() => {
366410
// Force a few compiler options to make sure we get the result we want.
367411
const compilerOptions: ts.CompilerOptions = Object.assign({}, plugin.compilerOptions, {

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

Lines changed: 1 addition & 0 deletions
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)