From dbf6bdc414e84c319193e58cf2176070e30d6d42 Mon Sep 17 00:00:00 2001 From: mudlabs Date: Fri, 24 May 2019 08:11:53 +1000 Subject: [PATCH 1/7] Update webpack-bundle-analyzer to patch 3.3.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 15212580..c93e5f39 100644 --- a/package.json +++ b/package.json @@ -96,7 +96,7 @@ "terser-webpack-plugin": "1.2.3", "ts-loader": "^5.3.1", "webpack": "~4.27.0", - "webpack-bundle-analyzer": "~3.0.2", + "webpack-bundle-analyzer": "^3.3.2", "webpack-cli": "~3.1.1", "webpack-sources": "~1.3.0" }, From 76314ee3ec04dc9a223a122f58af87bc5b569bf1 Mon Sep 17 00:00:00 2001 From: Sam <32623552+mudlabs@users.noreply.github.com> Date: Thu, 6 Jun 2019 09:00:05 +1000 Subject: [PATCH 2/7] Update package.json Co-Authored-By: Kristian Dimitrov --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c93e5f39..ee408e4e 100644 --- a/package.json +++ b/package.json @@ -96,7 +96,7 @@ "terser-webpack-plugin": "1.2.3", "ts-loader": "^5.3.1", "webpack": "~4.27.0", - "webpack-bundle-analyzer": "^3.3.2", + "webpack-bundle-analyzer": "~3.3.2", "webpack-cli": "~3.1.1", "webpack-sources": "~1.3.0" }, From 121c3b27cff08d98d7f74e8b4aea262203add5e8 Mon Sep 17 00:00:00 2001 From: fatme Date: Sun, 30 Jun 2019 23:48:46 +0300 Subject: [PATCH 3/7] fix: don't restart application when lazy loaded code is changed in angular app with uglify option Currently there is a logic that gets all runtime files and entry point files from webpack compilation. These files are needed to CLI in order to decides if the application should be restarted or refreshed on device(when there is at least one file that is not hot update file, CLI restarts the application). However, this logic doesn't work for lazy loaded modules in angular application as they are reported neither entry point files nor runtime files. Lazy loaded modules are directly injected into webpack compilation using the hooks of ContextModuleFactory - https://github.com/angular/ngtools-webpack-builds/blob/39ccb0b487e92a7ac4330ff9db821337b7aa5c45/src/angular_compiler_plugin.js#L516. This PR fixes the behavior with lazy loaded files as it gets all chunks produced from webpack compilation and omits hot-update.js files from them. Chunk files are all files except hot update files. Chunk files are: `runtime.js`, `tns_modules/inspector-modules.js`, `bundle.js`, `vendor.js` and all lazy loaded modules. When a files is changed in hmr mode, .hot-update.js file is included into chunk files. This way we don't need to separate the files to entry point, runtime, lazy loaded and others. We just need to omit .hot-update.js file from chunk files from webpack compilation. --- plugins/WatchStateLoggerPlugin.ts | 47 ++++++++----------------------- 1 file changed, 12 insertions(+), 35 deletions(-) diff --git a/plugins/WatchStateLoggerPlugin.ts b/plugins/WatchStateLoggerPlugin.ts index e10bca88..7e5302d7 100644 --- a/plugins/WatchStateLoggerPlugin.ts +++ b/plugins/WatchStateLoggerPlugin.ts @@ -33,51 +33,28 @@ export class WatchStateLoggerPlugin { .keys(compilation.assets) .filter(assetKey => compilation.assets[assetKey].emitted); - const webpackRuntimeFiles = getWebpackRuntimeOnlyFiles(compilation); - const entryPointFiles = getEntryPointFiles(compilation); + const chunkFiles = getChunkFiles(compilation); process.send && process.send(messages.compilationComplete, error => null); // Send emitted files so they can be LiveSynced if need be - process.send && process.send({ emittedFiles, webpackRuntimeFiles, entryPointFiles }, error => null); + process.send && process.send({ emittedFiles, chunkFiles }, error => null); }); } } -function getWebpackRuntimeOnlyFiles(compilation) { - let runtimeOnlyFiles = []; +function getChunkFiles(compilation) { + const chunkFiles = []; try { - runtimeOnlyFiles = [].concat(...Array.from(compilation.entrypoints.values()) - .map(entrypoint => entrypoint.runtimeChunk) - // filter embedded runtime chunks (e.g. part of bundle.js or inspector-modules.js) - .filter(runtimeChunk => !!runtimeChunk && runtimeChunk.preventIntegration) - .map(runtimeChunk => runtimeChunk.files)) - // get only the unique files in case of "single" runtime (e.g. runtime.js) - .filter((value, index, self) => self.indexOf(value) === index); - } catch (e) { - // breaking change in the Webpack API - console.log("Warning: Unable to find Webpack runtime files."); - } - - return runtimeOnlyFiles; -} - -function getEntryPointFiles(compilation) { - const entryPointFiles = []; - try { - Array.from(compilation.entrypoints.values()) - .forEach((entrypoint: any) => { - for (const entryChunk of entrypoint.chunks) { - entryChunk.files.forEach(fileName => { - if (fileName.indexOf("hot-update") === -1) { - entryPointFiles.push(fileName); - } - }); + compilation.chunks.forEach(chunk => { + chunk.files.forEach(file => { + if (file.indexOf("hot-update") === -1) { + chunkFiles.push(file); } }); + }); } catch (e) { - console.log("Warning: Unable to find Webpack entry point files."); + console.log("Warning: Unable to find chunk files."); } - return entryPointFiles - .filter((value, index, self) => self.indexOf(value) === index); // get only the unique files -} \ No newline at end of file + return chunkFiles; +} From a70fb3b937968b294aacdd437fcd6d21a86345b3 Mon Sep 17 00:00:00 2001 From: DimitarTachev Date: Mon, 1 Jul 2019 15:36:05 +0300 Subject: [PATCH 4/7] fix: create PropertyAssignment instead of string literal (Identifier) when modifying the NgModule - in some cases (e.g. when there is a decomposition in another NgModule property), the TypeScipt program is trying to read `node.name.kind` on each property causing an exception for Identifiers) --- transformers/ns-replace-lazy-loader.spec.ts | 37 +++++++++++++++++++++ transformers/ns-replace-lazy-loader.ts | 3 +- 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/transformers/ns-replace-lazy-loader.spec.ts b/transformers/ns-replace-lazy-loader.spec.ts index b3628dfc..cdf49df6 100644 --- a/transformers/ns-replace-lazy-loader.spec.ts +++ b/transformers/ns-replace-lazy-loader.spec.ts @@ -43,6 +43,43 @@ describe("@ngtools/webpack transformers", () => { AppModule); export { AppModule };` }, + { + name: "should add providers and NgModuleFactoryLoader when providers is missing and decomposition is used", + rawAppModule: ` + import { NgModule } from "@angular/core"; + import { NativeScriptModule } from "nativescript-angular/nativescript.module"; + import { AppComponent } from "./app.component"; + + const declarationsArray = [AppComponent]; + @NgModule({ + bootstrap: [ + AppComponent + ], + imports: [ + NativeScriptModule + ], + declarations: [ + ...declarationsArray + ] + }) + export class AppModule { } + `, + transformedAppModule: ` + import * as tslib_1 from "tslib"; import { NgModule } from "@angular/core"; + import { NativeScriptModule } from "nativescript-angular/nativescript.module"; + import { AppComponent } from "./app.component"; + ${NgLazyLoaderCode} + const declarationsArray = [AppComponent]; + let AppModule = class AppModule { }; + AppModule = tslib_1.__decorate([ NgModule({ + bootstrap: [ AppComponent ], + imports: [ NativeScriptModule ], + declarations: [ ...declarationsArray ], + providers: [{ provide: nsNgCoreImport_Generated.NgModuleFactoryLoader, useClass: NSLazyModulesLoader_Generated }] }) + ], + AppModule); + export { AppModule };` + }, { name: "should add NgModuleFactoryLoader when the providers array is empty", rawAppModule: ` diff --git a/transformers/ns-replace-lazy-loader.ts b/transformers/ns-replace-lazy-loader.ts index 9823e801..99f9774f 100644 --- a/transformers/ns-replace-lazy-loader.ts +++ b/transformers/ns-replace-lazy-loader.ts @@ -93,7 +93,8 @@ export function addArrayPropertyValueToNgModule( // the target field is missing, we will insert it @NgModule({ otherProps }) const lastConfigObjPropertyNode = ngModuleConfigObjectNode.properties[ngModuleConfigObjectNode.properties.length - 1]; - const newTargetPropertyNode = ts.createIdentifier(`${targetPropertyName}: [${newPropertyValue}]`); + + const newTargetPropertyNode = ts.createPropertyAssignment(targetPropertyName, ts.createIdentifier(`[${newPropertyValue}]`)); return [ new AddNodeOperation(sourceFile, lastConfigObjPropertyNode, undefined, newTargetPropertyNode), From 7d18cc19b25d6eae547acba25f15db88a29ad46c Mon Sep 17 00:00:00 2001 From: DimitarTachev Date: Tue, 2 Jul 2019 11:17:02 +0300 Subject: [PATCH 5/7] fix: unify the TypeScript version with the Angular App (trying to fix the CI) --- demo/TypeScriptApp/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demo/TypeScriptApp/package.json b/demo/TypeScriptApp/package.json index f98d9675..aabe8c7e 100644 --- a/demo/TypeScriptApp/package.json +++ b/demo/TypeScriptApp/package.json @@ -28,7 +28,7 @@ "mochawesome": "~3.1.2", "nativescript-dev-appium": "next", "nativescript-dev-webpack": "next", - "typescript": "~3.2.2", + "typescript": "~3.4.1", "node-sass": "^4.12.0" }, "scripts": { From f558607d95ed2b7bed962c3de06d2b94524e2184 Mon Sep 17 00:00:00 2001 From: Rosen Vladimirov Date: Tue, 2 Jul 2019 13:34:08 +0300 Subject: [PATCH 6/7] feat(hooks): improve hooks handling (#961) * fix(preuninstall): add preuninstall script to remove old hooks During migration from one version to another or when the plugin is removed from application we need to remove its hooks. This is usually done in preuninstall script, however, it was missing until now. This causes several issues when the version is updated as old hooks remain, but they may not be valid anymore. * fix(postinstall): remove old hooks As in 1.0.0 and CLI 6.0 we've changed the way nativescript-dev-webpack interacts with CLI, we need to remove hooks from previous nativescript-dev-webpack versions and use new ones. Usually this should happen with preuninstall script of the old version that removes the hooks. However, our current live version does not have such logic, so implement this in the postinstall of the current version. This way we try to ensure the current plugin will work correctly. * feat(hooks): add before-checkForChanges hook Add before-checkForChanges hook to prevent users from using the current version of the plugin with CLI 5.x.x or older. These two versions are incompatible, so add an error in case older CLI is used. --- lib/before-checkForChanges.js | 16 ++++++++++++++ package.json | 6 ++++++ postinstall.js | 39 +++++++++++++++++++++++++++++++++-- preuninstall.js | 11 ++++++++++ 4 files changed, 70 insertions(+), 2 deletions(-) create mode 100644 lib/before-checkForChanges.js create mode 100644 preuninstall.js diff --git a/lib/before-checkForChanges.js b/lib/before-checkForChanges.js new file mode 100644 index 00000000..d456a1d3 --- /dev/null +++ b/lib/before-checkForChanges.js @@ -0,0 +1,16 @@ +module.exports = function ($staticConfig, hookArgs) { + const majorVersionMatch = ($staticConfig.version || '').match(/^(\d+)\./); + const majorVersion = majorVersionMatch && majorVersionMatch[1] && +majorVersionMatch[1]; + if (majorVersion && majorVersion < 6) { + // check if we are using the bundle workflow or the legacy one. + const isUsingBundleWorkflow = hookArgs && + hookArgs.checkForChangesOpts && + hookArgs.checkForChangesOpts.projectChangesOptions && + hookArgs.checkForChangesOpts.projectChangesOptions.bundle; + + if (isUsingBundleWorkflow) { + const packageJsonData = require("../package.json") + throw new Error(`The current version of ${packageJsonData.name} (${packageJsonData.version}) is not compatible with the used CLI: ${$staticConfig.version}. Please upgrade your NativeScript CLI version (npm i -g nativescript).`); + } + } +} \ No newline at end of file diff --git a/package.json b/package.json index 24e125e1..de7ef1b9 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,11 @@ "type": "after-prepare", "script": "lib/after-prepare.js", "inject": true + }, + { + "type": "before-checkForChanges", + "script": "lib/before-checkForChanges.js", + "inject": true } ] }, @@ -24,6 +29,7 @@ }, "scripts": { "postinstall": "node postinstall.js", + "preuninstall": "node preuninstall.js", "postpack": "rm -rf node_modules", "prepare": "tsc && npm run jasmine", "test": "npm run prepare && npm run jasmine", diff --git a/postinstall.js b/postinstall.js index 54d6b163..1956dcf5 100644 --- a/postinstall.js +++ b/postinstall.js @@ -1,16 +1,50 @@ "use strict"; -const { dirname } = require("path"); const hook = require("nativescript-hook")(__dirname); const { compareProjectFiles } = require("./projectFilesManager"); const { getProjectDir } = require("./projectHelpers"); +const path = require("path"); +const fs = require("fs"); const projectDir = getProjectDir(); +// This method is introduced as in version 1.0.0 of nativescript-dev-webpack (compatible and required for NativeScript 6.0.0) +// we have changed a lot of hooks and old ones are incompatible. This should be automatically handled with preuninstall script of the old version. +// However, old versions of nativescript-dev-webpack do not have such logic, so remove them manually on postinstall of the current version. +// This logic can be removed later, once most of the projects are migrated to 1.0.0 of the package or later. +// These new versions have preuninstall script that will automatically handle this case. +function removeOldHooks() { + const oldHooks = [ + "before-prepareJSApp", + "before-cleanApp", + "before-watch", + "after-watch", + "before-watchPatterns", + "before-shouldPrepare", + "after-prepare", + "before-preview-sync" + ]; + + const hooksDir = path.join(projectDir, "hooks"); + const pkgName = require("./package.json").name; + const filename = `${pkgName}.js`; + oldHooks.forEach(hookName => { + const hookPath = path.join(hooksDir, hookName, filename); + + try { + if (fs.existsSync(hookPath)) { + fs.unlinkSync(hookPath); + } + } catch (err) { + console.warn(`${pkgName} postinstall task: unable to delete hook ${hookPath}. Error is: ${err}`); + } + }); +} + if (projectDir) { compareProjectFiles(projectDir); - + removeOldHooks(); hook.postinstall(); const installer = require("./installer"); installer.install(); @@ -18,3 +52,4 @@ if (projectDir) { // We are installing dev dependencies for the nativescript-dev-webpack plugin. console.log("Skipping postinstall artifacts! We assumed the nativescript-dev-webpack is installing devDependencies"); } + diff --git a/preuninstall.js b/preuninstall.js new file mode 100644 index 00000000..8632200f --- /dev/null +++ b/preuninstall.js @@ -0,0 +1,11 @@ +"use strict"; + +const hook = require("nativescript-hook")(__dirname); + +const { getProjectDir } = require("./projectHelpers"); + +const projectDir = getProjectDir(); + +if (projectDir) { + hook.preuninstall(); +} From 8c4292e09add87b28b08d4439999413ed3d314d0 Mon Sep 17 00:00:00 2001 From: DimitarTachev Date: Wed, 3 Jul 2019 09:47:59 +0300 Subject: [PATCH 7/7] fix: allow overriding the `global.process` object from both the app and the plugins By default it will be undefined but the plugins and the app developers will be able to polyfill it. We had the same behavior with the Legacy Workflow. --- templates/webpack.angular.js | 2 +- templates/webpack.javascript.js | 2 +- templates/webpack.typescript.js | 2 +- templates/webpack.vue.js | 5 +++-- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/templates/webpack.angular.js b/templates/webpack.angular.js index e94ffc0d..22b0b558 100644 --- a/templates/webpack.angular.js +++ b/templates/webpack.angular.js @@ -262,7 +262,7 @@ module.exports = env => { // Define useful constants like TNS_WEBPACK new webpack.DefinePlugin({ "global.TNS_WEBPACK": "true", - "process": undefined, + "process": "global.process", }), // Remove all files from the out dir. new CleanWebpackPlugin(itemsToClean, { verbose: !!verbose }), diff --git a/templates/webpack.javascript.js b/templates/webpack.javascript.js index c910a055..b976e827 100644 --- a/templates/webpack.javascript.js +++ b/templates/webpack.javascript.js @@ -213,7 +213,7 @@ module.exports = env => { // Define useful constants like TNS_WEBPACK new webpack.DefinePlugin({ "global.TNS_WEBPACK": "true", - "process": undefined, + "process": "global.process", }), // Remove all files from the out dir. new CleanWebpackPlugin(itemsToClean, { verbose: !!verbose }), diff --git a/templates/webpack.typescript.js b/templates/webpack.typescript.js index daf5a94b..b04e72e2 100644 --- a/templates/webpack.typescript.js +++ b/templates/webpack.typescript.js @@ -237,7 +237,7 @@ module.exports = env => { // Define useful constants like TNS_WEBPACK new webpack.DefinePlugin({ "global.TNS_WEBPACK": "true", - "process": undefined, + "process": "global.process", }), // Remove all files from the out dir. new CleanWebpackPlugin(itemsToClean, { verbose: !!verbose }), diff --git a/templates/webpack.vue.js b/templates/webpack.vue.js index 1d451d4c..600c399c 100644 --- a/templates/webpack.vue.js +++ b/templates/webpack.vue.js @@ -75,7 +75,7 @@ module.exports = env => { itemsToClean.push(`${join(projectRoot, "platforms", "android", "app", "src", "main", "assets", "snapshots")}`); itemsToClean.push(`${join(projectRoot, "platforms", "android", "app", "build", "configurations", "nativescript-android-snapshot")}`); } - + const config = { mode: mode, context: appFullPath, @@ -238,7 +238,8 @@ module.exports = env => { // Define useful constants like TNS_WEBPACK new webpack.DefinePlugin({ "global.TNS_WEBPACK": "true", - "TNS_ENV": JSON.stringify(mode) + "TNS_ENV": JSON.stringify(mode), + "process": "global.process" }), // Remove all files from the out dir. new CleanWebpackPlugin(itemsToClean, { verbose: !!verbose }),