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

Local snapshot support #181

Merged
merged 28 commits into from
Jun 14, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
9eaaa53
Merge nativescript-dev-android-snapshot package into nativescript-dev…
ivanbuhov May 14, 2017
8535fc2
Extract snapshot-generator and project-snapshot-generator as standalo…
ivanbuhov May 17, 2017
98e81d0
Add working mksnapshot tools
ivanbuhov May 19, 2017
6757683
Add tns-java-classes bundle
ivanbuhov May 30, 2017
b970c62
Change tools folder structure. Add requrie_override in bundle preamble.
ivanbuhov Jun 1, 2017
ac00eec
Generate tns-java-classes from node_modules
ivanbuhov Jun 7, 2017
36a8b36
Fix templates
ivanbuhov Jun 7, 2017
cc9025b
Enable snapshot generataion with ns-bundle script parameter
ivanbuhov Jun 7, 2017
ff864d3
Rename generated snapshot plugin to nativescript-snapshot-placeholder
ivanbuhov Jun 7, 2017
1ab11a7
Install snapshot artefacts in platform folder instead of adding a plugin
ivanbuhov Jun 8, 2017
4ed39d0
Generate empty tns-java-classes.js file only if such an assets doesn'…
ivanbuhov Jun 8, 2017
556c02f
refactor: drop dependency for semver
sis0k0 Jun 8, 2017
ba6ae08
Change build folder to platforms/android/snapshot-build in order to p…
ivanbuhov Jun 8, 2017
bd0ab60
[Refactor] Use const instead of var when it is appropriate
ivanbuhov Jun 8, 2017
f0aeeb7
Rename linux mksnapshot tool
ivanbuhov Jun 8, 2017
e5c07cf
Rename plugin to nativescript-android-snapshot
ivanbuhov Jun 8, 2017
e756171
Add support for snapshot generation without webpack bundle
ivanbuhov Jun 8, 2017
04585d7
Enable shortlisting target architectures when building snapshot
ivanbuhov Jun 10, 2017
fb2ad88
Rebuild mksnapshot tools for mac to make them print message on error
ivanbuhov Jun 10, 2017
b2cf6c1
Throw error and stop the build if snapshot generation fails
ivanbuhov Jun 10, 2017
4efad00
refactor: clean-up index.js
sis0k0 Jun 11, 2017
089dbd7
refactor: move plugins to separate dir
sis0k0 Jun 11, 2017
20916b3
Merge pull request #186 from NativeScript/vlaeva/refactor-project-str…
ivanbuhov Jun 12, 2017
94b44d9
refactor: move plugins to separate dir
sis0k0 Jun 11, 2017
bb11f17
fix: snapshot scope "frame" requires in vendor android
sis0k0 Jun 12, 2017
2ced705
fix(postinstall): add snapshot plugin to webpack config
sis0k0 Jun 12, 2017
935f9c6
fix: run updater scripts through ./bin/update-ns-webpack
sis0k0 Jun 12, 2017
79057b2
Merge pull request #187 from NativeScript/vlaeva/postinstall-replace-…
ivanbuhov Jun 13, 2017
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions bin/generate-android-snapshot
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/usr/bin/env node
const ProjectSnapshotGenerator = require("../snapshot/android/project-snapshot-generator");
const args = require("../snapshot/android/project-snapshot-generator-cli-ags-parser")();

const generator = new ProjectSnapshotGenerator(args);
generator.generate(args);
1 change: 1 addition & 0 deletions bin/generate-android-snapshot.cmd
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@node %~dp0\generate-android-snapshot %*
31 changes: 23 additions & 8 deletions bin/ns-bundle
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const { spawn } = require("child_process");
const { resolve: pathResolve } = require("path");
const { existsSync } = require("fs");
const { getPackageJson } = require("../projectHelpers");
const { isVersionGte } = require("../utils");

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

const npmArgs = JSON.parse(process.env.npm_config_argv).original;
const tnsArgs = getTnsArgs(npmArgs).map(escape);
Expand All @@ -28,6 +30,7 @@ function getTnsArgs(args) {
"--android",
"--ios",
"--uglify",
"--snapshot",
"--nobundle",
];

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

function execute(options) {
let commands = [];
const platform = options.platform;
let commands = [
() => runTns("prepare", platform)
];

if (options.bundle) {
commands = [
...commands,
() => cleanApp(platform),
() => cleanSnapshotArtefacts(),
() => cleanBuildArtifacts(platform),
() => webpack(platform),
];
}

if (shouldSnapshot(platform)) {
commands.push(() => installSnapshotArtefacts());
}

// If "build-app" or "start-app" is specified,
// the respective command should be run last.
// Otherwise, the app should be just prepared.
if (options.command) {
commands.push(() => runTns(options.command, platform));
} else {
commands.shift(() => runTns("prepare", platform))
}
return commands.reduce((current, next) => current.then(next), Promise.resolve());
}
Expand All @@ -65,12 +73,10 @@ function cleanBuildArtifacts(platform) {
return resolve();
}

