@ngtools/webpack 11.1.4 → 11.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +4 -4
- package/src/angular_compiler_plugin.js +6 -6
- package/src/ivy/plugin.d.ts +3 -0
- package/src/ivy/plugin.js +54 -16
- package/src/ivy/symbol.d.ts +1 -0
- package/src/ivy/transformation.js +5 -4
- package/src/transformers/export_ngfactory.js +2 -2
- package/src/transformers/import_factory.js +2 -2
- package/src/transformers/insert_import.js +7 -7
- package/src/transformers/register_locale_data.js +5 -5
- package/src/transformers/replace_bootstrap.js +4 -4
- package/src/transformers/replace_resources.js +20 -19
- package/src/transformers/replace_server_bootstrap.js +10 -10
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ngtools/webpack",
|
|
3
|
-
"version": "11.
|
|
3
|
+
"version": "11.2.0",
|
|
4
4
|
"description": "Webpack plugin that AoT compiles your Angular components and modules.",
|
|
5
5
|
"main": "./src/index.js",
|
|
6
6
|
"typings": "src/index.d.ts",
|
|
@@ -25,12 +25,12 @@
|
|
|
25
25
|
},
|
|
26
26
|
"homepage": "https://github.com/angular/angular-cli",
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@angular-devkit/core": "11.
|
|
29
|
-
"enhanced-resolve": "5.
|
|
28
|
+
"@angular-devkit/core": "11.2.0",
|
|
29
|
+
"enhanced-resolve": "5.7.0",
|
|
30
30
|
"webpack-sources": "2.2.0"
|
|
31
31
|
},
|
|
32
32
|
"peerDependencies": {
|
|
33
|
-
"@angular/compiler-cli": "^11.0.0",
|
|
33
|
+
"@angular/compiler-cli": "^11.0.0 || ^11.2.0-next",
|
|
34
34
|
"typescript": "~4.0.0 || ~4.1.0",
|
|
35
35
|
"webpack": "^4.0.0"
|
|
36
36
|
},
|
|
@@ -98,13 +98,13 @@ class AngularCompilerPlugin {
|
|
|
98
98
|
basePath = path.resolve(process.cwd(), options.basePath);
|
|
99
99
|
}
|
|
100
100
|
// Parse the tsconfig contents.
|
|
101
|
-
const
|
|
102
|
-
if (
|
|
103
|
-
throw new Error(compiler_cli_1.formatDiagnostics(
|
|
101
|
+
const { errors, rootNames, options: compilerOptions } = compiler_cli_1.readConfiguration(this._tsConfigPath, options.compilerOptions);
|
|
102
|
+
if (errors && errors.length) {
|
|
103
|
+
throw new Error(compiler_cli_1.formatDiagnostics(errors));
|
|
104
104
|
}
|
|
105
|
-
this._rootNames =
|
|
106
|
-
this._compilerOptions =
|
|
107
|
-
this._basePath =
|
|
105
|
+
this._rootNames = rootNames;
|
|
106
|
+
this._compilerOptions = compilerOptions;
|
|
107
|
+
this._basePath = compilerOptions.basePath || basePath || '';
|
|
108
108
|
// Overwrite outDir so we can find generated files next to their .ts origin in compilerHost.
|
|
109
109
|
this._compilerOptions.outDir = '';
|
|
110
110
|
this._compilerOptions.suppressOutputPathCheck = true;
|
package/src/ivy/plugin.d.ts
CHANGED
|
@@ -27,11 +27,14 @@ export declare class AngularWebpackPlugin {
|
|
|
27
27
|
private buildTimestamp;
|
|
28
28
|
private readonly lazyRouteMap;
|
|
29
29
|
private readonly requiredFilesToEmit;
|
|
30
|
+
private readonly requiredFilesToEmitCache;
|
|
31
|
+
private readonly fileEmitHistory;
|
|
30
32
|
constructor(options?: Partial<AngularPluginOptions>);
|
|
31
33
|
get options(): AngularPluginOptions;
|
|
32
34
|
apply(compiler: Compiler & {
|
|
33
35
|
watchMode?: boolean;
|
|
34
36
|
}): void;
|
|
37
|
+
private rebuildRequiredFiles;
|
|
35
38
|
private loadConfiguration;
|
|
36
39
|
private updateAotProgram;
|
|
37
40
|
private updateJitProgram;
|
package/src/ivy/plugin.js
CHANGED
|
@@ -10,6 +10,7 @@ exports.AngularWebpackPlugin = void 0;
|
|
|
10
10
|
*/
|
|
11
11
|
const compiler_cli_1 = require("@angular/compiler-cli");
|
|
12
12
|
const program_1 = require("@angular/compiler-cli/src/ngtsc/program");
|
|
13
|
+
const crypto_1 = require("crypto");
|
|
13
14
|
const path = require("path");
|
|
14
15
|
const ts = require("typescript");
|
|
15
16
|
const webpack_1 = require("webpack");
|
|
@@ -34,11 +35,16 @@ function initializeNgccProcessor(compiler, tsconfig) {
|
|
|
34
35
|
const processor = new ngcc_processor_1.NgccProcessor(mainFields, warnings, errors, compiler.context, tsconfig, inputFileSystem, (_b = webpackOptions.resolve) === null || _b === void 0 ? void 0 : _b.symlinks);
|
|
35
36
|
return { processor, errors, warnings };
|
|
36
37
|
}
|
|
38
|
+
function hashContent(content) {
|
|
39
|
+
return crypto_1.createHash('md5').update(content).digest();
|
|
40
|
+
}
|
|
37
41
|
const PLUGIN_NAME = 'angular-compiler';
|
|
38
42
|
class AngularWebpackPlugin {
|
|
39
43
|
constructor(options = {}) {
|
|
40
44
|
this.lazyRouteMap = {};
|
|
41
45
|
this.requiredFilesToEmit = new Set();
|
|
46
|
+
this.requiredFilesToEmitCache = new Map();
|
|
47
|
+
this.fileEmitHistory = new Map();
|
|
42
48
|
this.pluginOptions = {
|
|
43
49
|
emitClassMetadata: false,
|
|
44
50
|
emitNgModuleScope: false,
|
|
@@ -152,19 +158,7 @@ class AngularWebpackPlugin {
|
|
|
152
158
|
}
|
|
153
159
|
compilation.hooks.finishModules.tapPromise(PLUGIN_NAME, async (modules) => {
|
|
154
160
|
// Rebuild any remaining AOT required modules
|
|
155
|
-
|
|
156
|
-
const module = modules.find(({ resource }) => resource && paths_1.normalizePath(resource) === filename);
|
|
157
|
-
if (!module) {
|
|
158
|
-
resolve();
|
|
159
|
-
}
|
|
160
|
-
else {
|
|
161
|
-
compilation.rebuildModule(module, resolve);
|
|
162
|
-
}
|
|
163
|
-
});
|
|
164
|
-
for (const requiredFile of this.requiredFilesToEmit) {
|
|
165
|
-
await rebuild(requiredFile);
|
|
166
|
-
}
|
|
167
|
-
this.requiredFilesToEmit.clear();
|
|
161
|
+
await this.rebuildRequiredFiles(modules, compilation, fileEmitter);
|
|
168
162
|
// Analyze program for unused files
|
|
169
163
|
if (compilation.errors.length > 0) {
|
|
170
164
|
return;
|
|
@@ -192,6 +186,41 @@ class AngularWebpackPlugin {
|
|
|
192
186
|
compilation[symbol_1.AngularPluginSymbol] = fileEmitter;
|
|
193
187
|
});
|
|
194
188
|
}
|
|
189
|
+
async rebuildRequiredFiles(modules, compilation, fileEmitter) {
|
|
190
|
+
if (this.requiredFilesToEmit.size === 0) {
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
const rebuild = (webpackModule) => new Promise((resolve) => compilation.rebuildModule(webpackModule, resolve));
|
|
194
|
+
const filesToRebuild = new Set();
|
|
195
|
+
for (const requiredFile of this.requiredFilesToEmit) {
|
|
196
|
+
const history = this.fileEmitHistory.get(requiredFile);
|
|
197
|
+
if (history) {
|
|
198
|
+
const emitResult = await fileEmitter(requiredFile);
|
|
199
|
+
if ((emitResult === null || emitResult === void 0 ? void 0 : emitResult.content) === undefined ||
|
|
200
|
+
history.length !== emitResult.content.length ||
|
|
201
|
+
emitResult.hash === undefined ||
|
|
202
|
+
Buffer.compare(history.hash, emitResult.hash) !== 0) {
|
|
203
|
+
// New emit result is different so rebuild using new emit result
|
|
204
|
+
this.requiredFilesToEmitCache.set(requiredFile, emitResult);
|
|
205
|
+
filesToRebuild.add(requiredFile);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
// No emit history so rebuild
|
|
210
|
+
filesToRebuild.add(requiredFile);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
if (filesToRebuild.size > 0) {
|
|
214
|
+
for (const webpackModule of [...modules]) {
|
|
215
|
+
const resource = webpackModule.resource;
|
|
216
|
+
if (resource && filesToRebuild.has(paths_1.normalizePath(resource))) {
|
|
217
|
+
await rebuild(webpackModule);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
this.requiredFilesToEmit.clear();
|
|
222
|
+
this.requiredFilesToEmitCache.clear();
|
|
223
|
+
}
|
|
195
224
|
loadConfiguration(compilation) {
|
|
196
225
|
const { options: compilerOptions, rootNames, errors } = compiler_cli_1.readConfiguration(this.pluginOptions.tsconfig, this.pluginOptions.compilerOptions);
|
|
197
226
|
compilerOptions.enableIvy = true;
|
|
@@ -355,12 +384,15 @@ class AngularWebpackPlugin {
|
|
|
355
384
|
}
|
|
356
385
|
createFileEmitter(program, transformers = {}, getExtraDependencies, onAfterEmit) {
|
|
357
386
|
return async (file) => {
|
|
387
|
+
if (this.requiredFilesToEmitCache.has(file)) {
|
|
388
|
+
return this.requiredFilesToEmitCache.get(file);
|
|
389
|
+
}
|
|
358
390
|
const sourceFile = program.getSourceFile(file);
|
|
359
391
|
if (!sourceFile) {
|
|
360
392
|
return undefined;
|
|
361
393
|
}
|
|
362
|
-
let content
|
|
363
|
-
let map
|
|
394
|
+
let content;
|
|
395
|
+
let map;
|
|
364
396
|
program.emit(sourceFile, (filename, data) => {
|
|
365
397
|
if (filename.endsWith('.map')) {
|
|
366
398
|
map = data;
|
|
@@ -370,11 +402,17 @@ class AngularWebpackPlugin {
|
|
|
370
402
|
}
|
|
371
403
|
}, undefined, undefined, transformers);
|
|
372
404
|
onAfterEmit === null || onAfterEmit === void 0 ? void 0 : onAfterEmit(sourceFile);
|
|
405
|
+
let hash;
|
|
406
|
+
if (content !== undefined && this.watchMode) {
|
|
407
|
+
// Capture emit history info for Angular rebuild analysis
|
|
408
|
+
hash = hashContent(content);
|
|
409
|
+
this.fileEmitHistory.set(file, { length: content.length, hash });
|
|
410
|
+
}
|
|
373
411
|
const dependencies = [
|
|
374
412
|
...program.getAllDependencies(sourceFile),
|
|
375
413
|
...getExtraDependencies(sourceFile),
|
|
376
414
|
].map(paths_1.externalizePath);
|
|
377
|
-
return { content, map, dependencies };
|
|
415
|
+
return { content, map, dependencies, hash };
|
|
378
416
|
};
|
|
379
417
|
}
|
|
380
418
|
}
|
package/src/ivy/symbol.d.ts
CHANGED
|
@@ -60,16 +60,17 @@ function replaceBootstrap(getTypeChecker) {
|
|
|
60
60
|
let bootstrapImport;
|
|
61
61
|
let bootstrapNamespace;
|
|
62
62
|
const replacedNodes = [];
|
|
63
|
+
const nodeFactory = context.factory;
|
|
63
64
|
const visitNode = (node) => {
|
|
64
65
|
if (ts.isCallExpression(node) && ts.isIdentifier(node.expression)) {
|
|
65
66
|
const target = node.expression;
|
|
66
67
|
if (target.text === 'platformBrowserDynamic') {
|
|
67
68
|
if (!bootstrapNamespace) {
|
|
68
|
-
bootstrapNamespace =
|
|
69
|
-
bootstrapImport =
|
|
69
|
+
bootstrapNamespace = nodeFactory.createUniqueName('__NgCli_bootstrap_');
|
|
70
|
+
bootstrapImport = nodeFactory.createImportDeclaration(undefined, undefined, nodeFactory.createImportClause(false, undefined, nodeFactory.createNamespaceImport(bootstrapNamespace)), nodeFactory.createStringLiteral('@angular/platform-browser'));
|
|
70
71
|
}
|
|
71
72
|
replacedNodes.push(target);
|
|
72
|
-
return
|
|
73
|
+
return nodeFactory.updateCallExpression(node, nodeFactory.createPropertyAccessExpression(bootstrapNamespace, 'platformBrowser'), node.typeArguments, node.arguments);
|
|
73
74
|
}
|
|
74
75
|
}
|
|
75
76
|
return ts.visitEachChild(node, visitNode, context);
|
|
@@ -83,7 +84,7 @@ function replaceBootstrap(getTypeChecker) {
|
|
|
83
84
|
updatedSourceFile = ts.visitEachChild(updatedSourceFile, (node) => (removals.includes(node) ? undefined : node), context);
|
|
84
85
|
}
|
|
85
86
|
// Add new platform browser import
|
|
86
|
-
return
|
|
87
|
+
return nodeFactory.updateSourceFile(updatedSourceFile, ts.setTextRange(nodeFactory.createNodeArray([bootstrapImport, ...updatedSourceFile.statements]), sourceFile.statements));
|
|
87
88
|
}
|
|
88
89
|
else {
|
|
89
90
|
return updatedSourceFile;
|
|
@@ -45,8 +45,8 @@ function exportNgFactory(shouldTransform, getEntryModule) {
|
|
|
45
45
|
// Add the transform operations.
|
|
46
46
|
const factoryClassName = entryModule.className + 'NgFactory';
|
|
47
47
|
const factoryModulePath = normalizedEntryModulePath + '.ngfactory';
|
|
48
|
-
const namedExports = ts.createNamedExports([ts.createExportSpecifier(undefined, ts.createIdentifier(factoryClassName))]);
|
|
49
|
-
const newImport = ts.createExportDeclaration(undefined, undefined, namedExports, ts.
|
|
48
|
+
const namedExports = ts.factory.createNamedExports([ts.factory.createExportSpecifier(undefined, ts.factory.createIdentifier(factoryClassName))]);
|
|
49
|
+
const newImport = ts.factory.createExportDeclaration(undefined, undefined, false, namedExports, ts.factory.createStringLiteral(factoryModulePath));
|
|
50
50
|
const firstNode = ast_helpers_1.getFirstNode(sourceFile);
|
|
51
51
|
if (firstNode) {
|
|
52
52
|
ops.push(new interfaces_1.AddNodeOperation(sourceFile, firstNode, newImport));
|
|
@@ -183,11 +183,11 @@ function replaceImport(node, context, emitWarning, fileName, typeChecker) {
|
|
|
183
183
|
const replacementVisitor = (node) => {
|
|
184
184
|
if (node === importStringLit) {
|
|
185
185
|
// Transform the import string.
|
|
186
|
-
return ts.createStringLiteral(newImportString);
|
|
186
|
+
return ts.factory.createStringLiteral(newImportString);
|
|
187
187
|
}
|
|
188
188
|
else if (node === exportNameId) {
|
|
189
189
|
// Transform the export name.
|
|
190
|
-
return ts.createIdentifier(exportNameId.text + 'NgFactory');
|
|
190
|
+
return ts.factory.createIdentifier(exportNameId.text + 'NgFactory');
|
|
191
191
|
}
|
|
192
192
|
return ts.visitEachChild(node, replacementVisitor, context);
|
|
193
193
|
};
|
|
@@ -16,9 +16,9 @@ function insertStarImport(sourceFile, identifier, modulePath, target, before = f
|
|
|
16
16
|
const allImports = ast_helpers_1.collectDeepNodes(sourceFile, ts.SyntaxKind.ImportDeclaration);
|
|
17
17
|
// We don't need to verify if the symbol is already imported, star imports should be unique.
|
|
18
18
|
// Create the new import node.
|
|
19
|
-
const namespaceImport = ts.createNamespaceImport(identifier);
|
|
20
|
-
const importClause = ts.createImportClause(undefined, namespaceImport);
|
|
21
|
-
const newImport = ts.createImportDeclaration(undefined, undefined, importClause, ts.
|
|
19
|
+
const namespaceImport = ts.factory.createNamespaceImport(identifier);
|
|
20
|
+
const importClause = ts.factory.createImportClause(false, undefined, namespaceImport);
|
|
21
|
+
const newImport = ts.factory.createImportDeclaration(undefined, undefined, importClause, ts.factory.createStringLiteral(modulePath));
|
|
22
22
|
if (target) {
|
|
23
23
|
ops.push(new interfaces_1.AddNodeOperation(sourceFile, target, before ? newImport : undefined, before ? undefined : newImport));
|
|
24
24
|
}
|
|
@@ -71,13 +71,13 @@ function insertImport(sourceFile, symbolName, modulePath) {
|
|
|
71
71
|
return ops;
|
|
72
72
|
}
|
|
73
73
|
// Just pick the first one and insert at the end of its identifier list.
|
|
74
|
-
ops.push(new interfaces_1.AddNodeOperation(sourceFile, maybeImports[0].elements[maybeImports[0].elements.length - 1], undefined, ts.createImportSpecifier(undefined, ts.createIdentifier(symbolName))));
|
|
74
|
+
ops.push(new interfaces_1.AddNodeOperation(sourceFile, maybeImports[0].elements[maybeImports[0].elements.length - 1], undefined, ts.factory.createImportSpecifier(undefined, ts.factory.createIdentifier(symbolName))));
|
|
75
75
|
}
|
|
76
76
|
else {
|
|
77
77
|
// Create the new import node.
|
|
78
|
-
const namedImports = ts.createNamedImports([ts.createImportSpecifier(undefined, ts.createIdentifier(symbolName))]);
|
|
79
|
-
const importClause = ts.createImportClause(undefined, namedImports);
|
|
80
|
-
const newImport = ts.createImportDeclaration(undefined, undefined, importClause, ts.
|
|
78
|
+
const namedImports = ts.factory.createNamedImports([ts.factory.createImportSpecifier(undefined, ts.factory.createIdentifier(symbolName))]);
|
|
79
|
+
const importClause = ts.factory.createImportClause(false, undefined, namedImports);
|
|
80
|
+
const newImport = ts.factory.createImportDeclaration(undefined, undefined, importClause, ts.factory.createStringLiteral(modulePath));
|
|
81
81
|
if (allImports.length > 0) {
|
|
82
82
|
// Find the last import and insert after.
|
|
83
83
|
ops.push(new interfaces_1.AddNodeOperation(sourceFile, allImports[allImports.length - 1], undefined, newImport));
|
|
@@ -47,15 +47,15 @@ function registerLocaleData(shouldTransform, getEntryModule, locale) {
|
|
|
47
47
|
return;
|
|
48
48
|
}
|
|
49
49
|
// Create the import node for the locale.
|
|
50
|
-
const localeNamespaceId = ts.createUniqueName('__NgCli_locale_');
|
|
50
|
+
const localeNamespaceId = ts.factory.createUniqueName('__NgCli_locale_');
|
|
51
51
|
ops.push(...insert_import_1.insertStarImport(sourceFile, localeNamespaceId, `@angular/common/locales/${locale}`, firstNode, true));
|
|
52
52
|
// Create the import node for the registerLocaleData function.
|
|
53
|
-
const regIdentifier = ts.createIdentifier(`registerLocaleData`);
|
|
54
|
-
const regNamespaceId = ts.createUniqueName('__NgCli_locale_');
|
|
53
|
+
const regIdentifier = ts.factory.createIdentifier(`registerLocaleData`);
|
|
54
|
+
const regNamespaceId = ts.factory.createUniqueName('__NgCli_locale_');
|
|
55
55
|
ops.push(...insert_import_1.insertStarImport(sourceFile, regNamespaceId, '@angular/common', firstNode, true));
|
|
56
56
|
// Create the register function call
|
|
57
|
-
const registerFunctionCall = ts.
|
|
58
|
-
const registerFunctionStatement = ts.
|
|
57
|
+
const registerFunctionCall = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(regNamespaceId, regIdentifier), undefined, [ts.factory.createPropertyAccessExpression(localeNamespaceId, 'default')]);
|
|
58
|
+
const registerFunctionStatement = ts.factory.createExpressionStatement(registerFunctionCall);
|
|
59
59
|
ops.push(new interfaces_1.AddNodeOperation(sourceFile, firstNode, registerFunctionStatement));
|
|
60
60
|
});
|
|
61
61
|
return ops;
|
|
@@ -51,8 +51,8 @@ function replaceBootstrap(shouldTransform, getEntryModule, getTypeChecker, useFa
|
|
|
51
51
|
return;
|
|
52
52
|
}
|
|
53
53
|
const platformBrowserDynamicIdentifier = innerCallExpr.expression;
|
|
54
|
-
const idPlatformBrowser = ts.createUniqueName('__NgCli_bootstrap_');
|
|
55
|
-
const idNgFactory = ts.createUniqueName('__NgCli_bootstrap_');
|
|
54
|
+
const idPlatformBrowser = ts.factory.createUniqueName('__NgCli_bootstrap_');
|
|
55
|
+
const idNgFactory = ts.factory.createUniqueName('__NgCli_bootstrap_');
|
|
56
56
|
// Add the transform operations.
|
|
57
57
|
const relativeEntryModulePath = path_1.relative(path_1.dirname(sourceFile.fileName), entryModule.path);
|
|
58
58
|
let className = entryModule.className;
|
|
@@ -65,9 +65,9 @@ function replaceBootstrap(shouldTransform, getEntryModule, getTypeChecker, useFa
|
|
|
65
65
|
}
|
|
66
66
|
ops.push(
|
|
67
67
|
// Replace the entry module import.
|
|
68
|
-
...insert_import_1.insertStarImport(sourceFile, idNgFactory, modulePath), new interfaces_1.ReplaceNodeOperation(sourceFile, entryModuleIdentifier, ts.
|
|
68
|
+
...insert_import_1.insertStarImport(sourceFile, idNgFactory, modulePath), new interfaces_1.ReplaceNodeOperation(sourceFile, entryModuleIdentifier, ts.factory.createPropertyAccessExpression(idNgFactory, ts.factory.createIdentifier(className))),
|
|
69
69
|
// Replace the platformBrowserDynamic import.
|
|
70
|
-
...insert_import_1.insertStarImport(sourceFile, idPlatformBrowser, '@angular/platform-browser'), new interfaces_1.ReplaceNodeOperation(sourceFile, platformBrowserDynamicIdentifier, ts.
|
|
70
|
+
...insert_import_1.insertStarImport(sourceFile, idPlatformBrowser, '@angular/platform-browser'), new interfaces_1.ReplaceNodeOperation(sourceFile, platformBrowserDynamicIdentifier, ts.factory.createPropertyAccessExpression(idPlatformBrowser, 'platformBrowser')), new interfaces_1.ReplaceNodeOperation(sourceFile, bootstrapModuleIdentifier, ts.factory.createIdentifier(bootstrapIdentifier)));
|
|
71
71
|
});
|
|
72
72
|
return ops;
|
|
73
73
|
};
|
|
@@ -14,12 +14,13 @@ function replaceResources(shouldTransform, getTypeChecker, directTemplateLoading
|
|
|
14
14
|
const typeChecker = getTypeChecker();
|
|
15
15
|
const resourceImportDeclarations = [];
|
|
16
16
|
const moduleKind = context.getCompilerOptions().module;
|
|
17
|
+
const nodeFactory = context.factory;
|
|
17
18
|
const visitNode = (node) => {
|
|
18
19
|
if (ts.isClassDeclaration(node)) {
|
|
19
20
|
const decorators = ts.visitNodes(node.decorators, node => ts.isDecorator(node)
|
|
20
|
-
? visitDecorator(node, typeChecker, directTemplateLoading, resourceImportDeclarations, moduleKind)
|
|
21
|
+
? visitDecorator(nodeFactory, node, typeChecker, directTemplateLoading, resourceImportDeclarations, moduleKind)
|
|
21
22
|
: node);
|
|
22
|
-
return
|
|
23
|
+
return nodeFactory.updateClassDeclaration(node, decorators, node.modifiers, node.name, node.typeParameters, node.heritageClauses, node.members);
|
|
23
24
|
}
|
|
24
25
|
return ts.visitEachChild(node, visitNode, context);
|
|
25
26
|
};
|
|
@@ -30,7 +31,7 @@ function replaceResources(shouldTransform, getTypeChecker, directTemplateLoading
|
|
|
30
31
|
const updatedSourceFile = ts.visitNode(sourceFile, visitNode);
|
|
31
32
|
if (resourceImportDeclarations.length) {
|
|
32
33
|
// Add resource imports
|
|
33
|
-
return
|
|
34
|
+
return context.factory.updateSourceFile(updatedSourceFile, ts.setTextRange(context.factory.createNodeArray([
|
|
34
35
|
...resourceImportDeclarations,
|
|
35
36
|
...updatedSourceFile.statements,
|
|
36
37
|
]), updatedSourceFile.statements));
|
|
@@ -40,7 +41,7 @@ function replaceResources(shouldTransform, getTypeChecker, directTemplateLoading
|
|
|
40
41
|
};
|
|
41
42
|
}
|
|
42
43
|
exports.replaceResources = replaceResources;
|
|
43
|
-
function visitDecorator(node, typeChecker, directTemplateLoading, resourceImportDeclarations, moduleKind) {
|
|
44
|
+
function visitDecorator(nodeFactory, node, typeChecker, directTemplateLoading, resourceImportDeclarations, moduleKind) {
|
|
44
45
|
if (!isComponentDecorator(node, typeChecker)) {
|
|
45
46
|
return node;
|
|
46
47
|
}
|
|
@@ -57,18 +58,18 @@ function visitDecorator(node, typeChecker, directTemplateLoading, resourceImport
|
|
|
57
58
|
const styleReplacements = [];
|
|
58
59
|
// visit all properties
|
|
59
60
|
let properties = ts.visitNodes(objectExpression.properties, node => ts.isObjectLiteralElementLike(node)
|
|
60
|
-
? visitComponentMetadata(node, styleReplacements, directTemplateLoading, resourceImportDeclarations, moduleKind)
|
|
61
|
+
? visitComponentMetadata(nodeFactory, node, styleReplacements, directTemplateLoading, resourceImportDeclarations, moduleKind)
|
|
61
62
|
: node);
|
|
62
63
|
// replace properties with updated properties
|
|
63
64
|
if (styleReplacements.length > 0) {
|
|
64
|
-
const styleProperty =
|
|
65
|
-
properties =
|
|
65
|
+
const styleProperty = nodeFactory.createPropertyAssignment(nodeFactory.createIdentifier('styles'), nodeFactory.createArrayLiteralExpression(styleReplacements));
|
|
66
|
+
properties = nodeFactory.createNodeArray([...properties, styleProperty]);
|
|
66
67
|
}
|
|
67
|
-
return
|
|
68
|
-
|
|
68
|
+
return nodeFactory.updateDecorator(node, nodeFactory.updateCallExpression(decoratorFactory, decoratorFactory.expression, decoratorFactory.typeArguments, [
|
|
69
|
+
nodeFactory.updateObjectLiteralExpression(objectExpression, properties),
|
|
69
70
|
]));
|
|
70
71
|
}
|
|
71
|
-
function visitComponentMetadata(node, styleReplacements, directTemplateLoading, resourceImportDeclarations, moduleKind) {
|
|
72
|
+
function visitComponentMetadata(nodeFactory, node, styleReplacements, directTemplateLoading, resourceImportDeclarations, moduleKind) {
|
|
72
73
|
if (!ts.isPropertyAssignment(node) || ts.isComputedPropertyName(node.name)) {
|
|
73
74
|
return node;
|
|
74
75
|
}
|
|
@@ -77,11 +78,11 @@ function visitComponentMetadata(node, styleReplacements, directTemplateLoading,
|
|
|
77
78
|
case 'moduleId':
|
|
78
79
|
return undefined;
|
|
79
80
|
case 'templateUrl':
|
|
80
|
-
const importName = createResourceImport(node.initializer, directTemplateLoading ? '!raw-loader!' : '', resourceImportDeclarations, moduleKind);
|
|
81
|
+
const importName = createResourceImport(nodeFactory, node.initializer, directTemplateLoading ? '!raw-loader!' : '', resourceImportDeclarations, moduleKind);
|
|
81
82
|
if (!importName) {
|
|
82
83
|
return node;
|
|
83
84
|
}
|
|
84
|
-
return
|
|
85
|
+
return nodeFactory.updatePropertyAssignment(node, nodeFactory.createIdentifier('template'), importName);
|
|
85
86
|
case 'styles':
|
|
86
87
|
case 'styleUrls':
|
|
87
88
|
if (!ts.isArrayLiteralExpression(node.initializer)) {
|
|
@@ -93,9 +94,9 @@ function visitComponentMetadata(node, styleReplacements, directTemplateLoading,
|
|
|
93
94
|
return node;
|
|
94
95
|
}
|
|
95
96
|
if (isInlineStyles) {
|
|
96
|
-
return
|
|
97
|
+
return nodeFactory.createStringLiteral(node.text);
|
|
97
98
|
}
|
|
98
|
-
return createResourceImport(node, undefined, resourceImportDeclarations, moduleKind) || node;
|
|
99
|
+
return createResourceImport(nodeFactory, node, undefined, resourceImportDeclarations, moduleKind) || node;
|
|
99
100
|
});
|
|
100
101
|
// Styles should be placed first
|
|
101
102
|
if (isInlineStyles) {
|
|
@@ -127,18 +128,18 @@ function isComponentDecorator(node, typeChecker) {
|
|
|
127
128
|
}
|
|
128
129
|
return false;
|
|
129
130
|
}
|
|
130
|
-
function createResourceImport(node, loader, resourceImportDeclarations, moduleKind = ts.ModuleKind.ES2015) {
|
|
131
|
+
function createResourceImport(nodeFactory, node, loader, resourceImportDeclarations, moduleKind = ts.ModuleKind.ES2015) {
|
|
131
132
|
const url = getResourceUrl(node, loader);
|
|
132
133
|
if (!url) {
|
|
133
134
|
return null;
|
|
134
135
|
}
|
|
135
|
-
const urlLiteral =
|
|
136
|
+
const urlLiteral = nodeFactory.createStringLiteral(url);
|
|
136
137
|
if (moduleKind < ts.ModuleKind.ES2015) {
|
|
137
|
-
return
|
|
138
|
+
return nodeFactory.createPropertyAccessExpression(nodeFactory.createCallExpression(nodeFactory.createIdentifier('require'), [], [urlLiteral]), 'default');
|
|
138
139
|
}
|
|
139
140
|
else {
|
|
140
|
-
const importName =
|
|
141
|
-
resourceImportDeclarations.push(
|
|
141
|
+
const importName = nodeFactory.createIdentifier(`__NG_CLI_RESOURCE__${resourceImportDeclarations.length}`);
|
|
142
|
+
resourceImportDeclarations.push(nodeFactory.createImportDeclaration(undefined, undefined, nodeFactory.createImportClause(false, importName, undefined), urlLiteral));
|
|
142
143
|
return importName;
|
|
143
144
|
}
|
|
144
145
|
}
|
|
@@ -57,14 +57,14 @@ function replaceServerBootstrap(shouldTransform, getEntryModule, getTypeChecker)
|
|
|
57
57
|
return;
|
|
58
58
|
}
|
|
59
59
|
const platformDynamicServerIdentifier = innerCallExpr.expression;
|
|
60
|
-
const idPlatformServer = ts.createUniqueName('__NgCli_bootstrap_');
|
|
61
|
-
const idNgFactory = ts.createUniqueName('__NgCli_bootstrap_');
|
|
60
|
+
const idPlatformServer = ts.factory.createUniqueName('__NgCli_bootstrap_');
|
|
61
|
+
const idNgFactory = ts.factory.createUniqueName('__NgCli_bootstrap_');
|
|
62
62
|
// Add the transform operations.
|
|
63
63
|
ops.push(
|
|
64
64
|
// Replace the entry module import.
|
|
65
|
-
...insert_import_1.insertStarImport(sourceFile, idNgFactory, factoryModulePath), new interfaces_1.ReplaceNodeOperation(sourceFile, entryModuleIdentifier, ts.
|
|
65
|
+
...insert_import_1.insertStarImport(sourceFile, idNgFactory, factoryModulePath), new interfaces_1.ReplaceNodeOperation(sourceFile, entryModuleIdentifier, ts.factory.createPropertyAccessExpression(idNgFactory, ts.factory.createIdentifier(factoryClassName))),
|
|
66
66
|
// Replace the platformBrowserDynamic import.
|
|
67
|
-
...insert_import_1.insertStarImport(sourceFile, idPlatformServer, '@angular/platform-server'), new interfaces_1.ReplaceNodeOperation(sourceFile, platformDynamicServerIdentifier, ts.
|
|
67
|
+
...insert_import_1.insertStarImport(sourceFile, idPlatformServer, '@angular/platform-server'), new interfaces_1.ReplaceNodeOperation(sourceFile, platformDynamicServerIdentifier, ts.factory.createPropertyAccessExpression(idPlatformServer, 'platformServer')), new interfaces_1.ReplaceNodeOperation(sourceFile, bootstrapModuleIdentifier, ts.factory.createIdentifier('bootstrapModuleFactory')));
|
|
68
68
|
}
|
|
69
69
|
else if (callExpr.expression.kind === ts.SyntaxKind.Identifier) {
|
|
70
70
|
// Figure out if it is renderModule
|
|
@@ -73,20 +73,20 @@ function replaceServerBootstrap(shouldTransform, getEntryModule, getTypeChecker)
|
|
|
73
73
|
return;
|
|
74
74
|
}
|
|
75
75
|
const renderModuleIdentifier = identifierExpr;
|
|
76
|
-
const idPlatformServer = ts.createUniqueName('__NgCli_bootstrap_');
|
|
77
|
-
const idNgFactory = ts.createUniqueName('__NgCli_bootstrap_');
|
|
76
|
+
const idPlatformServer = ts.factory.createUniqueName('__NgCli_bootstrap_');
|
|
77
|
+
const idNgFactory = ts.factory.createUniqueName('__NgCli_bootstrap_');
|
|
78
78
|
ops.push(
|
|
79
79
|
// Replace the entry module import.
|
|
80
|
-
...insert_import_1.insertStarImport(sourceFile, idNgFactory, factoryModulePath), new interfaces_1.ReplaceNodeOperation(sourceFile, entryModuleIdentifier, ts.
|
|
80
|
+
...insert_import_1.insertStarImport(sourceFile, idNgFactory, factoryModulePath), new interfaces_1.ReplaceNodeOperation(sourceFile, entryModuleIdentifier, ts.factory.createPropertyAccessExpression(idNgFactory, ts.factory.createIdentifier(factoryClassName))),
|
|
81
81
|
// Replace the renderModule import.
|
|
82
|
-
...insert_import_1.insertStarImport(sourceFile, idPlatformServer, '@angular/platform-server'), new interfaces_1.ReplaceNodeOperation(sourceFile, renderModuleIdentifier, ts.
|
|
82
|
+
...insert_import_1.insertStarImport(sourceFile, idPlatformServer, '@angular/platform-server'), new interfaces_1.ReplaceNodeOperation(sourceFile, renderModuleIdentifier, ts.factory.createPropertyAccessExpression(idPlatformServer, 'renderModuleFactory')));
|
|
83
83
|
}
|
|
84
84
|
}
|
|
85
85
|
else if (entryModuleIdentifier.parent.kind === ts.SyntaxKind.PropertyAssignment) {
|
|
86
86
|
// This is for things that accept a module as a property in a config object
|
|
87
87
|
// .ie the express engine
|
|
88
|
-
const idNgFactory = ts.createUniqueName('__NgCli_bootstrap_');
|
|
89
|
-
ops.push(...insert_import_1.insertStarImport(sourceFile, idNgFactory, factoryModulePath), new interfaces_1.ReplaceNodeOperation(sourceFile, entryModuleIdentifier, ts.
|
|
88
|
+
const idNgFactory = ts.factory.createUniqueName('__NgCli_bootstrap_');
|
|
89
|
+
ops.push(...insert_import_1.insertStarImport(sourceFile, idNgFactory, factoryModulePath), new interfaces_1.ReplaceNodeOperation(sourceFile, entryModuleIdentifier, ts.factory.createPropertyAccessExpression(idNgFactory, ts.factory.createIdentifier(factoryClassName))));
|
|
90
90
|
}
|
|
91
91
|
});
|
|
92
92
|
return ops;
|