Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings
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 andcommitted
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

File tree

10 files changed

+198
-18
lines changed

10 files changed

+198
-18
lines changed

‎.gitignore‎

Lines changed: 4 additions & 0 deletions
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‎

Lines changed: 1 addition & 1 deletion
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‎

Lines changed: 2 additions & 2 deletions
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‎

Lines changed: 2 additions & 1 deletion
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‎

Lines changed: 15 additions & 14 deletions
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({
Lines changed: 3 additions & 0 deletions
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‎

Lines changed: 66 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

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

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎transformers/ns-replace-bootstrap.ts‎

Lines changed: 103 additions & 0 deletions
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‎

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

AltStyle によって変換されたページ (->オリジナル) /