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

Vlaeva/refactor project structure #186

Merged
merged 2 commits into from
Jun 12, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
121 changes: 20 additions & 101 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"]) {
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,30 @@ 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);
const aotEntryPath = path.join(APP_DIR, aotEntry);

return fs.existsSync(aotEntryPath) ? aotEntry : null;
return existsSync(aotEntryPath) ? aotEntry : null;
}

function getProjectDir() {
return path.dirname(path.dirname(__dirname));
}
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;
})();
38 changes: 38 additions & 0 deletions plugins/NativeScriptJsonpPlugin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
const { ConcatSources } = require("webpack-sources");

const WINDOWS_GLOBAL_MATCHER = /window\["nativescriptJsonp"\]/g;
const NATIVESCRIPT_GLOBAL = "global[\"nativescriptJsonp\"]";
const isVendorChunk = name => name === "vendor.js";

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

NativeScriptJsonpPlugin.prototype.apply = function (compiler) {
compiler.plugin("compilation", function (compilation) {
compilation.plugin("optimize-chunk-assets", function (chunks, callback) {
chunks.forEach(function (chunk) {
chunk.files
.filter(isVendorChunk)
.forEach(file => replaceGlobal(compilation.assets, file));
});
callback();
});
});
};

return NativeScriptJsonpPlugin;
})();

function replaceGlobal(assets, file) {
const path = assets[file];
const source = path.source();
const match = source.match(WINDOWS_GLOBAL_MATCHER);

if (match) {
const newSource = source.replace(WINDOWS_GLOBAL_MATCHER, NATIVESCRIPT_GLOBAL);
assets[file] = new ConcatSource(newSource);
}
}
88 changes: 88 additions & 0 deletions plugins/NativeScriptSnapshotPlugin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
const { resolve, join } = require("path");
const { closeSync, openSync } = require("fs");

const ProjectSnapshotGenerator = require("../snapshot/android/project-snapshot-generator");

exports.NativeScriptSnapshotPlugin = (function() {
function NativeScriptSnapshotPlugin(options) {
ProjectSnapshotGenerator.call(this, options); // Call the parent constructor

if (!this.options.chunk) {
throw new Error("No chunk specified.");
}

console.dir()

if (this.options.webpackConfig) {
if (this.options.webpackConfig.output && this.options.webpackConfig.output.libraryTarget) {
this.options.webpackConfig.output.libraryTarget = undefined;
}

if (this.options.webpackConfig.entry) {
if (typeof this.options.webpackConfig.entry === "string" ||
this.options.webpackConfig.entry instanceof Array)
this.options.webpackConfig.entry = { bundle: this.options.webpackConfig.entry };
}

this.options.webpackConfig.entry["tns-java-classes"] = this.getTnsJavaClassesBuildPath();
}
}

// inherit ProjectSnapshotGenerator
NativeScriptSnapshotPlugin.prototype = Object.create(ProjectSnapshotGenerator.prototype);
NativeScriptSnapshotPlugin.prototype.constructor = NativeScriptSnapshotPlugin;

NativeScriptSnapshotPlugin.prototype.getTnsJavaClassesBuildPath = function() {
return resolve(this.getBuildPath(), "../tns-java-classes.js");
}

NativeScriptSnapshotPlugin.prototype.generate = function(webpackChunk) {
const options = this.options;

const inputFile = join(options.webpackConfig.output.path, webpackChunk.files[0]);

console.log(`\n Snapshotting bundle at ${inputFile}`);

const preparedAppRootPath = join(options.projectRoot, "platforms/android/src/main/assets");
const preprocessedInputFile = join(preparedAppRootPath, "app/_embedded_script_.js");

ProjectSnapshotGenerator.prototype.generate.call(this, {
inputFile,
preprocessedInputFile,
targetArchs: options.targetArchs,
useLibs: options.useLibs,
androidNdkPath: options.androidNdkPath,
tnsJavaClassesPath: join(preparedAppRootPath, "app/tns-java-classes.js")
});

// Make the original file empty
if (inputFile !== preprocessedInputFile) {
closeSync(openSync(inputFile, "w")); // truncates the input file content
}
}

NativeScriptSnapshotPlugin.prototype.apply = function(compiler) {
const options = this.options;

// Generate tns-java-classes.js file
debugger;
ProjectSnapshotGenerator.prototype.generateTnsJavaClassesFile.call(this, {
output: this.getTnsJavaClassesBuildPath(),
options: options.tnsJavaClassesOptions
});

// Run the snapshot tool when the packing is done
compiler.plugin("done", function(result) {
debugger;
const chunkToSnapshot = result.compilation.chunks.find(chunk => chunk.name == options.chunk);
if (!chunkToSnapshot) {
throw new Error(`No chunk named '${options.chunk}' found.`);
}

this.generate(chunkToSnapshot);

}.bind(this));
}

return NativeScriptSnapshotPlugin;
})();
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
const ts = require("typescript");
const fs = require("fs");
const path = require("path");
const { forEachChild, SyntaxKind } = require("typescript");
const { existsSync } = require("fs");
const { resolve } = require("path");

const UrlResolvePlugin = (function() {
exports.UrlResolvePlugin = (function() {
function UrlResolvePlugin(options) {
if (!options || !options.platform) {
throw new Error(`Target platform must be specified!`);
Expand Down Expand Up @@ -40,15 +40,15 @@ const UrlResolvePlugin = (function() {

UrlResolvePlugin.prototype.usePlatformUrl = function(sourceFile) {
this.setCurrentDirectory(sourceFile);
ts.forEachChild(sourceFile, node => this.traverseDecorators(node));
forEachChild(sourceFile, node => this.traverseDecorators(node));
}

UrlResolvePlugin.prototype.setCurrentDirectory = function(sourceFile) {
this.currentDirectory = path.resolve(sourceFile.path, "..");
this.currentDirectory = resolve(sourceFile.path, "..");
}

UrlResolvePlugin.prototype.traverseDecorators = function(node) {
if (node.kind !== ts.SyntaxKind.ClassDeclaration || !node.decorators) {
if (node.kind !== SyntaxKind.ClassDeclaration || !node.decorators) {
return;
}

Expand Down Expand Up @@ -90,9 +90,9 @@ const UrlResolvePlugin = (function() {
}

UrlResolvePlugin.prototype.noMultiplatformFile = function(url) {
let filePath = path.resolve(this.currentDirectory, url);
let filePath = resolve(this.currentDirectory, url);

return !fs.existsSync(filePath);
return !existsSync(filePath);
}

UrlResolvePlugin.prototype.replaceUrlsValue = function(element) {
Expand All @@ -105,5 +105,3 @@ const UrlResolvePlugin = (function() {

return UrlResolvePlugin;
})();

module.exports = UrlResolvePlugin;
4 changes: 4 additions & 0 deletions plugins/angular.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module.exports = Object.assign({},
require("./UrlResolvePlugin")
);

6 changes: 6 additions & 0 deletions plugins/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = Object.assign({},
require("./GenerateBundleStarterPlugin"),
require("./NativeScriptJsonpPlugin"),
require("./NativeScriptSnapshotPlugin")
);

Loading