getTnsVersion().then(versionString => {
const version = versionToNumber(versionString);

getTnsVersion().then(version => {
// the android build artifacts should be cleaned manually
// for nativescript-cli v3.0.1 and below or if using uglify
if (version <= 301 || shouldUglify()) {
if (isVersionGte(version, "3.0.1") || shouldUglify()) {
gradlewClean().then(resolve).catch(throwError);
} else {
return resolve();
Expand All @@ -79,6 +85,14 @@ function cleanBuildArtifacts(platform) {
});
}

function cleanSnapshotArtefacts() {
require("../snapshot/android/project-snapshot-generator").cleanSnapshotArtefacts(PROJECT_DIR);
}

function installSnapshotArtefacts() {
require("../snapshot/android/project-snapshot-generator").installSnapshotArtefacts(PROJECT_DIR);
}

function gradlewClean() {
return new Promise((resolve, reject) => {
const platformsPath = pathResolve(PROJECT_DIR, "platforms", "android")
Expand Down Expand Up @@ -135,6 +149,7 @@ function webpack(platform) {
`--progress`,
`--env.${platform}`,
shouldUglify() && `--env.uglify`,
shouldSnapshot(platform) && `--env.snapshot`
];

spawnChildProcess(...args)
Expand Down
20 changes: 13 additions & 7 deletions bin/update-ns-webpack
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
#!/usr/bin/env node
const path = require("path");
const fs = require("fs");
const { resolve } = require("path");

const helpers = require("../projectHelpers");
const forceUpdateProjectDeps = require("../dependencyManager").forceUpdateProjectDeps;
const { getPackageJson, writePackageJson } = require("../projectHelpers");
const { forceUpdateProjectDeps } = require("../dependencyManager");
const { editExistingProjectFiles } = require("../projectFilesManager");

const PROJECT_DIR = path.resolve(__dirname, "../../../");
const packageJson = helpers.getPackageJson(PROJECT_DIR);
const PROJECT_DIR = resolve(__dirname, "../../../");

console.info("Updating dev dependencies...");
const packageJson = getPackageJson(PROJECT_DIR);
const { deps } = forceUpdateProjectDeps(packageJson);
packageJson.devDependencies = deps;
writePackageJson(packageJson, PROJECT_DIR);

console.info("\nUpdating configuration files...");
editExistingProjectFiles(PROJECT_DIR);

console.info("\nProject successfully updated! Don't forget to run `npm install`");

helpers.writePackageJson(packageJson, PROJECT_DIR);
122 changes: 20 additions & 102 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,84 +1,19 @@
var sources = require("webpack-sources");
var fs = require("fs");
var path = require("path");
const path = require("path");
const { existsSync } = require("fs");

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

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

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

if (isAngular) {
exports.UrlResolvePlugin = require("./resource-resolver-plugins/UrlResolvePlugin");
if (isAngular({projectDir: PROJECT_DIR})) {
Object.assign(exports, require('./plugins/angular'));
}

//HACK: changes the JSONP chunk eval function to `global["nativescriptJsonp"]`
// applied to tns-java-classes.js only
exports.NativeScriptJsonpPlugin = function () {
};

exports.NativeScriptJsonpPlugin.prototype.apply = function (compiler) {
compiler.plugin("compilation", function (compilation) {
compilation.plugin("optimize-chunk-assets", function (chunks, callback) {
chunks.forEach(function (chunk) {
chunk.files.forEach(function (file) {
if (file === "vendor.js") {
var src = compilation.assets[file];
var code = src.source();
var match = code.match(/window\["nativescriptJsonp"\]/);
if (match) {
compilation.assets[file] = new sources.ConcatSource(code.replace(/window\["nativescriptJsonp"\]/g, "global[\"nativescriptJsonp\"]"));
}
}
});
});
callback();
});
});
};

exports.GenerateBundleStarterPlugin = function (bundles) {
this.bundles = bundles;
};

exports.GenerateBundleStarterPlugin.prototype = {
apply: function (compiler) {
var plugin = this;
plugin.webpackContext = compiler.options.context;

compiler.plugin("emit", function (compilation, cb) {
compilation.assets["package.json"] = plugin.generatePackageJson();
compilation.assets["starter.js"] = plugin.generateStarterModule();
plugin.generateTnsJavaClasses(compilation);

cb();
});
},
generateTnsJavaClasses: function (compilation) {
const path = compilation.compiler.outputPath;
const isAndroid = path.indexOf("android") > -1;

if (isAndroid) {
compilation.assets["tns-java-classes.js"] = new sources.RawSource("");
}
},
generatePackageJson: function () {
var packageJsonPath = path.join(this.webpackContext, "package.json");
var packageData = JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
packageData.main = "starter";

return new sources.RawSource(JSON.stringify(packageData, null, 4));
},
generateStarterModule: function () {
var moduleSource = this.bundles.map(function (bundle) {
return "require(\"" + bundle + "\");";
}).join("\n");
return new sources.RawSource(moduleSource);
},
};
exports.uglifyMangleExcludes = require("./mangle-excludes");

exports.getEntryModule = function () {
const maybePackageJsonEntry = getPackageJsonEntry();
Expand All @@ -90,46 +25,29 @@ exports.getEntryModule = function () {
return maybeAotEntry || maybePackageJsonEntry;
};

exports.getAppPath = function (platform) {
var projectDir = path.dirname(path.dirname(__dirname));

exports.getAppPath = platform => {
if (/ios/i.test(platform)) {
var appName = path.basename(projectDir);
var sanitizedName = appName.split("").filter(function (c) {
return /[a-zA-Z0-9]/.test(c);
}).join("");
return "platforms/ios/" + sanitizedName + "/app";
const appName = path.basename(PROJECT_DIR);
const sanitizedName = sanitize(appName);

return `platforms/ios/${sanitizedName}/app`;
} else if (/android/i.test(platform)) {
return path.join(projectDir, "platforms/android/src/main/assets/app");
return path.join(PROJECT_DIR, "platforms/android/src/main/assets/app");
} else {
throw new Error("Invalid platform: " + platform);
throw new Error(`Invalid platform: ${platform}`);
}
};

exports.uglifyMangleExcludes = require("./mangle-excludes");

function getPackageJsonEntry() {
const packageJsonSource = getAppPackageJsonSource();
const packageJsonSource = getPackageJson(APP_DIR);
const entry = packageJsonSource.main;

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

function getAppPackageJsonSource() {
const projectDir = getProjectDir();
const appPackageJsonPath = path.join(projectDir, "app", "package.json");

return JSON.parse(fs.readFileSync(appPackageJsonPath, "utf8"));
}

function getAotEntry(entry) {
const aotEntry = `${entry}.aot.ts`;
const projectDir = getProjectDir();
const aotEntryPath = path.join(projectDir, "app", aotEntry);

return fs.existsSync(aotEntryPath) ? aotEntry : null;
}
const aotEntryPath = path.join(APP_DIR, aotEntry);

function getProjectDir() {
return path.dirname(path.dirname(__dirname));
return existsSync(aotEntryPath) ? aotEntry : null;
}
1 change: 0 additions & 1 deletion installer.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ function install() {
let packageJson = helpers.getPackageJson(PROJECT_DIR);

projectFilesManager.addProjectFiles(PROJECT_DIR, APP_DIR);
projectFilesManager.editExistingProjectFiles(PROJECT_DIR);

let scripts = packageJson.scripts || {};
scripts = npmScriptsManager.removeDeprecatedNpmScripts(scripts);
Expand Down
1 change: 1 addition & 0 deletions npmScriptsManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const SCRIPT_TEMPLATES = Object.freeze({
"start-[PLATFORM]-bundle": "npm run ns-bundle --[PLATFORM] --run-app",
"build-[PLATFORM]-bundle": "npm run ns-bundle --[PLATFORM] --build-app",
"publish-ios-bundle": "npm run ns-bundle --ios --publish-app",
"generate-android-snapshot": "generate-android-snapshot --projectRoot . --targetArchs arm,arm64 --install"
});

const DEPRECATED_SCRIPT_TEMPLATES = Object.freeze([
Expand Down
8 changes: 6 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,12 @@
"remove-ns-webpack": "./bin/remove-ns-webpack",
"update-ns-webpack": "./bin/update-ns-webpack",
"ns-bundle": "./bin/ns-bundle",
"ns-verify-bundle": "./bin/ns-verify-bundle"
"ns-verify-bundle": "./bin/ns-verify-bundle",
"generate-android-snapshot": "./bin/generate-android-snapshot"
},
"dependencies": {
"adm-zip": "^0.4.7",
"shelljs": "^0.6.0"
},
"dependencies": {},
"devDependencies": {}
}
47 changes: 47 additions & 0 deletions plugins/GenerateBundleStarterPlugin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
const { RawSource } = require("webpack-sources");
const { getPackageJson } = require("../projectHelpers");

exports.GenerateBundleStarterPlugin = (function() {
function GenerateBundleStarterPlugin(bundles) {
this.bundles = bundles;
};

GenerateBundleStarterPlugin.prototype.apply = function(compiler) {
const plugin = this;
plugin.webpackContext = compiler.options.context;

compiler.plugin("emit", function (compilation, cb) {
compilation.assets["package.json"] = plugin.generatePackageJson();
compilation.assets["starter.js"] = plugin.generateStarterModule();
plugin.generateTnsJavaClasses(compilation);

cb();
});
}

GenerateBundleStarterPlugin.prototype.generateTnsJavaClasses = function (compilation) {
const path = compilation.compiler.outputPath;
const isAndroid = path.indexOf("android") > -1;

if (isAndroid && !compilation.assets["tns-java-classes.js"]) {
compilation.assets["tns-java-classes.js"] = new RawSource("");
}
}

GenerateBundleStarterPlugin.prototype.generatePackageJson = function () {
const packageJson = getPackageJson(this.webpackContext);
packageJson.main = "starter";

return new RawSource(JSON.stringify(packageJson, null, 4));
}

GenerateBundleStarterPlugin.prototype.generateStarterModule = function () {
const moduleSource = this.bundles
.map(bundle => `require("${bundle}")`)
.join("\n");

return new RawSource(moduleSource);
}

return GenerateBundleStarterPlugin;
})();
Loading