Skip to content
This repository was archived by the owner on Aug 7, 2021. It is now read-only.

Commit c016418

Browse files
Alexander Vakrilovsis0k0
Alexander Vakrilov
authored andcommittedAug 17, 2018
feat: NativeScript bootstrap transformer (#634)
The bootstrap transformer will automatically replace the platform and bootstrap calls inside `main.ts` when building with AOT. This will eliminate the need for `main.aot.ts` and `app.module.ngfactory.d.ts` files in templates. This depends on angular/angular-cli#11786 going public
1 parent 42b0c0b commit c016418

10 files changed

+198
-18
lines changed
 

‎.gitignore

+4
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ plugins/NativeScriptAngularCompilerPlugin.d.ts
77
plugins/NativeScriptAngularCompilerPlugin.js
88
plugins/NativeScriptAngularCompilerPlugin.js.map
99

10+
transformers/ns-replace-bootstrap.d.ts
11+
transformers/ns-replace-bootstrap.js
12+
transformers/ns-replace-bootstrap.js.map
13+
1014
plugins/PlatformFSPlugin.d.ts
1115
plugins/PlatformFSPlugin.js
1216
plugins/PlatformFSPlugin.js.map

‎dependencyManager.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ function getRequiredDeps(packageJson) {
9090
};
9191

9292
if (!dependsOn(packageJson, "@angular-devkit/build-angular")) {
93-
deps["@ngtools/webpack"] = "~6.1.0";
93+
deps["@ngtools/webpack"] = "~6.2.0-beta.3";
9494
}
9595

9696
return deps;

‎index.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ const {
88
isIos,
99
} = require("./projectHelpers");
1010

11-
Object.assign(exports, require('./plugins'));
12-
Object.assign(exports, require('./host/resolver'));
11+
Object.assign(exports, require("./plugins"));
12+
Object.assign(exports, require("./host/resolver"));
1313

1414
exports.getAotEntryModule = function (appDirectory) {
1515
verifyEntryModuleDirectory(appDirectory);

‎package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@
9494
"devDependencies": {
9595
"@types/node": "^8.0.0",
9696
"conventional-changelog-cli": "^1.3.22",
97-
"typescript": "~2.7.2"
97+
"typescript": "~2.9.1",
98+
"@ngtools/webpack": "~6.2.0-beta.3"
9899
}
99100
}

‎templates/webpack.angular.js

+15-14
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ const { join, relative, resolve, sep } = require("path");
33
const webpack = require("webpack");
44
const nsWebpack = require("nativescript-dev-webpack");
55
const nativescriptTarget = require("nativescript-dev-webpack/nativescript-target");
6+
const { nsReplaceBootstrap } = require("nativescript-dev-webpack/transformers/ns-replace-bootstrap");
67
const CleanWebpackPlugin = require("clean-webpack-plugin");
78
const CopyWebpackPlugin = require("copy-webpack-plugin");
89
const { BundleAnalyzerPlugin } = require("webpack-bundle-analyzer");
@@ -46,11 +47,18 @@ module.exports = env => {
4647
const appFullPath = resolve(projectRoot, appPath);
4748
const appResourcesFullPath = resolve(projectRoot, appResourcesPath);
4849

49-
const entryModule = aot ?
50-
nsWebpack.getAotEntryModule(appFullPath) :
51-
`${nsWebpack.getEntryModule(appFullPath)}.ts`;
50+
const entryModule = `${nsWebpack.getEntryModule(appFullPath)}.ts`;
5251
const entryPath = `.${sep}${entryModule}`;
5352

53+
const ngCompilerPlugin = new AngularCompilerPlugin({
54+
hostReplacementPaths: nsWebpack.getResolver([platform, "tns"]),
55+
platformTransformers: aot ? [nsReplaceBootstrap(() => ngCompilerPlugin)] : null,
56+
mainPath: resolve(appPath, entryModule),
57+
tsConfigPath: join(__dirname, "tsconfig.esm.json"),
58+
skipCodeGeneration: !aot,
59+
sourceMap: !!sourceMap,
60+
});
61+
5462
const config = {
5563
mode: uglify ? "production" : "development",
5664
context: appFullPath,
@@ -107,7 +115,7 @@ module.exports = env => {
107115
test: (module, chunks) => {
108116
const moduleName = module.nameForCondition ? module.nameForCondition() : '';
109117
return /[\\/]node_modules[\\/]/.test(moduleName) ||
110-
appComponents.some(comp => comp === moduleName);
118+
appComponents.some(comp => comp === moduleName);
111119
},
112120
enforce: true,
113121
},
@@ -195,10 +203,9 @@ module.exports = env => {
195203
// Define useful constants like TNS_WEBPACK
196204
new webpack.DefinePlugin({
197205
"global.TNS_WEBPACK": "true",
198-
"process": undefined,
199206
}),
200207
// Remove all files from the out dir.
201-
new CleanWebpackPlugin([ `${dist}/**/*` ]),
208+
new CleanWebpackPlugin([`${dist}/**/*`]),
202209
// Copy native app resources to out dir.
203210
new CopyWebpackPlugin([
204211
{
@@ -221,19 +228,13 @@ module.exports = env => {
221228
// For instructions on how to set up workers with webpack
222229
// check out https://github.com/nativescript/worker-loader
223230
new NativeScriptWorkerPlugin(),
224-
225-
new AngularCompilerPlugin({
226-
hostReplacementPaths: nsWebpack.getResolver([platform, "tns"]),
227-
mainPath: resolve(appPath, "main.ts"),
228-
tsConfigPath: join(__dirname, "tsconfig.esm.json"),
229-
skipCodeGeneration: !aot,
230-
sourceMap: !!sourceMap,
231-
}),
231+
ngCompilerPlugin,
232232
// Does IPC communication with the {N} CLI to notify events when running in watch mode.
233233
new nsWebpack.WatchStateLoggerPlugin(),
234234
],
235235
};
236236

237+
237238
if (report) {
238239
// Generate report files for bundles content
239240
config.plugins.push(new BundleAnalyzerPlugin({
+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import * as ts from 'typescript';
2+
import { AngularCompilerPlugin } from '@ngtools/webpack';
3+
export declare function nsReplaceBootstrap(getNgCompiler: () => AngularCompilerPlugin): ts.TransformerFactory<ts.SourceFile>;

‎transformers/ns-replace-bootstrap.js

+66
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎transformers/ns-replace-bootstrap.js.map

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎transformers/ns-replace-bootstrap.ts

+103
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
import { dirname, relative } from 'path';
2+
import * as ts from 'typescript';
3+
import {
4+
StandardTransform,
5+
TransformOperation,
6+
collectDeepNodes,
7+
insertStarImport,
8+
ReplaceNodeOperation,
9+
makeTransform
10+
} from "@ngtools/webpack/src/transformers";
11+
import { workaroundResolve } from '@ngtools/webpack/src/compiler_host';
12+
import { AngularCompilerPlugin } from '@ngtools/webpack';
13+
14+
export function nsReplaceBootstrap(getNgCompiler: () => AngularCompilerPlugin): ts.TransformerFactory<ts.SourceFile> {
15+
const shouldTransform = (fileName) => !fileName.endsWith('.ngfactory.ts') && !fileName.endsWith('.ngstyle.ts');
16+
const getTypeChecker = () => getNgCompiler().typeChecker;
17+
18+
const standardTransform: StandardTransform = function (sourceFile: ts.SourceFile) {
19+
const ops: TransformOperation[] = [];
20+
const ngCompiler = getNgCompiler();
21+
22+
const entryModule = ngCompiler.entryModule
23+
? { path: workaroundResolve(ngCompiler.entryModule.path), className: getNgCompiler().entryModule.className }
24+
: ngCompiler.entryModule;
25+
26+
if (!shouldTransform(sourceFile.fileName) || !entryModule) {
27+
return ops;
28+
}
29+
30+
// Find all identifiers.
31+
const entryModuleIdentifiers = collectDeepNodes<ts.Identifier>(sourceFile,
32+
ts.SyntaxKind.Identifier)
33+
.filter(identifier => identifier.text === entryModule.className);
34+
35+
if (entryModuleIdentifiers.length === 0) {
36+
return [];
37+
}
38+
39+
const relativeEntryModulePath = relative(dirname(sourceFile.fileName), entryModule.path);
40+
const normalizedEntryModulePath = `./${relativeEntryModulePath}`.replace(/\\/g, '/');
41+
42+
// Find the bootstrap calls.
43+
entryModuleIdentifiers.forEach(entryModuleIdentifier => {
44+
// Figure out if it's a `platformNativeScriptDynamic().bootstrapModule(AppModule)` call.
45+
if (!(
46+
entryModuleIdentifier.parent
47+
&& entryModuleIdentifier.parent.kind === ts.SyntaxKind.CallExpression
48+
)) {
49+
return;
50+
}
51+
52+
const callExpr = entryModuleIdentifier.parent as ts.CallExpression;
53+
54+
if (callExpr.expression.kind !== ts.SyntaxKind.PropertyAccessExpression) {
55+
return;
56+
}
57+
58+
const propAccessExpr = callExpr.expression as ts.PropertyAccessExpression;
59+
60+
if (propAccessExpr.name.text !== 'bootstrapModule'
61+
|| propAccessExpr.expression.kind !== ts.SyntaxKind.CallExpression) {
62+
return;
63+
}
64+
65+
const bootstrapModuleIdentifier = propAccessExpr.name;
66+
const innerCallExpr = propAccessExpr.expression as ts.CallExpression;
67+
68+
if (!(
69+
innerCallExpr.expression.kind === ts.SyntaxKind.Identifier
70+
&& (innerCallExpr.expression as ts.Identifier).text === 'platformNativeScriptDynamic'
71+
)) {
72+
return;
73+
}
74+
75+
const platformBrowserDynamicIdentifier = innerCallExpr.expression as ts.Identifier;
76+
77+
const idPlatformBrowser = ts.createUniqueName('__NgCli_bootstrap_');
78+
const idNgFactory = ts.createUniqueName('__NgCli_bootstrap_');
79+
80+
// Add the transform operations.
81+
const factoryClassName = entryModule.className + 'NgFactory';
82+
const factoryModulePath = normalizedEntryModulePath + '.ngfactory';
83+
ops.push(
84+
// Replace the entry module import.
85+
...insertStarImport(sourceFile, idNgFactory, factoryModulePath),
86+
new ReplaceNodeOperation(sourceFile, entryModuleIdentifier,
87+
ts.createPropertyAccess(idNgFactory, ts.createIdentifier(factoryClassName))),
88+
89+
// Replace the platformBrowserDynamic import.
90+
...insertStarImport(sourceFile, idPlatformBrowser, 'nativescript-angular/platform-static'),
91+
new ReplaceNodeOperation(sourceFile, platformBrowserDynamicIdentifier,
92+
ts.createPropertyAccess(idPlatformBrowser, 'platformNativeScript')),
93+
94+
new ReplaceNodeOperation(sourceFile, bootstrapModuleIdentifier,
95+
ts.createIdentifier('bootstrapModuleFactory')),
96+
);
97+
});
98+
99+
return ops;
100+
};
101+
102+
return makeTransform(standardTransform, getTypeChecker);
103+
}

‎tsconfig.json

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
"files": [
1111
"plugins/PlatformFSPlugin.ts",
1212
"plugins/WatchStateLoggerPlugin.ts",
13+
"transformers/ns-replace-bootstrap.ts",
1314
"host/resolver.ts"
1415
]
1516
}

0 commit comments

Comments
 (0)
This repository has been archived.