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

Commit

Permalink
feat: generate the snapshot entry module at build time
Browse files Browse the repository at this point in the history
fixes #511
  • Loading branch information
sis0k0 committed May 3, 2018
1 parent 2ff43bf commit 2ec8083
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 46 deletions.
56 changes: 44 additions & 12 deletions plugins/NativeScriptSnapshotPlugin/index.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,56 @@
const { resolve, join } = require("path");
const { closeSync, openSync } = require("fs");
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 { resolveAndroidAppPath } = require("../../projectHelpers");
const { resolveAndroidAppPath, getAndroidProjectPath } = require("../../projectHelpers");
const schema = require("./options.json");

const SNAPSHOT_ENTRY_NAME = "snapshot-entry";
const SNAPSHOT_ENTRY_MODULE = `${SNAPSHOT_ENTRY_NAME}.js`;

exports.NativeScriptSnapshotPlugin = (function() {
function NativeScriptSnapshotPlugin(options) {
NativeScriptSnapshotPlugin.validateSchema(options);
if (options.chunk) {
options.chunks = options.chunks || [];
options.chunks.push(options.chunk);
}

ProjectSnapshotGenerator.call(this, options);

if (this.options.webpackConfig) {
if (this.options.webpackConfig.output && this.options.webpackConfig.output.libraryTarget) {
this.options.webpackConfig.output.libraryTarget = undefined;
}
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, projectRoot } = options;

const androidProjectPath = getAndroidProjectPath({ projectRoot: projectRoot });
const snapshotEntryPath = join(androidProjectPath, SNAPSHOT_ENTRY_MODULE);
const snapshotEntryContent = requireModules.map(mod => `require('${mod}')`).join(";");
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.validateSchema = function(options) {
if (!options.chunk && !options.chunks) {
const error = NativeScriptSnapshotPlugin.extendError({ message: `No chunks specified!` });
Expand All @@ -31,12 +59,16 @@ exports.NativeScriptSnapshotPlugin = (function() {

try {
validateOptions(schema, options, "NativeScriptSnapshotPlugin");

if (options.chunk) {
options.chunks = options.chunks || [];
options.chunks.push(options.chunk);
}
} catch (error) {
throw new Error(error.message);
}
}

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

Expand Down
32 changes: 28 additions & 4 deletions plugins/NativeScriptSnapshotPlugin/options.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,40 @@
"projectRoot": {
"type": "string"
},
"webpackConfig": {},
"webpackConfig": {
"type": "object"
},
"targetArchs": {
"type": "array"
"type": "array",
"default": [
"arm",
"arm64",
"ia32"
],
"items": {
"type": "string",
"enum": [
"arm",
"arm64",
"ia32"
]
}
},
"useLibs": {
"type": "boolean"
"type": "boolean",
"default": false
},
"v8Version": {
"type": "string"
"type": "string"
},
"requireModules": {
"type": "array",
"default": []
}
},
"required": [
"projectRoot",
"webpackConfig"
],
"additionalProperties": false
}
20 changes: 12 additions & 8 deletions templates/webpack.angular.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ module.exports = env => {
nsWebpack.getAotEntryModule(appFullPath) :
`${nsWebpack.getEntryModule(appFullPath)}.ts`;
const entryPath = `.${sep}${entryModule}`;
const vendorPath = `.${sep}vendor.ts`;

const config = {
mode: production ? "production" : "development",
Expand All @@ -67,7 +66,6 @@ module.exports = env => {
target: nativescriptTarget,
entry: {
bundle: entryPath,
vendor: vendorPath,
},
output: {
pathinfo: false,
Expand Down Expand Up @@ -103,7 +101,6 @@ module.exports = env => {
},
devtool: "none",
optimization: {
runtimeChunk: { name: "vendor" },
splitChunks: {
cacheGroups: {
common: {
Expand All @@ -113,7 +110,6 @@ module.exports = env => {
const moduleName = module.nameForCondition ? module.nameForCondition() : '';
return /[\\/]node_modules[\\/]/.test(moduleName) ||
appComponents.some(comp => comp === moduleName);

},
enforce: true,
},
Expand Down Expand Up @@ -186,7 +182,6 @@ module.exports = env => {
], { ignore: [`${relative(appPath, appResourcesFullPath)}/**`] }),
// Generate a bundle starter script and activate it in package.json
new nsWebpack.GenerateBundleStarterPlugin([
"./vendor",
"./common",
"./bundle",
]),
Expand All @@ -210,9 +205,9 @@ module.exports = env => {

if (platform === "android") {
// Require all Android app components
// in the entry module (bundle.ts) and the vendor module (vendor.ts).
// in the entry module (bundle.ts)
config.module.rules.unshift({
test: new RegExp(`${entryPath}|${vendorPath}`),
test: new RegExp(`${entryPath}`),
use: {
loader: "nativescript-dev-webpack/android-app-components-loader",
options: { modules: appComponents }
Expand All @@ -233,7 +228,16 @@ module.exports = env => {

if (snapshot) {
config.plugins.push(new nsWebpack.NativeScriptSnapshotPlugin({
chunks: [ "vendor", "common" ],
chunk: "common",
requireModules: [
"reflect-metadata",
"@angular/platform-browser",
"@angular/core",
"@angular/common",
"@angular/router",
"nativescript-angular/platform-static",
"nativescript-angular/router",
],
projectRoot,
webpackConfig: config,
targetArchs: ["arm", "arm64", "ia32"],
Expand Down
18 changes: 7 additions & 11 deletions templates/webpack.javascript.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ module.exports = env => {

const entryModule = nsWebpack.getEntryModule(appFullPath);
const entryPath = `.${sep}${entryModule}.js`;
const vendorPath = `.${sep}vendor.js`;

const config = {
mode: production ? "production" : "development",
Expand All @@ -63,7 +62,6 @@ module.exports = env => {
target: nativescriptTarget,
entry: {
bundle: entryPath,
vendor: vendorPath,
},
output: {
pathinfo: false,
Expand Down Expand Up @@ -99,7 +97,6 @@ module.exports = env => {
},
devtool: "none",
optimization: {
runtimeChunk: { name: "vendor" },
splitChunks: {
cacheGroups: {
common: {
Expand Down Expand Up @@ -167,9 +164,8 @@ module.exports = env => {
], { ignore: [`${relative(appPath, appResourcesFullPath)}/**`] }),
// Generate a bundle starter script and activate it in package.json
new nsWebpack.GenerateBundleStarterPlugin([
"./vendor", // install webpackJsonpCallback
"./common", // require app/vendor.js
"./bundle", // require the entry module (app/app.js)
"./common",
"./bundle",
]),
// Support for web workers since v3.2
new NativeScriptWorkerPlugin(),
Expand All @@ -184,9 +180,9 @@ module.exports = env => {

if (platform === "android") {
// Require all Android app components
// in the entry module (bundle.js) and the vendor module (vendor.js).
// in the entry module (bundle.js).
config.module.rules.unshift({
test: new RegExp(`${entryPath}|${vendorPath}`),
test: new RegExp(`${entryPath}`),
use: {
loader: "nativescript-dev-webpack/android-app-components-loader",
options: { modules: appComponents }
Expand All @@ -207,9 +203,9 @@ module.exports = env => {

if (snapshot) {
config.plugins.push(new nsWebpack.NativeScriptSnapshotPlugin({
chunks: [
"common",
"vendor",
chunk: "common",
requireModules: [
"tns-core-modules/bundle-entry-points",
],
projectRoot,
webpackConfig: config,
Expand Down
18 changes: 7 additions & 11 deletions templates/webpack.typescript.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ module.exports = env => {

const entryModule = nsWebpack.getEntryModule(appFullPath);
const entryPath = `.${sep}${entryModule}.ts`;
const vendorPath = `.${sep}vendor.ts`;

const config = {
mode: production ? "production" : "development",
Expand All @@ -63,7 +62,6 @@ module.exports = env => {
target: nativescriptTarget,
entry: {
bundle: entryPath,
vendor: vendorPath,
},
output: {
pathinfo: false,
Expand Down Expand Up @@ -99,7 +97,6 @@ module.exports = env => {
},
devtool: "none",
optimization: {
runtimeChunk: { name: "vendor" },
splitChunks: {
cacheGroups: {
common: {
Expand Down Expand Up @@ -169,9 +166,8 @@ module.exports = env => {
], { ignore: [`${relative(appPath, appResourcesFullPath)}/**`] }),
// Generate a bundle starter script and activate it in package.json
new nsWebpack.GenerateBundleStarterPlugin([
"./vendor", // install webpackJsonpCallback
"./common", // require app/vendor.js
"./bundle", // require the entry module (app/app.js)
"./common",
"./bundle",
]),
// Support for web workers since v3.2
new NativeScriptWorkerPlugin(),
Expand All @@ -186,9 +182,9 @@ module.exports = env => {

if (platform === "android") {
// Require all Android app components
// in the entry module (bundle.ts) and the vendor module (vendor.ts).
// in the entry module (bundle.ts).
config.module.rules.unshift({
test: new RegExp(`${entryPath}|${vendorPath}`),
test: new RegExp(`${entryPath}`),
use: {
loader: "nativescript-dev-webpack/android-app-components-loader",
options: { modules: appComponents }
Expand All @@ -209,9 +205,9 @@ module.exports = env => {

if (snapshot) {
config.plugins.push(new nsWebpack.NativeScriptSnapshotPlugin({
chunks: [
"common",
"vendor",
chunk: "common",
requireModules: [
"tns-core-modules/bundle-entry-points",
],
projectRoot,
webpackConfig: config,
Expand Down

0 comments on commit 2ec8083

Please sign in to comment.