mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-08-15 02:54:11 +08:00
174 lines
6.9 KiB
JavaScript
174 lines
6.9 KiB
JavaScript
const { relative, resolve, join } = require("path");
|
|
const { closeSync, openSync, writeFileSync } = require("fs");
|
|
const validateOptions = require("schema-utils");
|
|
|
|
const ProjectSnapshotGenerator = require("../../snapshot/android/project-snapshot-generator");
|
|
const { getPackageJson } = require("../../helpers/projectHelpers");
|
|
const {
|
|
ANDROID_PROJECT_DIR,
|
|
ANDROID_APP_PATH,
|
|
} = require("../../helpers/androidProjectHelpers");
|
|
const { ensureDirectoryExistence } = require("../../lib/utils");
|
|
const schema = require("./options.json");
|
|
|
|
const SNAPSHOT_ENTRY_NAME = "snapshot-entry";
|
|
const SNAPSHOT_ENTRY_MODULE = `${SNAPSHOT_ENTRY_NAME}.js`;
|
|
exports.SNAPSHOT_ENTRY_NAME = SNAPSHOT_ENTRY_NAME;
|
|
|
|
exports.NativeScriptSnapshotPlugin = (function () {
|
|
function NativeScriptSnapshotPlugin(options) {
|
|
NativeScriptSnapshotPlugin.validateSchema(options);
|
|
|
|
ProjectSnapshotGenerator.call(this, options);
|
|
|
|
const { webpackConfig } = this.options;
|
|
NativeScriptSnapshotPlugin.removeLibraryTarget(webpackConfig);
|
|
|
|
const { entry } = webpackConfig;
|
|
if (typeof entry === "string" || Array.isArray(entry)) {
|
|
webpackConfig.entry = { bundle: entry };
|
|
}
|
|
|
|
NativeScriptSnapshotPlugin.ensureSnapshotModuleEntry(this.options);
|
|
}
|
|
|
|
NativeScriptSnapshotPlugin.removeLibraryTarget = function (webpackConfig) {
|
|
const { output } = webpackConfig;
|
|
if (output) {
|
|
output.libraryTarget = undefined;
|
|
}
|
|
}
|
|
|
|
NativeScriptSnapshotPlugin.ensureSnapshotModuleEntry = function (options) {
|
|
const { webpackConfig, requireModules, chunks, includeApplicationCss } = options;
|
|
const internalRequireModules = this.getInternalRequireModules(webpackConfig.context);
|
|
|
|
const snapshotEntryPath = join(ANDROID_PROJECT_DIR, SNAPSHOT_ENTRY_MODULE);
|
|
|
|
let snapshotEntryContent = "";
|
|
if (includeApplicationCss) {
|
|
snapshotEntryContent += `
|
|
require("${
|
|
options.angular ?
|
|
'@nativescript/webpack/helpers/load-application-css-angular' :
|
|
'@nativescript/webpack/helpers/load-application-css-regular'
|
|
}")();
|
|
`;
|
|
}
|
|
snapshotEntryContent += [...requireModules, ...internalRequireModules]
|
|
.map(mod => `require('${mod}')`).join(";");
|
|
|
|
ensureDirectoryExistence(snapshotEntryPath);
|
|
writeFileSync(snapshotEntryPath, snapshotEntryContent, { encoding: "utf8" });
|
|
|
|
// add the module to the entry points to make sure it's content is evaluated
|
|
webpackConfig.entry[SNAPSHOT_ENTRY_NAME] = relative(webpackConfig.context, snapshotEntryPath);
|
|
|
|
// prepend the module to the script that will be snapshotted
|
|
chunks.unshift(SNAPSHOT_ENTRY_NAME);
|
|
|
|
// ensure that the runtime is installed only in the snapshotted chunk
|
|
webpackConfig.optimization.runtimeChunk = { name: SNAPSHOT_ENTRY_NAME };
|
|
}
|
|
NativeScriptSnapshotPlugin.getInternalRequireModules = function (webpackContext) {
|
|
const packageJson = getPackageJson(webpackContext);
|
|
return (packageJson && packageJson["android"] && packageJson["android"]["requireModules"]) || [];
|
|
}
|
|
|
|
NativeScriptSnapshotPlugin.validateSchema = function (options) {
|
|
if (!options.chunk && !options.chunks) {
|
|
const error = NativeScriptSnapshotPlugin.extendError({ message: `No chunks specified!` });
|
|
throw error;
|
|
}
|
|
|
|
try {
|
|
validateOptions(schema, options, "NativeScriptSnapshotPlugin");
|
|
|
|
if (options.chunk) {
|
|
options.chunks = options.chunks || [];
|
|
options.chunks.push(options.chunk);
|
|
}
|
|
} catch (error) {
|
|
throw new Error(error.message);
|
|
}
|
|
}
|
|
|
|
NativeScriptSnapshotPlugin.prototype = Object.create(ProjectSnapshotGenerator.prototype);
|
|
NativeScriptSnapshotPlugin.prototype.constructor = NativeScriptSnapshotPlugin;
|
|
|
|
NativeScriptSnapshotPlugin.prototype.generate = function (webpackChunks) {
|
|
const options = this.options;
|
|
if (options.skipSnapshotTools) {
|
|
console.log(`Skipping snapshot tools.`);
|
|
return Promise.resolve();
|
|
}
|
|
|
|
const inputFiles = webpackChunks.map(chunk => join(options.webpackConfig.output.path, chunk.files[0]));
|
|
const preprocessedInputFile = join(
|
|
this.options.projectRoot,
|
|
ANDROID_APP_PATH,
|
|
"_embedded_script_.js"
|
|
);
|
|
|
|
console.log(`\n Snapshotting bundle from ${inputFiles}`);
|
|
|
|
return ProjectSnapshotGenerator.prototype.generate.call(this, {
|
|
inputFiles,
|
|
preprocessedInputFile,
|
|
targetArchs: options.targetArchs,
|
|
useLibs: options.useLibs,
|
|
androidNdkPath: options.androidNdkPath,
|
|
v8Version: options.v8Version,
|
|
snapshotInDocker: options.snapshotInDocker,
|
|
skipSnapshotTools: options.skipSnapshotTools
|
|
}).then(() => {
|
|
// Make the original files empty
|
|
inputFiles.forEach(inputFile =>
|
|
closeSync(openSync(inputFile, "w")) // truncates the input file content
|
|
);
|
|
});
|
|
}
|
|
|
|
NativeScriptSnapshotPlugin.prototype.apply = function (compiler) {
|
|
const options = this.options;
|
|
|
|
compiler.hooks.afterEmit.tapAsync("NativeScriptSnapshotPlugin", function (compilation, callback) {
|
|
const chunksToSnapshot = options.chunks
|
|
.map(name => ({ name, chunk: compilation.chunks.find(chunk => chunk.name === name) }));
|
|
const unexistingChunks = chunksToSnapshot.filter(pair => !pair.chunk);
|
|
|
|
if (unexistingChunks.length) {
|
|
const message = `The following chunks does not exist: ` + unexistingChunks.map(pair => pair.name).join(", ");
|
|
const error = NativeScriptSnapshotPlugin.extendError({ message });
|
|
compilation.errors.push(error);
|
|
return callback();
|
|
}
|
|
|
|
this.generate(chunksToSnapshot.map(pair => pair.chunk))
|
|
.then(() => {
|
|
console.log("Successfully generated snapshots!");
|
|
return callback();
|
|
})
|
|
.catch((error) => {
|
|
const extendedError = NativeScriptSnapshotPlugin.extendError({ originalError: error });
|
|
compilation.errors.push(extendedError);
|
|
return callback();
|
|
});
|
|
}.bind(this));
|
|
}
|
|
|
|
NativeScriptSnapshotPlugin.extendError = function ({ originalError, message } = {}) {
|
|
const header = `NativeScriptSnapshot. Snapshot generation failed!\n`;
|
|
if (originalError) {
|
|
originalError.message = `${header}${originalError.message}`;
|
|
return originalError;
|
|
}
|
|
|
|
const newMessage = message ? `${header}${message}` : header;
|
|
return new Error(newMessage);
|
|
};
|
|
|
|
return NativeScriptSnapshotPlugin;
|
|
})();
|
|
|