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

Commit 1b5dcdc

Browse files
authored
Local snapshot support (#181)
Introduce support for v8 heap snapshot generation
1 parent 46519ba commit 1b5dcdc

39 files changed

+949
-156
lines changed

Diff for: bin/generate-android-snapshot

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#!/usr/bin/env node
2+
const ProjectSnapshotGenerator = require("../snapshot/android/project-snapshot-generator");
3+
const args = require("../snapshot/android/project-snapshot-generator-cli-ags-parser")();
4+
5+
const generator = new ProjectSnapshotGenerator(args);
6+
generator.generate(args);

Diff for: bin/generate-android-snapshot.cmd

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
@node %~dp0\generate-android-snapshot %*

Diff for: bin/ns-bundle

+23-8
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ const { spawn } = require("child_process");
44
const { resolve: pathResolve } = require("path");
55
const { existsSync } = require("fs");
66
const { getPackageJson } = require("../projectHelpers");
7+
const { isVersionGte } = require("../utils");
78

89
const PROJECT_DIR = pathResolve(__dirname, "../../../");
910
const packageJson = getPackageJson(PROJECT_DIR);
@@ -15,6 +16,7 @@ if (!process.env.npm_config_argv) {
1516
const escape = arg => `"${arg}"`;
1617
const isTnsCommand = flag => flag.endsWith("-app");
1718
const shouldUglify = () => process.env.npm_config_uglify;
19+
const shouldSnapshot = (platform) => platform == "android" && require("os").type() != "Windows_NT" && process.env.npm_config_snapshot;
1820

1921
const npmArgs = JSON.parse(process.env.npm_config_argv).original;
2022
const tnsArgs = getTnsArgs(npmArgs).map(escape);
@@ -28,6 +30,7 @@ function getTnsArgs(args) {
2830
"--android",
2931
"--ios",
3032
"--uglify",
33+
"--snapshot",
3134
"--nobundle",
3235
];
3336

@@ -37,24 +40,29 @@ function getTnsArgs(args) {
3740
execute(options);
3841

3942
function execute(options) {
40-
let commands = [];
4143
const platform = options.platform;
44+
let commands = [
45+
() => runTns("prepare", platform)
46+
];
4247

4348
if (options.bundle) {
4449
commands = [
50+
...commands,
4551
() => cleanApp(platform),
52+
() => cleanSnapshotArtefacts(),
4653
() => cleanBuildArtifacts(platform),
4754
() => webpack(platform),
4855
];
4956
}
5057

58+
if (shouldSnapshot(platform)) {
59+
commands.push(() => installSnapshotArtefacts());
60+
}
61+
5162
// If "build-app" or "start-app" is specified,
5263
// the respective command should be run last.
53-
// Otherwise, the app should be just prepared.
5464
if (options.command) {
5565
commands.push(() => runTns(options.command, platform));
56-
} else {
57-
commands.shift(() => runTns("prepare", platform))
5866
}
5967
return commands.reduce((current, next) => current.then(next), Promise.resolve());
6068
}
@@ -65,12 +73,10 @@ function cleanBuildArtifacts(platform) {
6573
return resolve();
6674
}
6775

68-
getTnsVersion().then(versionString => {
69-
const version = versionToNumber(versionString);
70-
76+
getTnsVersion().then(version => {
7177
// the android build artifacts should be cleaned manually
7278
// for nativescript-cli v3.0.1 and below or if using uglify
73-
if (version <= 301 || shouldUglify()) {
79+
if (isVersionGte(version, "3.0.1") || shouldUglify()) {
7480
gradlewClean().then(resolve).catch(throwError);
7581
} else {
7682
return resolve();
@@ -79,6 +85,14 @@ function cleanBuildArtifacts(platform) {
7985
});
8086
}
8187

88+
function cleanSnapshotArtefacts() {
89+
require("../snapshot/android/project-snapshot-generator").cleanSnapshotArtefacts(PROJECT_DIR);
90+
}
91+
92+
function installSnapshotArtefacts() {
93+
require("../snapshot/android/project-snapshot-generator").installSnapshotArtefacts(PROJECT_DIR);
94+
}
95+
8296
function gradlewClean() {
8397
return new Promise((resolve, reject) => {
8498
const platformsPath = pathResolve(PROJECT_DIR, "platforms", "android")
@@ -135,6 +149,7 @@ function webpack(platform) {
135149
`--progress`,
136150
`--env.${platform}`,
137151
shouldUglify() && `--env.uglify`,
152+
shouldSnapshot(platform) && `--env.snapshot`
138153
];
139154

140155
spawnChildProcess(...args)

Diff for: bin/update-ns-webpack

+13-7
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,20 @@
11
#!/usr/bin/env node
2-
const path = require("path");
3-
const fs = require("fs");
2+
const { resolve } = require("path");
43

5-
const helpers = require("../projectHelpers");
6-
const forceUpdateProjectDeps = require("../dependencyManager").forceUpdateProjectDeps;
4+
const { getPackageJson, writePackageJson } = require("../projectHelpers");
5+
const { forceUpdateProjectDeps } = require("../dependencyManager");
6+
const { editExistingProjectFiles } = require("../projectFilesManager");
77

8-
const PROJECT_DIR = path.resolve(__dirname, "../../../");
9-
const packageJson = helpers.getPackageJson(PROJECT_DIR);
8+
const PROJECT_DIR = resolve(__dirname, "../../../");
109

10+
console.info("Updating dev dependencies...");
11+
const packageJson = getPackageJson(PROJECT_DIR);
1112
const { deps } = forceUpdateProjectDeps(packageJson);
1213
packageJson.devDependencies = deps;
14+
writePackageJson(packageJson, PROJECT_DIR);
15+
16+
console.info("\nUpdating configuration files...");
17+
editExistingProjectFiles(PROJECT_DIR);
18+
19+
console.info("\nProject successfully updated! Don't forget to run `npm install`");
1320

14-
helpers.writePackageJson(packageJson, PROJECT_DIR);

Diff for: index.js

+20-102
Original file line numberDiff line numberDiff line change
@@ -1,84 +1,19 @@
1-
var sources = require("webpack-sources");
2-
var fs = require("fs");
3-
var path = require("path");
1+
const path = require("path");
2+
const { existsSync } = require("fs");
43

5-
var projectDir = path.dirname(path.dirname(__dirname));
6-
var packageJsonPath = path.join(projectDir, "package.json");
7-
var packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
4+
const { getPackageJson, isAngular } = require("./projectHelpers");
5+
const { sanitize } = require("./utils");
86

9-
var isAngular = Object.keys(packageJson.dependencies).filter(function (dependency) {
10-
return /^@angular\b/.test(dependency);
11-
}).length > 0;
7+
const PROJECT_DIR = path.dirname(path.dirname(__dirname));
8+
const APP_DIR = path.join(PROJECT_DIR, "app");
129

10+
Object.assign(exports, require('./plugins'));
1311

14-
if (isAngular) {
15-
exports.UrlResolvePlugin = require("./resource-resolver-plugins/UrlResolvePlugin");
12+
if (isAngular({projectDir: PROJECT_DIR})) {
13+
Object.assign(exports, require('./plugins/angular'));
1614
}
1715

18-
//HACK: changes the JSONP chunk eval function to `global["nativescriptJsonp"]`
19-
// applied to tns-java-classes.js only
20-
exports.NativeScriptJsonpPlugin = function () {
21-
};
22-
23-
exports.NativeScriptJsonpPlugin.prototype.apply = function (compiler) {
24-
compiler.plugin("compilation", function (compilation) {
25-
compilation.plugin("optimize-chunk-assets", function (chunks, callback) {
26-
chunks.forEach(function (chunk) {
27-
chunk.files.forEach(function (file) {
28-
if (file === "vendor.js") {
29-
var src = compilation.assets[file];
30-
var code = src.source();
31-
var match = code.match(/window\["nativescriptJsonp"\]/);
32-
if (match) {
33-
compilation.assets[file] = new sources.ConcatSource(code.replace(/window\["nativescriptJsonp"\]/g, "global[\"nativescriptJsonp\"]"));
34-
}
35-
}
36-
});
37-
});
38-
callback();
39-
});
40-
});
41-
};
42-
43-
exports.GenerateBundleStarterPlugin = function (bundles) {
44-
this.bundles = bundles;
45-
};
46-
47-
exports.GenerateBundleStarterPlugin.prototype = {
48-
apply: function (compiler) {
49-
var plugin = this;
50-
plugin.webpackContext = compiler.options.context;
51-
52-
compiler.plugin("emit", function (compilation, cb) {
53-
compilation.assets["package.json"] = plugin.generatePackageJson();
54-
compilation.assets["starter.js"] = plugin.generateStarterModule();
55-
plugin.generateTnsJavaClasses(compilation);
56-
57-
cb();
58-
});
59-
},
60-
generateTnsJavaClasses: function (compilation) {
61-
const path = compilation.compiler.outputPath;
62-
const isAndroid = path.indexOf("android") > -1;
63-
64-
if (isAndroid) {
65-
compilation.assets["tns-java-classes.js"] = new sources.RawSource("");
66-
}
67-
},
68-
generatePackageJson: function () {
69-
var packageJsonPath = path.join(this.webpackContext, "package.json");
70-
var packageData = JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
71-
packageData.main = "starter";
72-
73-
return new sources.RawSource(JSON.stringify(packageData, null, 4));
74-
},
75-
generateStarterModule: function () {
76-
var moduleSource = this.bundles.map(function (bundle) {
77-
return "require(\"" + bundle + "\");";
78-
}).join("\n");
79-
return new sources.RawSource(moduleSource);
80-
},
81-
};
16+
exports.uglifyMangleExcludes = require("./mangle-excludes");
8217

8318
exports.getEntryModule = function () {
8419
const maybePackageJsonEntry = getPackageJsonEntry();
@@ -90,46 +25,29 @@ exports.getEntryModule = function () {
9025
return maybeAotEntry || maybePackageJsonEntry;
9126
};
9227

93-
exports.getAppPath = function (platform) {
94-
var projectDir = path.dirname(path.dirname(__dirname));
95-
28+
exports.getAppPath = platform => {
9629
if (/ios/i.test(platform)) {
97-
var appName = path.basename(projectDir);
98-
var sanitizedName = appName.split("").filter(function (c) {
99-
return /[a-zA-Z0-9]/.test(c);
100-
}).join("");
101-
return "platforms/ios/" + sanitizedName + "/app";
30+
const appName = path.basename(PROJECT_DIR);
31+
const sanitizedName = sanitize(appName);
32+
33+
return `platforms/ios/${sanitizedName}/app`;
10234
} else if (/android/i.test(platform)) {
103-
return path.join(projectDir, "platforms/android/src/main/assets/app");
35+
return path.join(PROJECT_DIR, "platforms/android/src/main/assets/app");
10436
} else {
105-
throw new Error("Invalid platform: " + platform);
37+
throw new Error(`Invalid platform: ${platform}`);
10638
}
10739
};
10840

109-
exports.uglifyMangleExcludes = require("./mangle-excludes");
110-
11141
function getPackageJsonEntry() {
112-
const packageJsonSource = getAppPackageJsonSource();
42+
const packageJsonSource = getPackageJson(APP_DIR);
11343
const entry = packageJsonSource.main;
11444

11545
return entry ? entry.replace(/\.js$/i, "") : null;
11646
}
11747

118-
function getAppPackageJsonSource() {
119-
const projectDir = getProjectDir();
120-
const appPackageJsonPath = path.join(projectDir, "app", "package.json");
121-
122-
return JSON.parse(fs.readFileSync(appPackageJsonPath, "utf8"));
123-
}
124-
12548
function getAotEntry(entry) {
12649
const aotEntry = `${entry}.aot.ts`;
127-
const projectDir = getProjectDir();
128-
const aotEntryPath = path.join(projectDir, "app", aotEntry);
129-
130-
return fs.existsSync(aotEntryPath) ? aotEntry : null;
131-
}
50+
const aotEntryPath = path.join(APP_DIR, aotEntry);
13251

133-
function getProjectDir() {
134-
return path.dirname(path.dirname(__dirname));
52+
return existsSync(aotEntryPath) ? aotEntry : null;
13553
}

Diff for: installer.js

-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ function install() {
1313
const packageJson = helpers.getPackageJson(PROJECT_DIR);
1414

1515
projectFilesManager.addProjectFiles(PROJECT_DIR, APP_DIR);
16-
projectFilesManager.editExistingProjectFiles(PROJECT_DIR);
1716

1817
const scripts = packageJson.scripts || {};
1918
npmScriptsManager.removeDeprecatedNpmScripts(scripts);

Diff for: npmScriptsManager.js

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ const SCRIPT_TEMPLATES = Object.freeze({
33
"start-[PLATFORM]-bundle": "npm run ns-bundle --[PLATFORM] --run-app",
44
"build-[PLATFORM]-bundle": "npm run ns-bundle --[PLATFORM] --build-app",
55
"publish-ios-bundle": "npm run ns-bundle --ios --publish-app",
6+
"generate-android-snapshot": "generate-android-snapshot --projectRoot . --targetArchs arm,arm64 --install"
67
});
78

89
const DEPRECATED_SCRIPT_TEMPLATES = Object.freeze([

Diff for: package.json

+6-2
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,12 @@
2222
"remove-ns-webpack": "./bin/remove-ns-webpack",
2323
"update-ns-webpack": "./bin/update-ns-webpack",
2424
"ns-bundle": "./bin/ns-bundle",
25-
"ns-verify-bundle": "./bin/ns-verify-bundle"
25+
"ns-verify-bundle": "./bin/ns-verify-bundle",
26+
"generate-android-snapshot": "./bin/generate-android-snapshot"
27+
},
28+
"dependencies": {
29+
"adm-zip": "^0.4.7",
30+
"shelljs": "^0.6.0"
2631
},
27-
"dependencies": {},
2832
"devDependencies": {}
2933
}

Diff for: plugins/GenerateBundleStarterPlugin.js

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
const { RawSource } = require("webpack-sources");
2+
const { getPackageJson } = require("../projectHelpers");
3+
4+
exports.GenerateBundleStarterPlugin = (function() {
5+
function GenerateBundleStarterPlugin(bundles) {
6+
this.bundles = bundles;
7+
};
8+
9+
GenerateBundleStarterPlugin.prototype.apply = function(compiler) {
10+
const plugin = this;
11+
plugin.webpackContext = compiler.options.context;
12+
13+
compiler.plugin("emit", function (compilation, cb) {
14+
compilation.assets["package.json"] = plugin.generatePackageJson();
15+
compilation.assets["starter.js"] = plugin.generateStarterModule();
16+
plugin.generateTnsJavaClasses(compilation);
17+
18+
cb();
19+
});
20+
}
21+
22+
GenerateBundleStarterPlugin.prototype.generateTnsJavaClasses = function (compilation) {
23+
const path = compilation.compiler.outputPath;
24+
const isAndroid = path.indexOf("android") > -1;
25+
26+
if (isAndroid && !compilation.assets["tns-java-classes.js"]) {
27+
compilation.assets["tns-java-classes.js"] = new RawSource("");
28+
}
29+
}
30+
31+
GenerateBundleStarterPlugin.prototype.generatePackageJson = function () {
32+
const packageJson = getPackageJson(this.webpackContext);
33+
packageJson.main = "starter";
34+
35+
return new RawSource(JSON.stringify(packageJson, null, 4));
36+
}
37+
38+
GenerateBundleStarterPlugin.prototype.generateStarterModule = function () {
39+
const moduleSource = this.bundles
40+
.map(bundle => `require("${bundle}")`)
41+
.join("\n");
42+
43+
return new RawSource(moduleSource);
44+
}
45+
46+
return GenerateBundleStarterPlugin;
47+
})();

0 commit comments

Comments
 (0)