diff --git a/demo/AngularApp/package.json b/demo/AngularApp/package.json index ad3c59d4..e2241aaa 100644 --- a/demo/AngularApp/package.json +++ b/demo/AngularApp/package.json @@ -42,9 +42,8 @@ "mocha": "~5.2.0", "mochawesome": "~3.1.2", "nativescript-dev-appium": "next", - "nativescript-dev-sass": "next", - "nativescript-dev-typescript": "next", "nativescript-dev-webpack": "next", + "node-sass": "^4.12.0", "typescript": "~3.4.5" }, "scripts": { diff --git a/demo/AngularApp/webpack.config.js b/demo/AngularApp/webpack.config.js index bd41e4f5..9019eea7 100644 --- a/demo/AngularApp/webpack.config.js +++ b/demo/AngularApp/webpack.config.js @@ -44,13 +44,15 @@ module.exports = env => { // You can provide the following flags when running 'tns run android|ios' aot, // --env.aot - snapshot, // --env.snapshot + snapshot, // --env.snapshot, + production, // --env.production uglify, // --env.uglify report, // --env.report sourceMap, // --env.sourceMap hiddenSourceMap, // --env.hiddenSourceMap hmr, // --env.hmr, unitTesting, // --env.unitTesting + verbose, // --env.verbose } = env; const isAnySourceMapEnabled = !!sourceMap || !!hiddenSourceMap; @@ -60,8 +62,9 @@ module.exports = env => { const tsConfigName = "tsconfig.tns.json"; const entryModule = `${nsWebpack.getEntryModule(appFullPath, platform)}.ts`; const entryPath = `.${sep}${entryModule}`; - const entries = { bundle: entryPath, application: "./application.android" }; - if (platform === "ios") { + const entries = { bundle: entryPath }; + const areCoreModulesExternal = Array.isArray(env.externals) && env.externals.some(e => e.indexOf("tns-core-modules") > -1); + if (platform === "ios" && !areCoreModulesExternal) { entries["tns_modules/tns-core-modules/inspector_modules"] = "inspector_modules"; }; @@ -101,8 +104,14 @@ module.exports = env => { let sourceMapFilename = nsWebpack.getSourceMapFilename(hiddenSourceMap, __dirname, dist); + const itemsToClean = [`${dist}/**/*`]; + if (platform === "android") { + 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: uglify ? "production" : "development", + mode: production ? "production" : "development", context: appFullPath, externals, watchOptions: { @@ -257,7 +266,7 @@ module.exports = env => { "process": undefined, }), // Remove all files from the out dir. - new CleanWebpackPlugin([`${dist}/**/*`]), + new CleanWebpackPlugin(itemsToClean, { verbose: !!verbose }), // Copy assets to out dir. Add your own globs as needed. new CopyWebpackPlugin([ { from: { glob: "fonts/**" } }, @@ -274,19 +283,6 @@ module.exports = env => { ], }; - // Copy the native app resources to the out dir - // only if doing a full build (tns run/build) and not previewing (tns preview) - if (!externals || externals.length === 0) { - config.plugins.push(new CopyWebpackPlugin([ - { - from: `${appResourcesFullPath}/${appResourcesPlatformDir}`, - to: `${dist}/App_Resources/${appResourcesPlatformDir}`, - context: projectRoot - }, - ])); - } - - if (report) { // Generate report files for bundles content config.plugins.push(new BundleAnalyzerPlugin({ diff --git a/demo/JavaScriptApp/app/activity.android.js b/demo/JavaScriptApp/app/activity.android.js index 14120ab4..443eb271 100644 --- a/demo/JavaScriptApp/app/activity.android.js +++ b/demo/JavaScriptApp/app/activity.android.js @@ -1,4 +1,4 @@ -const frame = require("ui/frame"); +const frame = require("tns-core-modules/ui/frame"); const superProto = androidx.appcompat.app.AppCompatActivity.prototype; androidx.appcompat.app.AppCompatActivity.extend("org.myApp.MainActivity", { diff --git a/demo/JavaScriptApp/app/app.js b/demo/JavaScriptApp/app/app.js index 3294b628..614b1678 100644 --- a/demo/JavaScriptApp/app/app.js +++ b/demo/JavaScriptApp/app/app.js @@ -4,7 +4,7 @@ You can use this file to perform app-level initialization, but the primary purpose of the file is to pass control to the app’s first module. */ -var application = require("application"); +var application = require("tns-core-modules/application"); application.start({ moduleName: "main-page" }); diff --git a/demo/JavaScriptApp/app/main-page.android.js b/demo/JavaScriptApp/app/main-page.android.js index 31b03cd3..70a0ab21 100644 --- a/demo/JavaScriptApp/app/main-page.android.js +++ b/demo/JavaScriptApp/app/main-page.android.js @@ -1,4 +1,4 @@ -var frameModule = require("ui/frame"); +var frameModule = require("tns-core-modules/ui/frame"); var createViewModel = require("./main-view-model").createViewModel; function onNavigatingTo(args) { diff --git a/demo/JavaScriptApp/app/main-page.ios.js b/demo/JavaScriptApp/app/main-page.ios.js index 1330474f..094ffd4a 100644 --- a/demo/JavaScriptApp/app/main-page.ios.js +++ b/demo/JavaScriptApp/app/main-page.ios.js @@ -1,4 +1,4 @@ -var frameModule = require("ui/frame"); +var frameModule = require("tns-core-modules/ui/frame"); var createViewModel = require("./main-view-model").createViewModel; function onNavigatingTo(args) { diff --git a/demo/JavaScriptApp/app/main-view-model.js b/demo/JavaScriptApp/app/main-view-model.js index c0993f5a..20ab082e 100644 --- a/demo/JavaScriptApp/app/main-view-model.js +++ b/demo/JavaScriptApp/app/main-view-model.js @@ -1,4 +1,4 @@ -var Observable = require("data/observable").Observable; +var Observable = require("tns-core-modules/data/observable").Observable; function getMessage(counter) { if (counter <= 0) { diff --git a/demo/JavaScriptApp/package.json b/demo/JavaScriptApp/package.json index 4118a33c..58364992 100644 --- a/demo/JavaScriptApp/package.json +++ b/demo/JavaScriptApp/package.json @@ -27,9 +27,8 @@ "mocha": "~5.2.0", "mochawesome": "~3.1.2", "nativescript-dev-appium": "next", - "nativescript-dev-sass": "next", "nativescript-dev-webpack": "next", - "node-sass": "^4.7.1" + "node-sass": "4.12.0" }, "scripts": { "setup": "npm pack ../../ && npm i -D nativescript-dev-webpack*.tgz", diff --git a/demo/JavaScriptApp/webpack.config.js b/demo/JavaScriptApp/webpack.config.js index e6156dca..6d8c7c8c 100644 --- a/demo/JavaScriptApp/webpack.config.js +++ b/demo/JavaScriptApp/webpack.config.js @@ -5,6 +5,7 @@ const nsWebpack = require("nativescript-dev-webpack"); const nativescriptTarget = require("nativescript-dev-webpack/nativescript-target"); const CleanWebpackPlugin = require("clean-webpack-plugin"); const CopyWebpackPlugin = require("copy-webpack-plugin"); +const ExtraWatchWebpackPlugin = require('extra-watch-webpack-plugin'); const { BundleAnalyzerPlugin } = require("webpack-bundle-analyzer"); const { NativeScriptWorkerPlugin } = require("nativescript-worker-loader/NativeScriptWorkerPlugin"); const TerserPlugin = require("terser-webpack-plugin"); @@ -39,12 +40,14 @@ module.exports = env => { // You can provide the following flags when running 'tns run android|ios' snapshot, // --env.snapshot + production, // --env.production uglify, // --env.uglify report, // --env.report sourceMap, // --env.sourceMap hiddenSourceMap, // --env.hiddenSourceMap hmr, // --env.hmr, - unitTesting, // --env.unitTesting + unitTesting, // --env.unitTesting, + verbose, // --env.verbose } = env; const isAnySourceMapEnabled = !!sourceMap || !!hiddenSourceMap; @@ -55,14 +58,21 @@ module.exports = env => { const entryModule = nsWebpack.getEntryModule(appFullPath, platform); const entryPath = `.${sep}${entryModule}.js`; const entries = { bundle: entryPath, application: "./application.android" }; - if (platform === "ios") { + const areCoreModulesExternal = Array.isArray(env.externals) && env.externals.some(e => e.indexOf("tns-core-modules") > -1); + if (platform === "ios" && !areCoreModulesExternal) { entries["tns_modules/tns-core-modules/inspector_modules"] = "inspector_modules"; }; let sourceMapFilename = nsWebpack.getSourceMapFilename(hiddenSourceMap, __dirname, dist); + const itemsToClean = [`${dist}/**/*`]; + if (platform === "android") { + 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: uglify ? "production" : "development", + mode: production ? "production" : "development", context: appFullPath, externals, watchOptions: { @@ -208,7 +218,7 @@ module.exports = env => { "process": undefined, }), // Remove all files from the out dir. - new CleanWebpackPlugin([`${dist}/**/*`]), + new CleanWebpackPlugin(itemsToClean, { verbose: !!verbose }), // Copy assets to out dir. Add your own globs as needed. new CopyWebpackPlugin([ { from: { glob: "fonts/**" } }, @@ -226,21 +236,12 @@ module.exports = env => { }), // Does IPC communication with the {N} CLI to notify events when running in watch mode. new nsWebpack.WatchStateLoggerPlugin(), + new ExtraWatchWebpackPlugin({ + files: [`node_modules/**/*.${platform}.js`] + }) ], }; - // Copy the native app resources to the out dir - // only if doing a full build (tns run/build) and not previewing (tns preview) - if (!externals || externals.length === 0) { - config.plugins.push(new CopyWebpackPlugin([ - { - from: `${appResourcesFullPath}/${appResourcesPlatformDir}`, - to: `${dist}/App_Resources/${appResourcesPlatformDir}`, - context: projectRoot - }, - ])); - } - if (report) { // Generate report files for bundles content config.plugins.push(new BundleAnalyzerPlugin({ diff --git a/demo/TypeScriptApp/app/activity.android.ts b/demo/TypeScriptApp/app/activity.android.ts index 2bbd6398..176e23d1 100644 --- a/demo/TypeScriptApp/app/activity.android.ts +++ b/demo/TypeScriptApp/app/activity.android.ts @@ -1,4 +1,4 @@ -import {setActivityCallbacks, AndroidActivityCallbacks} from "ui/frame"; +import {setActivityCallbacks, AndroidActivityCallbacks} from "tns-core-modules/ui/frame"; @JavaProxy("org.myApp.MainActivity") class Activity extends androidx.appcompat.app.AppCompatActivity { diff --git a/demo/TypeScriptApp/app/app.ts b/demo/TypeScriptApp/app/app.ts index 25278f50..87b66a81 100644 --- a/demo/TypeScriptApp/app/app.ts +++ b/demo/TypeScriptApp/app/app.ts @@ -4,7 +4,7 @@ You can use this file to perform app-level initialization, but the primary purpose of the file is to pass control to the app’s first module. */ -import * as app from 'application'; +import * as app from 'tns-core-modules/application'; app.start({ moduleName: 'main-page' }); diff --git a/demo/TypeScriptApp/app/main-page.ios.ts b/demo/TypeScriptApp/app/main-page.ios.ts index 9cc631bc..02f3fa4c 100644 --- a/demo/TypeScriptApp/app/main-page.ios.ts +++ b/demo/TypeScriptApp/app/main-page.ios.ts @@ -4,11 +4,11 @@ a code-behind file. The code-behind is a great place to place your view logic, and to set up your page’s data binding. */ -import { EventData } from 'data/observable'; -import { Page } from 'ui/page'; +import { EventData } from 'tns-core-modules/data/observable'; +import { Page } from 'tns-core-modules/ui/page'; import { HelloWorldModel } from './main-view-model'; -import { Label } from 'ui/label'; -import * as frameModule from 'ui/frame'; +import { Label } from 'tns-core-modules/ui/label'; +import * as frameModule from 'tns-core-modules/ui/frame'; // Event handler for Page "navigatingTo" event attached in main-page.xml export function onNavigatingTo(args: EventData) { diff --git a/demo/TypeScriptApp/app/main-view-model.ts b/demo/TypeScriptApp/app/main-view-model.ts index c88ea9e5..56936641 100644 --- a/demo/TypeScriptApp/app/main-view-model.ts +++ b/demo/TypeScriptApp/app/main-view-model.ts @@ -1,4 +1,4 @@ -import {Observable} from 'data/observable'; +import {Observable} from 'tns-core-modules/data/observable'; export class HelloWorldModel extends Observable { diff --git a/demo/TypeScriptApp/package.json b/demo/TypeScriptApp/package.json index 62c8f58c..f98d9675 100644 --- a/demo/TypeScriptApp/package.json +++ b/demo/TypeScriptApp/package.json @@ -27,10 +27,9 @@ "mocha": "~5.2.0", "mochawesome": "~3.1.2", "nativescript-dev-appium": "next", - "nativescript-dev-sass": "next", - "nativescript-dev-typescript": "next", "nativescript-dev-webpack": "next", - "typescript": "~3.2.2" + "typescript": "~3.2.2", + "node-sass": "^4.12.0" }, "scripts": { "setup": "npm pack ../../ && npm i -D nativescript-dev-webpack*.tgz", diff --git a/demo/TypeScriptApp/webpack.config.js b/demo/TypeScriptApp/webpack.config.js index 64e87be0..30e2c763 100644 --- a/demo/TypeScriptApp/webpack.config.js +++ b/demo/TypeScriptApp/webpack.config.js @@ -6,6 +6,7 @@ const nativescriptTarget = require("nativescript-dev-webpack/nativescript-target const CleanWebpackPlugin = require("clean-webpack-plugin"); const CopyWebpackPlugin = require("copy-webpack-plugin"); const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin'); +const ExtraWatchWebpackPlugin = require('extra-watch-webpack-plugin'); const { BundleAnalyzerPlugin } = require("webpack-bundle-analyzer"); const { NativeScriptWorkerPlugin } = require("nativescript-worker-loader/NativeScriptWorkerPlugin"); const TerserPlugin = require("terser-webpack-plugin"); @@ -40,12 +41,14 @@ module.exports = env => { // You can provide the following flags when running 'tns run android|ios' snapshot, // --env.snapshot + production, // --env.production uglify, // --env.uglify report, // --env.report sourceMap, // --env.sourceMap hiddenSourceMap, // --env.hiddenSourceMap hmr, // --env.hmr, - unitTesting, // --env.unitTesting + unitTesting, // --env.unitTesting, + verbose, // --env.verbose } = env; const isAnySourceMapEnabled = !!sourceMap || !!hiddenSourceMap; const externals = nsWebpack.getConvertedExternals(env.externals); @@ -59,14 +62,21 @@ module.exports = env => { const tsConfigPath = resolve(projectRoot, "tsconfig.tns.json"); - if (platform === "ios") { + const areCoreModulesExternal = Array.isArray(env.externals) && env.externals.some(e => e.indexOf("tns-core-modules") > -1); + if (platform === "ios" && !areCoreModulesExternal) { entries["tns_modules/tns-core-modules/inspector_modules"] = "inspector_modules"; }; let sourceMapFilename = nsWebpack.getSourceMapFilename(hiddenSourceMap, __dirname, dist); + const itemsToClean = [`${dist}/**/*`]; + if (platform === "android") { + 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: uglify ? "production" : "development", + mode: production ? "production" : "development", context: appFullPath, externals, watchOptions: { @@ -212,10 +222,13 @@ module.exports = env => { loader: "ts-loader", options: { configFile: tsConfigPath, - transpileOnly: !!hmr, + // https://github.com/TypeStrong/ts-loader/blob/ea2fcf925ec158d0a536d1e766adfec6567f5fb4/README.md#faster-builds + // https://github.com/TypeStrong/ts-loader/blob/ea2fcf925ec158d0a536d1e766adfec6567f5fb4/README.md#hot-module-replacement + transpileOnly: true, allowTsInNodeModules: true, compilerOptions: { - sourceMap: isAnySourceMapEnabled + sourceMap: isAnySourceMapEnabled, + declaration: false } }, } @@ -229,7 +242,7 @@ module.exports = env => { "process": undefined, }), // Remove all files from the out dir. - new CleanWebpackPlugin([`${dist}/**/*`]), + new CleanWebpackPlugin(itemsToClean, { verbose: !!verbose }), // Copy assets to out dir. Add your own globs as needed. new CopyWebpackPlugin([ { from: { glob: "fonts/**" } }, @@ -246,21 +259,20 @@ module.exports = env => { }), // Does IPC communication with the {N} CLI to notify events when running in watch mode. new nsWebpack.WatchStateLoggerPlugin(), + // https://github.com/TypeStrong/ts-loader/blob/ea2fcf925ec158d0a536d1e766adfec6567f5fb4/README.md#faster-builds + // https://github.com/TypeStrong/ts-loader/blob/ea2fcf925ec158d0a536d1e766adfec6567f5fb4/README.md#hot-module-replacement + new ForkTsCheckerWebpackPlugin({ + tsconfig: tsConfigPath, + async: false, + useTypescriptIncrementalApi: true, + memoryLimit: 4096 + }), + new ExtraWatchWebpackPlugin({ + files: [`node_modules/**/*.${platform}.ts`] + }) ], }; - // Copy the native app resources to the out dir - // only if doing a full build (tns run/build) and not previewing (tns preview) - if (!externals || externals.length === 0) { - config.plugins.push(new CopyWebpackPlugin([ - { - from: `${appResourcesFullPath}/${appResourcesPlatformDir}`, - to: `${dist}/App_Resources/${appResourcesPlatformDir}`, - context: projectRoot - }, - ])); - } - if (report) { // Generate report files for bundles content config.plugins.push(new BundleAnalyzerPlugin({ @@ -285,12 +297,6 @@ module.exports = env => { if (hmr) { config.plugins.push(new webpack.HotModuleReplacementPlugin()); - - // With HMR ts-loader should run in `transpileOnly` mode, - // so assure type-checking with fork-ts-checker-webpack-plugin - config.plugins.push(new ForkTsCheckerWebpackPlugin({ - tsconfig: tsConfigPath - })); } diff --git a/lib/after-prepare.js b/lib/after-prepare.js index 2f647f1c..f876e6e6 100644 --- a/lib/after-prepare.js +++ b/lib/after-prepare.js @@ -2,15 +2,13 @@ const { installSnapshotArtefacts } = require("../snapshot/android/project-snapsh const { shouldSnapshot } = require("./utils"); module.exports = function (hookArgs) { - const env = hookArgs.env || {}; - env.hmr = hookArgs.appFilesUpdaterOptions.useHotModuleReload; + const env = hookArgs.prepareData.env || {}; const shouldSnapshotOptions = { - platform: hookArgs.platform, - bundle: hookArgs.appFilesUpdaterOptions.bundle, - release: hookArgs.appFilesUpdaterOptions.release + platform: hookArgs.prepareData.platform, + release: hookArgs.prepareData.release }; if (env.snapshot && shouldSnapshot(shouldSnapshotOptions)) { - installSnapshotArtefacts(hookArgs.projectData.projectDir); + installSnapshotArtefacts(hookArgs.prepareData.projectDir); } } diff --git a/lib/after-watch.js b/lib/after-watch.js deleted file mode 100644 index 85e8cb20..00000000 --- a/lib/after-watch.js +++ /dev/null @@ -1,8 +0,0 @@ -const { stopWebpackCompiler } = require('./compiler'); -const { removeListener } = require("./utils"); - -module.exports = function($logger, $liveSyncService) { - stopWebpackCompiler($logger); - removeListener($liveSyncService, "liveSyncStopped"); - removeListener(process, "exit"); -} diff --git a/lib/before-cleanApp.js b/lib/before-cleanApp.js deleted file mode 100644 index 70a06b0a..00000000 --- a/lib/before-cleanApp.js +++ /dev/null @@ -1,16 +0,0 @@ -const { cleanSnapshotArtefacts } = require("../snapshot/android/project-snapshot-generator"); -const { isAndroid } = require("../projectHelpers"); -const { getWebpackProcesses } = require("./compiler"); - -module.exports = function (hookArgs) { - return (args, originalMethod) => { - const platform = hookArgs.platformInfo.platform; - const webpackProcesses = getWebpackProcesses(); - const promise = webpackProcesses[platform] ? Promise.resolve() : originalMethod(...args); - return promise.then(() => { - if (isAndroid(platform)) { - cleanSnapshotArtefacts(hookArgs.platformInfo.projectData.projectDir); - } - }); - } -} diff --git a/lib/before-prepareJS.js b/lib/before-prepareJS.js deleted file mode 100644 index debd93dd..00000000 --- a/lib/before-prepareJS.js +++ /dev/null @@ -1,17 +0,0 @@ -const { runWebpackCompiler } = require("./compiler"); - -module.exports = function ($logger, $liveSyncService, hookArgs) { - const platform = hookArgs.config.platform; - const appFilesUpdaterOptions = hookArgs.config.appFilesUpdaterOptions; - const env = hookArgs.config.env || {}; - env.hmr = appFilesUpdaterOptions.useHotModuleReload; - const config = { - env, - platform, - bundle: appFilesUpdaterOptions.bundle, - release: appFilesUpdaterOptions.release, - }; - - const result = config.bundle && runWebpackCompiler.bind(runWebpackCompiler, config, hookArgs.config.projectData, $logger, $liveSyncService, hookArgs); - return result; -} diff --git a/lib/before-preview-sync.js b/lib/before-preview-sync.js deleted file mode 100644 index f15cefcd..00000000 --- a/lib/before-preview-sync.js +++ /dev/null @@ -1,22 +0,0 @@ -const { runWebpackCompiler } = require("./compiler"); - -module.exports = function($logger, $liveSyncService, hookArgs) { - const { config } = hookArgs; - const bundle = config && config.appFilesUpdaterOptions && config.appFilesUpdaterOptions.bundle; - if (bundle) { - const env = config.env || {}; - env.hmr = config.appFilesUpdaterOptions.useHotModuleReload; - const platform = config.platform; - const release = config && config.appFilesUpdaterOptions && config.appFilesUpdaterOptions.release; - const compilerConfig = { - env, - platform, - bundle, - release, - watch: true - }; - - return runWebpackCompiler(compilerConfig, hookArgs.projectData, $logger, $liveSyncService, hookArgs); - } -} - diff --git a/lib/before-shouldPrepare.js b/lib/before-shouldPrepare.js deleted file mode 100644 index f61fa2df..00000000 --- a/lib/before-shouldPrepare.js +++ /dev/null @@ -1,25 +0,0 @@ -const { join } = require("path"); -const { readFileSync, existsSync, writeFileSync } = require("fs"); -const envOptionsCacheFileLocation = join(__dirname, "env.cache.json"); - -module.exports = function (hookArgs) { - const platformInfo = hookArgs.shouldPrepareInfo && hookArgs.shouldPrepareInfo.platformInfo; - if (platformInfo && platformInfo.appFilesUpdaterOptions && platformInfo.appFilesUpdaterOptions.bundle) { - - return (args, originalMethod) => { - return originalMethod(...args).then(originalShouldPrepare => { - const currentEnvString = JSON.stringify(platformInfo.env || {}); - if (existsSync(envOptionsCacheFileLocation)) { - const oldEnvOptionsString = readFileSync(envOptionsCacheFileLocation).toString(); - if (oldEnvOptionsString === currentEnvString) { - return originalShouldPrepare; - } - } - - writeFileSync(envOptionsCacheFileLocation, currentEnvString); - - return true; - }); - }; - } -} diff --git a/lib/before-watch.js b/lib/before-watch.js deleted file mode 100644 index 84ba260d..00000000 --- a/lib/before-watch.js +++ /dev/null @@ -1,35 +0,0 @@ -const { getWebpackProcesses, runWebpackCompiler, stopWebpackCompiler } = require("./compiler"); -const { addListener } = require("./utils"); - -module.exports = function ($logger, $liveSyncService, $devicesService, hookArgs) { - if (hookArgs.config) { - const appFilesUpdaterOptions = hookArgs.config.appFilesUpdaterOptions; - if (appFilesUpdaterOptions.bundle) { - addListener($liveSyncService, "liveSyncStopped", () => { - const webpackProcesses = getWebpackProcesses(); - Object.keys(webpackProcesses).forEach(platform => { - const devices = $devicesService.getDevicesForPlatform(platform); - if (!devices || !devices.length) { - stopWebpackCompiler($logger, platform); - } - }); - }); - addListener(process, "exit", () => stopWebpackCompiler($logger)); - - const platforms = hookArgs.config.platforms; - return Promise.all(platforms.map(platform => { - const env = hookArgs.config.env || {}; - env.hmr = appFilesUpdaterOptions.useHotModuleReload; - const config = { - env, - platform, - bundle: appFilesUpdaterOptions.bundle, - release: appFilesUpdaterOptions.release, - watch: true - }; - - return runWebpackCompiler(config, hookArgs.projectData, $logger, $liveSyncService, hookArgs); - })); - } - } -} diff --git a/lib/before-watchPatterns.js b/lib/before-watchPatterns.js deleted file mode 100644 index fddfc999..00000000 --- a/lib/before-watchPatterns.js +++ /dev/null @@ -1,19 +0,0 @@ -const { basename } = require("path"); -const { getAppPathFromProjectData } = require("../projectHelpers"); - -module.exports = function (hookArgs) { - const { liveSyncData } = hookArgs; - if (!liveSyncData || !liveSyncData.bundle) { - return; - } - - return (args, originalMethod) => { - return originalMethod(...args).then(originalPatterns => { - - const appPath = getAppPathFromProjectData(hookArgs.projectData); - const ignorePattern = `!${appPath}`; - - return [...originalPatterns, ignorePattern]; - }); - }; -} diff --git a/lib/compiler.js b/lib/compiler.js deleted file mode 100644 index 6398436c..00000000 --- a/lib/compiler.js +++ /dev/null @@ -1,182 +0,0 @@ -const utils = require("./utils"); -const { spawn } = require("child_process"); -const { resolve: pathResolve } = require("path"); -const { existsSync } = require("fs"); -const readline = require("readline"); - -const { messages } = require("../plugins/WatchStateLoggerPlugin"); -const { buildEnvData, debuggingEnabled, getUpdatedEmittedFiles } = require("./utils"); - -let hasBeenInvoked = false; - -let webpackProcesses = {}; -let hasLoggedSnapshotWarningMessage = false; - -exports.getWebpackProcesses = function getWebpackProcess() { - return webpackProcesses; -} - -exports.runWebpackCompiler = function runWebpackCompiler(config, $projectData, $logger, $liveSyncService, hookArgs) { - if (config.bundle) { - return new Promise(function (resolveBase, rejectBase) { - if (webpackProcesses[config.platform]) { - return resolveBase(); - } - - let isResolved = false; - function resolve() { - if (isResolved) return; - isResolved = true; - resolveBase(); - } - function reject(error) { - if (isResolved) return; - isResolved = true; - rejectBase(error); - } - - console.log(`Running webpack for ${config.platform}...`); - - const projectDir = $projectData.projectDir; - const { platform, env } = config; - if (debuggingEnabled($liveSyncService, projectDir)) { - env["sourceMap"] = true; - } - - // Currently externals param is passed only from before-preview-sync hook. This hook is triggered only when `tns preview --bundle` command is executed - if (hookArgs && hookArgs.externals) { - env.externals = hookArgs.externals; - } - - const envData = buildEnvData($projectData, platform, env); - const envParams = buildEnvCommandLineParams(config, envData, $logger); - - const args = [ - "--preserve-symlinks", - pathResolve(projectDir, "node_modules", "webpack", "bin", "webpack.js"), - `--config=${pathResolve(projectDir, "webpack.config.js")}`, - ...(config.watch ? ["--watch"] : []), - ...envParams, - ].filter(a => !!a); - - const childProcess = spawn("node", args, { - // Watch opens IPC so we don't mess with the stdin/out/err. - // These will notify us for the webpack compilation states. - // Enables `childProcess.on("message", msg => ...)` kind of communication. - stdio: config.watch ? ["inherit", "inherit", "inherit", "ipc"] : "inherit", - cwd: projectDir - }); - - let isFirstWebpackWatchCompilation = true; - function resolveOnWebpackCompilationComplete(message) { - if (message === messages.compilationComplete) { - console.log("Webpack build done!"); - resolve(); - } - - if (message.emittedFiles) { - if (isFirstWebpackWatchCompilation) { - isFirstWebpackWatchCompilation = false; - return; - } - - const result = getUpdatedEmittedFiles(message.emittedFiles, message.webpackRuntimeFiles); - - if (hookArgs.hmrData) { - hookArgs.hmrData[platform] = { - hash: result.hash || "", - fallbackFiles: result.fallbackFiles - }; - } - - if (hookArgs.filesToSyncMap && hookArgs.startSyncFilesTimeout) { - hookArgs.filesToSyncMap[platform] = result.emittedFiles; - hookArgs.startSyncFilesTimeout(platform); - } else if (hookArgs.filesToSync && hookArgs.startSyncFilesTimeout) { - hookArgs.filesToSync.push(...result.emittedFiles); - hookArgs.startSyncFilesTimeout(platform); - } - } - } - - if (config.watch) { - childProcess.on("message", resolveOnWebpackCompilationComplete); - if (webpackProcesses[platform]) { - throw new Error("Webpack process already spawned."); - } - webpackProcesses[platform] = childProcess; - } - - childProcess.on("close", code => { - if (webpackProcesses[platform] === childProcess) { - delete webpackProcesses[platform]; - } - if (code === 0) { - resolve(); - } else { - const error = new Error(`Executing webpack failed with exit code ${code}.`); - error.code = code; - reject(error); - } - }); - }); - } -} - -exports.stopWebpackCompiler = function stopWebpackCompiler($logger, platform) { - if (platform) { - stopWebpackForPlatform($logger, platform); - } else { - Object.keys(webpackProcesses).forEach(platform => stopWebpackForPlatform($logger, platform)); - } -} - -function buildEnvCommandLineParams(config, envData, $logger) { - const envFlagNames = Object.keys(envData); - const snapshotEnvIndex = envFlagNames.indexOf("snapshot"); - if (snapshotEnvIndex > -1 && !utils.shouldSnapshot(config)) { - logSnapshotWarningMessage($logger); - envFlagNames.splice(snapshotEnvIndex, 1); - } - - const args = []; - envFlagNames.map(item => { - let envValue = envData[item]; - if (typeof envValue === "undefined") { - return; - } - if (typeof envValue === "boolean") { - if (envValue) { - args.push(`--env.${item}`); - } - } else { - if (!Array.isArray(envValue)) { - envValue = [envValue]; - } - - envValue.map(value => args.push(`--env.${item}=${value}`)) - } - }); - - return args; -} - -function logSnapshotWarningMessage($logger) { - if (!hasLoggedSnapshotWarningMessage) { - $logger.warn("Stripping the snapshot flag. " + - "Bear in mind that snapshot is only available in release builds and " + - "is NOT available on Windows systems."); - - hasLoggedSnapshotWarningMessage = true; - } -} - -function stopWebpackForPlatform($logger, platform) { - $logger.trace(`Stopping webpack watch for platform ${platform}.`); - const webpackProcess = webpackProcesses[platform]; - if (webpackProcess) { - webpackProcess.kill("SIGINT"); - delete webpackProcesses[platform]; - } -} - diff --git a/lib/utils.js b/lib/utils.js index b5341c52..a527b24a 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -1,97 +1,11 @@ const os = require("os"); - -const { - getAppPathFromProjectData, - getAppResourcesPathFromProjectData, - isAndroid, -} = require("../projectHelpers"); - -const eventHandlers = {}; - -function debuggingEnabled(liveSyncService, projectDir) { - const deviceDescriptors = liveSyncService.getLiveSyncDeviceDescriptors(projectDir); - return deviceDescriptors.some(device => device.debugggingEnabled); -} - -function buildEnvData($projectData, platform, env) { - const envData = Object.assign({}, - env, - { [platform.toLowerCase()]: true } - ); - - const appPath = getAppPathFromProjectData($projectData); - const appResourcesPath = getAppResourcesPathFromProjectData($projectData); - Object.assign(envData, - appPath && { appPath }, - appResourcesPath && { appResourcesPath } - ); - - return envData; -} - -/** - * Checks if there's a file in the following pattern 5e0326f3bb50f9f26cf0.hot-update.json - * if yes this is a HMR update and remove all bundle files as we don't need them to be synced, - * but only the update chunks - */ -function getUpdatedEmittedFiles(emittedFiles, webpackRuntimeFiles) { - let fallbackFiles = []; - let hotHash; - if (emittedFiles.some(x => x.endsWith('.hot-update.json'))) { - let result = emittedFiles.slice(); - const hotUpdateScripts = emittedFiles.filter(x => x.endsWith('.hot-update.js')); - hotUpdateScripts.forEach(hotUpdateScript => { - const { name, hash } = parseHotUpdateChunkName(hotUpdateScript); - hotHash = hash; - // remove bundle/vendor.js files if there's a bundle.XXX.hot-update.js or vendor.XXX.hot-update.js - result = result.filter(file => file !== `${name}.js`); - if (webpackRuntimeFiles && webpackRuntimeFiles.length) { - // remove files containing only the Webpack runtime (e.g. runtime.js) - result = result.filter(file => webpackRuntimeFiles.indexOf(file) === -1); - } - }); - //if applying of hot update fails, we must fallback to the full files - fallbackFiles = emittedFiles.filter(file => result.indexOf(file) === -1); - return { emittedFiles: result, fallbackFiles, hash: hotHash }; - } - else { - return { emittedFiles, fallbackFiles }; - } -} - -/** - * Parse the filename of the hot update chunk. - * @param name bundle.deccb264c01d6d42416c.hot-update.js - * @returns { name: string, hash: string } { name: 'bundle', hash: 'deccb264c01d6d42416c' } - */ -function parseHotUpdateChunkName(name) { - const matcher = /^(.+)\.(.+)\.hot-update/gm; - const matches = matcher.exec(name); - return { - name: matches[1] || "", - hash: matches[2] || "", - }; -} +const { isAndroid } = require("../projectHelpers"); function shouldSnapshot(config) { const platformSupportsSnapshot = isAndroid(config.platform); const osSupportsSnapshot = os.type() !== "Windows_NT"; - return config.bundle && config.release && platformSupportsSnapshot && osSupportsSnapshot; -} - -function addListener(eventEmitter, name, handler) { - if (!eventHandlers[name]) { - eventEmitter.on(name, handler); - eventHandlers[name] = handler; - } -} - -function removeListener(eventEmitter, name) { - if (eventHandlers[name]) { - eventEmitter.removeListener(name, eventHandlers[name]); - delete eventHandlers[name]; - } + return config.release && platformSupportsSnapshot && osSupportsSnapshot; } function convertToUnixPath(relativePath) { @@ -99,12 +13,6 @@ function convertToUnixPath(relativePath) { } module.exports = { - buildEnvData, - debuggingEnabled, shouldSnapshot, - getUpdatedEmittedFiles, - parseHotUpdateChunkName, - addListener, - removeListener, convertToUnixPath }; diff --git a/package.json b/package.json index 62882c62..a4e474b9 100644 --- a/package.json +++ b/package.json @@ -10,45 +10,10 @@ ], "nativescript": { "hooks": [ - { - "type": "before-prepareJSApp", - "script": "lib/before-prepareJS.js", - "inject": true - }, - { - "type": "before-cleanApp", - "script": "lib/before-cleanApp.js", - "inject": true - }, - { - "type": "before-watch", - "script": "lib/before-watch.js", - "inject": true - }, - { - "type": "after-watch", - "script": "lib/after-watch.js", - "inject": true - }, - { - "type": "before-watchPatterns", - "script": "lib/before-watchPatterns.js", - "inject": true - }, - { - "type": "before-shouldPrepare", - "script": "lib/before-shouldPrepare.js", - "inject": true - }, { "type": "after-prepare", "script": "lib/after-prepare.js", "inject": true - }, - { - "type": "before-preview-sync", - "script": "lib/before-preview-sync", - "inject": true } ] }, @@ -79,6 +44,7 @@ "copy-webpack-plugin": "~4.6.0", "css-loader": "~2.1.1", "fork-ts-checker-webpack-plugin": "1.3.0", + "extra-watch-webpack-plugin": "1.0.3", "global-modules-path": "2.0.0", "minimatch": "3.0.4", "nativescript-hook": "0.2.4", diff --git a/plugins/WatchStateLoggerPlugin.ts b/plugins/WatchStateLoggerPlugin.ts index 55cbb8ba..bbcff833 100644 --- a/plugins/WatchStateLoggerPlugin.ts +++ b/plugins/WatchStateLoggerPlugin.ts @@ -1,5 +1,3 @@ -import { join } from "path"; - export enum messages { compilationComplete = "Webpack compilation complete.", startWatching = "Webpack compilation complete. Watching for file changes.", @@ -31,24 +29,21 @@ export class WatchStateLoggerPlugin { console.log(messages.compilationComplete); } - const runtimeOnlyFiles = getWebpackRuntimeOnlyFiles(compilation, compiler.context); let emittedFiles = Object .keys(compilation.assets) .filter(assetKey => compilation.assets[assetKey].emitted); - // provide fake paths to the {N} CLI - relative to the 'app' folder - // in order to trigger the livesync process - const emittedFilesFakePaths = emittedFiles - .map(file => join(compiler.context, file)); + const webpackRuntimeFiles = getWebpackRuntimeOnlyFiles(compilation); + const entryPointFiles = getEntryPointFiles(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: emittedFilesFakePaths, webpackRuntimeFiles: runtimeOnlyFiles }, error => null); + process.send && process.send({ emittedFiles, webpackRuntimeFiles, entryPointFiles }, error => null); }); } } -function getWebpackRuntimeOnlyFiles(compilation, basePath) { +function getWebpackRuntimeOnlyFiles(compilation) { let runtimeOnlyFiles = []; try { runtimeOnlyFiles = [].concat(...Array.from(compilation.entrypoints.values()) @@ -57,9 +52,7 @@ function getWebpackRuntimeOnlyFiles(compilation, basePath) { .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) - // convert to absolute paths - .map(fileName => join(basePath, fileName)); + .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."); @@ -67,3 +60,24 @@ function getWebpackRuntimeOnlyFiles(compilation, basePath) { return runtimeOnlyFiles; } + +function getEntryPointFiles(compilation) { + const entryPointFiles = []; + try { + Array.from(compilation.entrypoints.values()) + .forEach((entrypoint: any) => { + const entryChunk = entrypoint.chunks.find(chunk => chunk.name === entrypoint.options.name); + if (entryChunk) { + entryChunk.files.forEach(fileName => { + if (fileName.indexOf("hot-update") === -1) { + entryPointFiles.push(fileName); + } + }); + } + }); + } catch (e) { + console.log("Warning: Unable to find Webpack entry point files."); + } + + return entryPointFiles; +} \ No newline at end of file diff --git a/projectHelpers.js b/projectHelpers.js index 64862bf3..792dd8fa 100644 --- a/projectHelpers.js +++ b/projectHelpers.js @@ -3,11 +3,6 @@ const fs = require("fs"); const hook = require("nativescript-hook")(__dirname); -const PROJECT_DATA_GETTERS = { - appPath: "getAppDirectoryRelativePath", - appResourcesPath: "getAppResourcesRelativeDirectoryPath", -}; - const isTypeScript = ({ projectDir, packageJson } = {}) => { packageJson = packageJson || getPackageJson(projectDir); @@ -78,14 +73,6 @@ const getPackageJsonPath = projectDir => resolve(projectDir, "package.json"); const isAndroid = platform => /android/i.test(platform); const isIos = platform => /ios/i.test(platform); -function getAppPathFromProjectData(data) { - return safeGet(data, PROJECT_DATA_GETTERS.appPath); -} - -function getAppResourcesPathFromProjectData(data) { - return safeGet(data, PROJECT_DATA_GETTERS.appResourcesPath); -} - function safeGet(object, property, ...args) { if (!object) { return; @@ -112,8 +99,6 @@ function convertSlashesInPath(modulePath) { const isWindows = process.platform.startsWith("win32"); module.exports = { - getAppPathFromProjectData, - getAppResourcesPathFromProjectData, getPackageJson, getProjectDir, isAndroid, diff --git a/templates/webpack.angular.js b/templates/webpack.angular.js index b7d950c0..e94ffc0d 100644 --- a/templates/webpack.angular.js +++ b/templates/webpack.angular.js @@ -43,13 +43,15 @@ module.exports = env => { // You can provide the following flags when running 'tns run android|ios' aot, // --env.aot - snapshot, // --env.snapshot + snapshot, // --env.snapshot, + production, // --env.production uglify, // --env.uglify report, // --env.report sourceMap, // --env.sourceMap hiddenSourceMap, // --env.hiddenSourceMap hmr, // --env.hmr, unitTesting, // --env.unitTesting + verbose, // --env.verbose } = env; const isAnySourceMapEnabled = !!sourceMap || !!hiddenSourceMap; @@ -101,8 +103,14 @@ module.exports = env => { let sourceMapFilename = nsWebpack.getSourceMapFilename(hiddenSourceMap, __dirname, dist); + const itemsToClean = [`${dist}/**/*`]; + if (platform === "android") { + 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: uglify ? "production" : "development", + mode: production ? "production" : "development", context: appFullPath, externals, watchOptions: { @@ -257,7 +265,7 @@ module.exports = env => { "process": undefined, }), // Remove all files from the out dir. - new CleanWebpackPlugin([`${dist}/**/*`]), + new CleanWebpackPlugin(itemsToClean, { verbose: !!verbose }), // Copy assets to out dir. Add your own globs as needed. new CopyWebpackPlugin([ { from: { glob: "fonts/**" } }, @@ -274,19 +282,6 @@ module.exports = env => { ], }; - // Copy the native app resources to the out dir - // only if doing a full build (tns run/build) and not previewing (tns preview) - if (!externals || externals.length === 0) { - config.plugins.push(new CopyWebpackPlugin([ - { - from: `${appResourcesFullPath}/${appResourcesPlatformDir}`, - to: `${dist}/App_Resources/${appResourcesPlatformDir}`, - context: projectRoot - }, - ])); - } - - if (report) { // Generate report files for bundles content config.plugins.push(new BundleAnalyzerPlugin({ diff --git a/templates/webpack.javascript.js b/templates/webpack.javascript.js index 105992d5..fd656554 100644 --- a/templates/webpack.javascript.js +++ b/templates/webpack.javascript.js @@ -5,6 +5,7 @@ const nsWebpack = require("nativescript-dev-webpack"); const nativescriptTarget = require("nativescript-dev-webpack/nativescript-target"); const CleanWebpackPlugin = require("clean-webpack-plugin"); const CopyWebpackPlugin = require("copy-webpack-plugin"); +const ExtraWatchWebpackPlugin = require('extra-watch-webpack-plugin'); const { BundleAnalyzerPlugin } = require("webpack-bundle-analyzer"); const { NativeScriptWorkerPlugin } = require("nativescript-worker-loader/NativeScriptWorkerPlugin"); const TerserPlugin = require("terser-webpack-plugin"); @@ -38,12 +39,14 @@ module.exports = env => { // You can provide the following flags when running 'tns run android|ios' snapshot, // --env.snapshot + production, // --env.production uglify, // --env.uglify report, // --env.report sourceMap, // --env.sourceMap hiddenSourceMap, // --env.hiddenSourceMap hmr, // --env.hmr, - unitTesting, // --env.unitTesting + unitTesting, // --env.unitTesting, + verbose, // --env.verbose } = env; const isAnySourceMapEnabled = !!sourceMap || !!hiddenSourceMap; @@ -61,8 +64,14 @@ module.exports = env => { let sourceMapFilename = nsWebpack.getSourceMapFilename(hiddenSourceMap, __dirname, dist); + const itemsToClean = [`${dist}/**/*`]; + if (platform === "android") { + 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: uglify ? "production" : "development", + mode: production ? "production" : "development", context: appFullPath, externals, watchOptions: { @@ -208,7 +217,7 @@ module.exports = env => { "process": undefined, }), // Remove all files from the out dir. - new CleanWebpackPlugin([`${dist}/**/*`]), + new CleanWebpackPlugin(itemsToClean, { verbose: !!verbose }), // Copy assets to out dir. Add your own globs as needed. new CopyWebpackPlugin([ { from: { glob: "fonts/**" } }, @@ -226,21 +235,12 @@ module.exports = env => { }), // Does IPC communication with the {N} CLI to notify events when running in watch mode. new nsWebpack.WatchStateLoggerPlugin(), + new ExtraWatchWebpackPlugin({ + files: [`node_modules/**/*.${platform}.js`] + }) ], }; - // Copy the native app resources to the out dir - // only if doing a full build (tns run/build) and not previewing (tns preview) - if (!externals || externals.length === 0) { - config.plugins.push(new CopyWebpackPlugin([ - { - from: `${appResourcesFullPath}/${appResourcesPlatformDir}`, - to: `${dist}/App_Resources/${appResourcesPlatformDir}`, - context: projectRoot - }, - ])); - } - if (report) { // Generate report files for bundles content config.plugins.push(new BundleAnalyzerPlugin({ diff --git a/templates/webpack.typescript.js b/templates/webpack.typescript.js index 75efdc61..fd169d2e 100644 --- a/templates/webpack.typescript.js +++ b/templates/webpack.typescript.js @@ -6,6 +6,7 @@ const nativescriptTarget = require("nativescript-dev-webpack/nativescript-target const CleanWebpackPlugin = require("clean-webpack-plugin"); const CopyWebpackPlugin = require("copy-webpack-plugin"); const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin'); +const ExtraWatchWebpackPlugin = require('extra-watch-webpack-plugin'); const { BundleAnalyzerPlugin } = require("webpack-bundle-analyzer"); const { NativeScriptWorkerPlugin } = require("nativescript-worker-loader/NativeScriptWorkerPlugin"); const TerserPlugin = require("terser-webpack-plugin"); @@ -39,12 +40,14 @@ module.exports = env => { // You can provide the following flags when running 'tns run android|ios' snapshot, // --env.snapshot + production, // --env.production uglify, // --env.uglify report, // --env.report sourceMap, // --env.sourceMap hiddenSourceMap, // --env.hiddenSourceMap hmr, // --env.hmr, - unitTesting, // --env.unitTesting + unitTesting, // --env.unitTesting, + verbose, // --env.verbose } = env; const isAnySourceMapEnabled = !!sourceMap || !!hiddenSourceMap; const externals = nsWebpack.getConvertedExternals(env.externals); @@ -65,8 +68,14 @@ module.exports = env => { let sourceMapFilename = nsWebpack.getSourceMapFilename(hiddenSourceMap, __dirname, dist); + const itemsToClean = [`${dist}/**/*`]; + if (platform === "android") { + 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: uglify ? "production" : "development", + mode: production ? "production" : "development", context: appFullPath, externals, watchOptions: { @@ -232,7 +241,7 @@ module.exports = env => { "process": undefined, }), // Remove all files from the out dir. - new CleanWebpackPlugin([`${dist}/**/*`]), + new CleanWebpackPlugin(itemsToClean, { verbose: !!verbose }), // Copy assets to out dir. Add your own globs as needed. new CopyWebpackPlugin([ { from: { glob: "fonts/**" } }, @@ -256,22 +265,13 @@ module.exports = env => { async: false, useTypescriptIncrementalApi: true, memoryLimit: 4096 + }), + new ExtraWatchWebpackPlugin({ + files: [`node_modules/**/*.${platform}.ts`] }) ], }; - // Copy the native app resources to the out dir - // only if doing a full build (tns run/build) and not previewing (tns preview) - if (!externals || externals.length === 0) { - config.plugins.push(new CopyWebpackPlugin([ - { - from: `${appResourcesFullPath}/${appResourcesPlatformDir}`, - to: `${dist}/App_Resources/${appResourcesPlatformDir}`, - context: projectRoot - }, - ])); - } - if (report) { // Generate report files for bundles content config.plugins.push(new BundleAnalyzerPlugin({ diff --git a/templates/webpack.vue.js b/templates/webpack.vue.js index 5f8cbec4..945d1f7f 100644 --- a/templates/webpack.vue.js +++ b/templates/webpack.vue.js @@ -3,6 +3,7 @@ const { join, relative, resolve, sep } = require("path"); const webpack = require("webpack"); const CleanWebpackPlugin = require("clean-webpack-plugin"); const CopyWebpackPlugin = require("copy-webpack-plugin"); +const ExtraWatchWebpackPlugin = require('extra-watch-webpack-plugin'); const { BundleAnalyzerPlugin } = require("webpack-bundle-analyzer"); const TerserPlugin = require("terser-webpack-plugin"); @@ -48,6 +49,7 @@ module.exports = env => { sourceMap, // --env.sourceMap hiddenSourceMap, // --env.hiddenSourceMap unitTesting, // --env.unitTesting + verbose, // --env.verbose } = env; const isAnySourceMapEnabled = !!sourceMap || !!hiddenSourceMap; @@ -69,6 +71,12 @@ module.exports = env => { let sourceMapFilename = nsWebpack.getSourceMapFilename(hiddenSourceMap, __dirname, dist); + const itemsToClean = [`${dist}/**/*`]; + if (platform === "android") { + 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, @@ -234,7 +242,7 @@ module.exports = env => { "TNS_ENV": JSON.stringify(mode) }), // Remove all files from the out dir. - new CleanWebpackPlugin([`${dist}/**/*`]), + new CleanWebpackPlugin(itemsToClean, { verbose: !!verbose }), // Copy assets to out dir. Add your own globs as needed. new CopyWebpackPlugin([ { from: { glob: "fonts/**" } }, @@ -251,6 +259,9 @@ module.exports = env => { }), // Does IPC communication with the {N} CLI to notify events when running in watch mode. new nsWebpack.WatchStateLoggerPlugin(), + new ExtraWatchWebpackPlugin({ + files: [`node_modules/**/*.${platform}.ts`, `node_modules/**/*.${platform}.js`] + }) ], }; @@ -269,18 +280,6 @@ module.exports = env => { ); } - // Copy the native app resources to the out dir - // only if doing a full build (tns run/build) and not previewing (tns preview) - if (!externals || externals.length === 0) { - config.plugins.push(new CopyWebpackPlugin([ - { - from: `${appResourcesFullPath}/${appResourcesPlatformDir}`, - to: `${dist}/App_Resources/${appResourcesPlatformDir}`, - context: projectRoot - }, - ])); - } - if (report) { // Generate report files for bundles content config.plugins.push(new BundleAnalyzerPlugin({