From be52cefe672aaca6d707c1c3b78cee7ee8abe8f1 Mon Sep 17 00:00:00 2001 From: Nathanael Anderson Date: Fri, 29 Jan 2021 14:04:25 -0600 Subject: [PATCH] fix(webpack): --env.uglify works properly now (#9165) --- .prettierignore | 1 + packages/webpack/package.json | 2 +- packages/webpack/templates/webpack.angular.js | 746 ++++++++---------- .../webpack/templates/webpack.javascript.js | 530 ++++++------- packages/webpack/templates/webpack.react.js | 147 ++-- packages/webpack/templates/webpack.svelte.js | 258 +++--- .../webpack/templates/webpack.typescript.js | 604 +++++++------- packages/webpack/templates/webpack.vue.js | 663 ++++++++-------- 8 files changed, 1422 insertions(+), 1529 deletions(-) diff --git a/.prettierignore b/.prettierignore index ab6e626ad..d10e2e5be 100644 --- a/.prettierignore +++ b/.prettierignore @@ -22,3 +22,4 @@ package.json *.css *.scss *.sh +!packages/webpack/templates/*.js diff --git a/packages/webpack/package.json b/packages/webpack/package.json index 52652eb40..caafd21f4 100644 --- a/packages/webpack/package.json +++ b/packages/webpack/package.json @@ -1,6 +1,6 @@ { "name": "@nativescript/webpack", - "version": "4.0.1", + "version": "4.0.2", "main": "index", "description": "Webpack plugin for NativeScript", "homepage": "https://nativescript.org", diff --git a/packages/webpack/templates/webpack.angular.js b/packages/webpack/templates/webpack.angular.js index 1472428ae..513b97d88 100644 --- a/packages/webpack/templates/webpack.angular.js +++ b/packages/webpack/templates/webpack.angular.js @@ -4,450 +4,370 @@ const fs = require('fs'); const webpack = require('webpack'); const nsWebpack = require('@nativescript/webpack'); const nativescriptTarget = require('@nativescript/webpack/nativescript-target'); -const { - nsSupportHmrNg -} = require('@nativescript/webpack/transformers/ns-support-hmr-ng'); -const { nsTransformNativeClassesNg } = require("@nativescript/webpack/transformers/ns-transform-native-classes-ng"); -const { - parseWorkspaceConfig, hasConfigurations -} = require('@nativescript/webpack/helpers/angular-config-parser'); -const { - getMainModulePath -} = require('@nativescript/webpack/utils/ast-utils'); -const { getNoEmitOnErrorFromTSConfig, getCompilerOptionsFromTSConfig } = require("@nativescript/webpack/utils/tsconfig-utils"); +const { nsSupportHmrNg } = require('@nativescript/webpack/transformers/ns-support-hmr-ng'); +const { nsTransformNativeClassesNg } = require('@nativescript/webpack/transformers/ns-transform-native-classes-ng'); +const { parseWorkspaceConfig, hasConfigurations } = require('@nativescript/webpack/helpers/angular-config-parser'); +const { getMainModulePath } = require('@nativescript/webpack/utils/ast-utils'); +const { getNoEmitOnErrorFromTSConfig, getCompilerOptionsFromTSConfig } = require('@nativescript/webpack/utils/tsconfig-utils'); const { CleanWebpackPlugin } = require('clean-webpack-plugin'); const CopyWebpackPlugin = require('copy-webpack-plugin'); const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer'); -const { - NativeScriptWorkerPlugin -} = require('nativescript-worker-loader/NativeScriptWorkerPlugin'); +const { NativeScriptWorkerPlugin } = require('nativescript-worker-loader/NativeScriptWorkerPlugin'); const TerserPlugin = require('terser-webpack-plugin'); -const { - getAngularCompilerPlugin -} = require('@nativescript/webpack/plugins/NativeScriptAngularCompilerPlugin'); +const { getAngularCompilerPlugin } = require('@nativescript/webpack/plugins/NativeScriptAngularCompilerPlugin'); const hashSalt = Date.now().toString(); -module.exports = env => { - // Add your custom Activities, Services and other Android app components here. - const appComponents = [ - "@nativescript/core/ui/frame", "@nativescript/core/ui/frame/activity" - ]; +module.exports = (env) => { + // Add your custom Activities, Services and other Android app components here. + const appComponents = ['@nativescript/core/ui/frame', '@nativescript/core/ui/frame/activity']; - const platform = env && ((env.android && 'android') || (env.ios && 'ios')); - if (!platform) { - throw new Error('You need to provide a target platform!'); - } + const platform = env && ((env.android && 'android') || (env.ios && 'ios')); + if (!platform) { + throw new Error('You need to provide a target platform!'); + } - const AngularCompilerPlugin = getAngularCompilerPlugin(platform); - const projectRoot = __dirname; + const AngularCompilerPlugin = getAngularCompilerPlugin(platform); + const projectRoot = __dirname; - // Default destination inside platforms//... - const dist = resolve( - projectRoot, - nsWebpack.getAppPath(platform, projectRoot) - ); + // Default destination inside platforms//... + const dist = resolve(projectRoot, nsWebpack.getAppPath(platform, projectRoot)); - const { - // The 'appPath' and 'appResourcesPath' values are fetched from - // the nsconfig.json configuration file - // when bundling with `tns run android|ios --bundle`. - appPath = 'src', - appResourcesPath = 'App_Resources', + const { + // The 'appPath' and 'appResourcesPath' values are fetched from + // the nsconfig.json configuration file + // when bundling with `tns run android|ios --bundle`. + appPath = 'src', + appResourcesPath = 'App_Resources', - // You can provide the following flags when running 'tns run android|ios' - snapshot, // --env.snapshot, - production, // --env.production - configuration, // --env.configuration (consistent with angular cli usage) - projectName, // --env.projectName (drive configuration through angular projects) - uglify, // --env.uglify - report, // --env.report - sourceMap, // --env.sourceMap - hiddenSourceMap, // --env.hiddenSourceMap - hmr, // --env.hmr, - unitTesting, // --env.unitTesting - testing, // --env.testing - verbose, // --env.verbose - ci, // --env.ci - snapshotInDocker, // --env.snapshotInDocker - skipSnapshotTools, // --env.skipSnapshotTools - compileSnapshot // --env.compileSnapshot - } = env; + // You can provide the following flags when running 'tns run android|ios' + snapshot, // --env.snapshot, + production, // --env.production + configuration, // --env.configuration (consistent with angular cli usage) + projectName, // --env.projectName (drive configuration through angular projects) + uglify, // --env.uglify + report, // --env.report + sourceMap, // --env.sourceMap + hiddenSourceMap, // --env.hiddenSourceMap + hmr, // --env.hmr, + unitTesting, // --env.unitTesting + testing, // --env.testing + verbose, // --env.verbose + ci, // --env.ci + snapshotInDocker, // --env.snapshotInDocker + skipSnapshotTools, // --env.skipSnapshotTools + compileSnapshot, // --env.compileSnapshot + } = env; - const { fileReplacements, copyReplacements } = parseWorkspaceConfig(platform, configuration, projectName); + const { fileReplacements, copyReplacements } = parseWorkspaceConfig(platform, configuration, projectName); - const useLibs = compileSnapshot; - const isAnySourceMapEnabled = !!sourceMap || !!hiddenSourceMap; - const externals = nsWebpack.getConvertedExternals(env.externals); - const appFullPath = resolve(projectRoot, appPath); - const appResourcesFullPath = resolve(projectRoot, appResourcesPath); - let tsConfigName = 'tsconfig.json'; - let tsConfigPath = resolve(projectRoot, tsConfigName); - const tsConfigTnsName = 'tsconfig.tns.json'; - const tsConfigTnsPath = resolve(projectRoot, tsConfigTnsName); - if (fs.existsSync(tsConfigTnsPath)) { - // support shared angular app configurations - tsConfigName = tsConfigTnsName; - tsConfigPath = tsConfigTnsPath; - } - const tsConfigEnvName = 'tsconfig.env.json'; - const tsConfigEnvPath = resolve(projectRoot, tsConfigEnvName); - if (hasConfigurations(configuration) && fs.existsSync(tsConfigEnvPath)) { - // when configurations are used, switch to environments supported config - tsConfigName = tsConfigEnvName; - tsConfigPath = tsConfigEnvPath; - } - const entryModule = `${nsWebpack.getEntryModule(appFullPath, platform)}.ts`; - const entryPath = `.${sep}${entryModule}`; - const entries = { bundle: entryPath }; - const areCoreModulesExternal = - Array.isArray(env.externals) && - env.externals.some(e => e.indexOf('@nativescript') > -1); - if (platform === 'ios' && !areCoreModulesExternal && !testing) { - entries['tns_modules/@nativescript/core/inspector_modules'] = - 'inspector_modules'; - } + const useLibs = compileSnapshot; + const isAnySourceMapEnabled = !!sourceMap || !!hiddenSourceMap; + const externals = nsWebpack.getConvertedExternals(env.externals); + const appFullPath = resolve(projectRoot, appPath); + const appResourcesFullPath = resolve(projectRoot, appResourcesPath); + let tsConfigName = 'tsconfig.json'; + let tsConfigPath = resolve(projectRoot, tsConfigName); + const tsConfigTnsName = 'tsconfig.tns.json'; + const tsConfigTnsPath = resolve(projectRoot, tsConfigTnsName); + if (fs.existsSync(tsConfigTnsPath)) { + // support shared angular app configurations + tsConfigName = tsConfigTnsName; + tsConfigPath = tsConfigTnsPath; + } + const tsConfigEnvName = 'tsconfig.env.json'; + const tsConfigEnvPath = resolve(projectRoot, tsConfigEnvName); + if (hasConfigurations(configuration) && fs.existsSync(tsConfigEnvPath)) { + // when configurations are used, switch to environments supported config + tsConfigName = tsConfigEnvName; + tsConfigPath = tsConfigEnvPath; + } + const entryModule = `${nsWebpack.getEntryModule(appFullPath, platform)}.ts`; + const entryPath = `.${sep}${entryModule}`; + const entries = { bundle: entryPath }; + const areCoreModulesExternal = Array.isArray(env.externals) && env.externals.some((e) => e.indexOf('@nativescript') > -1); + if (platform === 'ios' && !areCoreModulesExternal && !testing) { + entries['tns_modules/@nativescript/core/inspector_modules'] = 'inspector_modules'; + } - const compilerOptions = getCompilerOptionsFromTSConfig(tsConfigPath); - nsWebpack.processTsPathsForScopedModules({ compilerOptions }); - nsWebpack.processTsPathsForScopedAngular({ compilerOptions }); + const compilerOptions = getCompilerOptionsFromTSConfig(tsConfigPath); + nsWebpack.processTsPathsForScopedModules({ compilerOptions }); + nsWebpack.processTsPathsForScopedAngular({ compilerOptions }); - const ngCompilerTransformers = [nsTransformNativeClassesNg]; - const additionalLazyModuleResources = []; + const ngCompilerTransformers = [nsTransformNativeClassesNg]; + const additionalLazyModuleResources = []; - const copyIgnore = { ignore: [`${relative(appPath, appResourcesFullPath)}/**`] }; - const copyTargets = [ - { from: { glob: 'assets/**', dot: false } }, - { from: { glob: 'fonts/**', dot: false } }, - ...copyReplacements, - ]; + const copyIgnore = { ignore: [`${relative(appPath, appResourcesFullPath)}/**`] }; + const copyTargets = [{ from: { glob: 'assets/**', dot: false } }, { from: { glob: 'fonts/**', dot: false } }, ...copyReplacements]; - if (!production) { - // for development purposes only - // for example, include mock json folder - // copyTargets.push({ from: 'tools/mockdata', to: 'assets/mockdata' }); + if (!production) { + // for development purposes only + // for example, include mock json folder + // copyTargets.push({ from: 'tools/mockdata', to: 'assets/mockdata' }); - if (hmr) { - ngCompilerTransformers.push(nsSupportHmrNg); - } - } + if (hmr) { + ngCompilerTransformers.push(nsSupportHmrNg); + } + } - // when "@angular/core" is external, it's not included in the bundles. In this way, it will be used - // directly from node_modules and the Angular modules loader won't be able to resolve the lazy routes - // fixes https://github.com/NativeScript/nativescript-cli/issues/4024 - if (env.externals && env.externals.indexOf('@angular/core') > -1) { - const appModuleRelativePath = getMainModulePath( - resolve(appFullPath, entryModule), - tsConfigName - ); - if (appModuleRelativePath) { - const appModuleFolderPath = dirname( - resolve(appFullPath, appModuleRelativePath) - ); - // include the new lazy loader path in the allowed ones - additionalLazyModuleResources.push(appModuleFolderPath); - } - } + // when "@angular/core" is external, it's not included in the bundles. In this way, it will be used + // directly from node_modules and the Angular modules loader won't be able to resolve the lazy routes + // fixes https://github.com/NativeScript/nativescript-cli/issues/4024 + if (env.externals && env.externals.indexOf('@angular/core') > -1) { + const appModuleRelativePath = getMainModulePath(resolve(appFullPath, entryModule), tsConfigName); + if (appModuleRelativePath) { + const appModuleFolderPath = dirname(resolve(appFullPath, appModuleRelativePath)); + // include the new lazy loader path in the allowed ones + additionalLazyModuleResources.push(appModuleFolderPath); + } + } - const ngCompilerPlugin = new AngularCompilerPlugin({ - hostReplacementPaths: nsWebpack.getResolver([platform, 'tns']), - platformTransformers: ngCompilerTransformers.map(t => - t(() => ngCompilerPlugin, resolve(appFullPath, entryModule), projectRoot) - ), - mainPath: join(appFullPath, entryModule), - tsConfigPath, - skipCodeGeneration: false, - sourceMap: !!isAnySourceMapEnabled, - additionalLazyModuleResources: additionalLazyModuleResources, - compilerOptions: { paths: compilerOptions.paths } - }); + const ngCompilerPlugin = new AngularCompilerPlugin({ + hostReplacementPaths: nsWebpack.getResolver([platform, 'tns']), + platformTransformers: ngCompilerTransformers.map((t) => t(() => ngCompilerPlugin, resolve(appFullPath, entryModule), projectRoot)), + mainPath: join(appFullPath, entryModule), + tsConfigPath, + skipCodeGeneration: false, + sourceMap: !!isAnySourceMapEnabled, + additionalLazyModuleResources: additionalLazyModuleResources, + compilerOptions: { paths: compilerOptions.paths }, + }); - let sourceMapFilename = nsWebpack.getSourceMapFilename( - hiddenSourceMap, - __dirname, - dist - ); + 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 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 noEmitOnErrorFromTSConfig = getNoEmitOnErrorFromTSConfig(tsConfigName); + const noEmitOnErrorFromTSConfig = getNoEmitOnErrorFromTSConfig(tsConfigName); - nsWebpack.processAppComponents(appComponents, platform); - const config = { - mode: production ? 'production' : 'development', - context: appFullPath, - externals, - watchOptions: { - ignored: [ - appResourcesFullPath, - // Don't watch hidden files - '**/.*' - ] - }, - target: nativescriptTarget, - entry: entries, - output: { - pathinfo: false, - path: dist, - sourceMapFilename, - libraryTarget: 'commonjs2', - filename: '[name].js', - globalObject: 'global', - hashSalt - }, - resolve: { - extensions: ['.ts', '.js', '.scss', '.css'], - // Resolve {N} system modules from @nativescript/core - modules: [ - resolve(__dirname, 'node_modules/@nativescript/core'), - resolve(__dirname, 'node_modules'), - 'node_modules/@nativescript/core', - 'node_modules' - ], - alias: { - '~/package.json': resolve(projectRoot, 'package.json'), - '~': appFullPath, - "tns-core-modules": "@nativescript/core", - "nativescript-angular": "@nativescript/angular", - ...fileReplacements - }, - symlinks: true - }, - resolveLoader: { - symlinks: false - }, - node: { - // Disable node shims that conflict with NativeScript - http: false, - timers: false, - setImmediate: false, - fs: 'empty', - __dirname: false - }, - devtool: hiddenSourceMap - ? 'hidden-source-map' - : sourceMap - ? 'inline-source-map' - : 'none', - optimization: { - runtimeChunk: 'single', - noEmitOnErrors: noEmitOnErrorFromTSConfig, - splitChunks: { - cacheGroups: { - vendor: { - name: 'vendor', - chunks: 'all', - test: (module, chunks) => { - const moduleName = module.nameForCondition - ? module.nameForCondition() - : ''; - return ( - /[\\/]node_modules[\\/]/.test(moduleName) || - appComponents.some(comp => comp === moduleName) - ); - }, - enforce: true - } - } - }, - minimize: !!uglify, - minimizer: [ - new TerserPlugin({ - parallel: true, - cache: !ci, - sourceMap: isAnySourceMapEnabled, - terserOptions: { - output: { - comments: false, - semicolons: !isAnySourceMapEnabled - }, - compress: { - // The Android SBG has problems parsing the output - // when these options are enabled - collapse_vars: platform !== 'android', - sequences: platform !== 'android', - // custom - drop_console: true, - drop_debugger: true, - ecma: 6, - keep_infinity: platform === 'android', // for Chrome/V8 - reduce_funcs: platform !== 'android', // for Chrome/V8 - global_defs: { - __UGLIFIED__: true - } - }, - // custom - ecma: 6, - safari10: platform !== 'android' - } - }) - ] - }, - module: { - rules: [ - { - include: join(appFullPath, entryPath), - use: [ - // Require all Android app components - platform === 'android' && { - loader: '@nativescript/webpack/helpers/android-app-components-loader', - options: { modules: appComponents } - }, + nsWebpack.processAppComponents(appComponents, platform); + const config = { + mode: production ? 'production' : 'development', + context: appFullPath, + externals, + watchOptions: { + ignored: [ + appResourcesFullPath, + // Don't watch hidden files + '**/.*', + ], + }, + target: nativescriptTarget, + entry: entries, + output: { + pathinfo: false, + path: dist, + sourceMapFilename, + libraryTarget: 'commonjs2', + filename: '[name].js', + globalObject: 'global', + hashSalt, + }, + resolve: { + extensions: ['.ts', '.js', '.scss', '.css'], + // Resolve {N} system modules from @nativescript/core + modules: [resolve(__dirname, 'node_modules/@nativescript/core'), resolve(__dirname, 'node_modules'), 'node_modules/@nativescript/core', 'node_modules'], + alias: { + '~/package.json': resolve(projectRoot, 'package.json'), + '~': appFullPath, + 'tns-core-modules': '@nativescript/core', + 'nativescript-angular': '@nativescript/angular', + ...fileReplacements, + }, + symlinks: true, + }, + resolveLoader: { + symlinks: false, + }, + node: { + // Disable node shims that conflict with NativeScript + http: false, + timers: false, + setImmediate: false, + fs: 'empty', + __dirname: false, + }, + devtool: hiddenSourceMap ? 'hidden-source-map' : sourceMap ? 'inline-source-map' : 'none', + optimization: { + runtimeChunk: 'single', + noEmitOnErrors: noEmitOnErrorFromTSConfig, + splitChunks: { + cacheGroups: { + vendor: { + name: 'vendor', + chunks: 'all', + test: (module, chunks) => { + const moduleName = module.nameForCondition ? module.nameForCondition() : ''; + return /[\\/]node_modules[\\/]/.test(moduleName) || appComponents.some((comp) => comp === moduleName); + }, + enforce: true, + }, + }, + }, + minimize: !!uglify, + minimizer: [ + new TerserPlugin({ + parallel: true, + cache: !ci, + sourceMap: isAnySourceMapEnabled, + terserOptions: { + output: { + comments: false, + semicolons: !isAnySourceMapEnabled, + }, + compress: { + // The Android SBG has problems parsing the output + // when these options are enabled + collapse_vars: platform !== 'android', + sequences: platform !== 'android', + // For v8 Compatibility + keep_infinity: true, // for V8 + reduce_funcs: false, // for V8 + // custom + drop_console: production, + drop_debugger: true, + ecma: 6, + global_defs: { + __UGLIFIED__: true, + }, + }, + // Required for Element Level CSS, Observable Events, & Android Frame + keep_classnames: true, + // custom + ecma: 6, + safari10: platform !== 'android', + }, + }), + ], + }, + module: { + rules: [ + { + include: join(appFullPath, entryPath), + use: [ + // Require all Android app components + platform === 'android' && { + loader: '@nativescript/webpack/helpers/android-app-components-loader', + options: { modules: appComponents }, + }, - { - loader: '@nativescript/webpack/bundle-config-loader', - options: { - angular: true, - loadCss: !snapshot, // load the application css if in debug mode - unitTesting, - appFullPath, - projectRoot, - ignoredFiles: nsWebpack.getUserDefinedEntries(entries, platform) - } - } - ].filter(loader => !!loader) - }, + { + loader: '@nativescript/webpack/bundle-config-loader', + options: { + angular: true, + loadCss: !snapshot, // load the application css if in debug mode + unitTesting, + appFullPath, + projectRoot, + ignoredFiles: nsWebpack.getUserDefinedEntries(entries, platform), + }, + }, + ].filter((loader) => !!loader), + }, - { test: /\.html$|\.xml$/, use: 'raw-loader' }, + { test: /\.html$|\.xml$/, use: 'raw-loader' }, - { - test: /[\/|\\]app\.css$/, - use: [ - '@nativescript/webpack/helpers/style-hot-loader', - { - loader: "@nativescript/webpack/helpers/css2json-loader", - options: { useForImports: true } - }, - ], - }, - { - test: /[\/|\\]app\.scss$/, - use: [ - '@nativescript/webpack/helpers/style-hot-loader', - { - loader: "@nativescript/webpack/helpers/css2json-loader", - options: { useForImports: true } - }, - 'sass-loader', - ], - }, + { + test: /[\/|\\]app\.css$/, + use: [ + '@nativescript/webpack/helpers/style-hot-loader', + { + loader: '@nativescript/webpack/helpers/css2json-loader', + options: { useForImports: true }, + }, + ], + }, + { + test: /[\/|\\]app\.scss$/, + use: [ + '@nativescript/webpack/helpers/style-hot-loader', + { + loader: '@nativescript/webpack/helpers/css2json-loader', + options: { useForImports: true }, + }, + 'sass-loader', + ], + }, - // Angular components reference css files and their imports using raw-loader - { test: /\.css$/, exclude: /[\/|\\]app\.css$/, use: 'raw-loader' }, - { - test: /\.scss$/, - exclude: /[\/|\\]app\.scss$/, - use: ['raw-loader', 'resolve-url-loader', 'sass-loader'] - }, + // Angular components reference css files and their imports using raw-loader + { test: /\.css$/, exclude: /[\/|\\]app\.css$/, use: 'raw-loader' }, + { + test: /\.scss$/, + exclude: /[\/|\\]app\.scss$/, + use: ['raw-loader', 'resolve-url-loader', 'sass-loader'], + }, - { - test: /(?:\.ngfactory\.js|\.ngstyle\.js|\.ts)$/, - use: [ - '@nativescript/webpack/helpers/moduleid-compat-loader', - '@nativescript/webpack/helpers/lazy-ngmodule-hot-loader', - '@ngtools/webpack' - ] - }, + { + test: /(?:\.ngfactory\.js|\.ngstyle\.js|\.ts)$/, + use: ['@nativescript/webpack/helpers/moduleid-compat-loader', '@nativescript/webpack/helpers/lazy-ngmodule-hot-loader', '@ngtools/webpack'], + }, - // Mark files inside `@angular/core` as using SystemJS style dynamic imports. - // Removing this will cause deprecation warnings to appear. - { - test: /[\/\\]@angular[\/\\]core[\/\\].+\.js$/, - parser: { system: true } - } - ] - }, - plugins: [ - // Define useful constants like TNS_WEBPACK - new webpack.DefinePlugin({ - 'global.TNS_WEBPACK': 'true', - 'global.isAndroid': platform === 'android', - 'global.isIOS': platform === 'ios', - process: 'global.process' - }), - // Remove all files from the out dir. - new CleanWebpackPlugin({ - cleanOnceBeforeBuildPatterns: itemsToClean, - verbose: !!verbose - }), - // Copy assets - new CopyWebpackPlugin([ - ...copyTargets, - { from: { glob: '**/*.jpg', dot: false } }, - { from: { glob: '**/*.png', dot: false } }, - ], copyIgnore), - new nsWebpack.GenerateNativeScriptEntryPointsPlugin('bundle'), - // For instructions on how to set up workers with webpack - // check out https://github.com/nativescript/worker-loader - new NativeScriptWorkerPlugin(), - ngCompilerPlugin, - // Does IPC communication with the {N} CLI to notify events when running in watch mode. - new nsWebpack.WatchStateLoggerPlugin() - ] - }; + // Mark files inside `@angular/core` as using SystemJS style dynamic imports. + // Removing this will cause deprecation warnings to appear. + { + test: /[\/\\]@angular[\/\\]core[\/\\].+\.js$/, + parser: { system: true }, + }, + ], + }, + plugins: [ + // Define useful constants like TNS_WEBPACK + new webpack.DefinePlugin({ + 'global.TNS_WEBPACK': 'true', + 'global.isAndroid': platform === 'android', + 'global.isIOS': platform === 'ios', + process: 'global.process', + }), + // Remove all files from the out dir. + new CleanWebpackPlugin({ + cleanOnceBeforeBuildPatterns: itemsToClean, + verbose: !!verbose, + }), + // Copy assets + new CopyWebpackPlugin([...copyTargets, { from: { glob: '**/*.jpg', dot: false } }, { from: { glob: '**/*.png', dot: false } }], copyIgnore), + new nsWebpack.GenerateNativeScriptEntryPointsPlugin('bundle'), + // For instructions on how to set up workers with webpack + // check out https://github.com/nativescript/worker-loader + new NativeScriptWorkerPlugin(), + ngCompilerPlugin, + // Does IPC communication with the {N} CLI to notify events when running in watch mode. + new nsWebpack.WatchStateLoggerPlugin(), + ], + }; - if (report) { - // Generate report files for bundles content - config.plugins.push( - new BundleAnalyzerPlugin({ - analyzerMode: 'static', - openAnalyzer: false, - generateStatsFile: true, - reportFilename: resolve(projectRoot, 'report', `report.html`), - statsFilename: resolve(projectRoot, 'report', `stats.json`) - }) - ); - } + if (report) { + // Generate report files for bundles content + config.plugins.push( + new BundleAnalyzerPlugin({ + analyzerMode: 'static', + openAnalyzer: false, + generateStatsFile: true, + reportFilename: resolve(projectRoot, 'report', `report.html`), + statsFilename: resolve(projectRoot, 'report', `stats.json`), + }) + ); + } - if (snapshot) { - config.plugins.push( - new nsWebpack.NativeScriptSnapshotPlugin({ - chunk: 'vendor', - angular: true, - requireModules: [ - 'reflect-metadata', - '@angular/platform-browser', - '@angular/core', - '@angular/common', - '@angular/router', - '@nativescript/angular' - ], - projectRoot, - webpackConfig: config, - snapshotInDocker, - skipSnapshotTools, - useLibs - }) - ); - } + if (snapshot) { + config.plugins.push( + new nsWebpack.NativeScriptSnapshotPlugin({ + chunk: 'vendor', + angular: true, + requireModules: ['reflect-metadata', '@angular/platform-browser', '@angular/core', '@angular/common', '@angular/router', '@nativescript/angular'], + projectRoot, + webpackConfig: config, + snapshotInDocker, + skipSnapshotTools, + useLibs, + }) + ); + } - if (!production && hmr) { - config.plugins.push(new webpack.HotModuleReplacementPlugin()); - } + if (!production && hmr) { + config.plugins.push(new webpack.HotModuleReplacementPlugin()); + } - return config; -}; \ No newline at end of file + return config; +}; diff --git a/packages/webpack/templates/webpack.javascript.js b/packages/webpack/templates/webpack.javascript.js index 69c197a69..0fe5b4e48 100644 --- a/packages/webpack/templates/webpack.javascript.js +++ b/packages/webpack/templates/webpack.javascript.js @@ -1,297 +1,293 @@ -const { join, relative, resolve, sep } = require("path"); +const { join, relative, resolve, sep } = require('path'); const fs = require('fs'); -const webpack = require("webpack"); -const nsWebpack = require("@nativescript/webpack"); -const nativescriptTarget = require("@nativescript/webpack/nativescript-target"); -const { CleanWebpackPlugin } = require("clean-webpack-plugin"); -const CopyWebpackPlugin = require("copy-webpack-plugin"); -const { BundleAnalyzerPlugin } = require("webpack-bundle-analyzer"); -const { NativeScriptWorkerPlugin } = require("nativescript-worker-loader/NativeScriptWorkerPlugin"); -const TerserPlugin = require("terser-webpack-plugin"); +const webpack = require('webpack'); +const nsWebpack = require('@nativescript/webpack'); +const nativescriptTarget = require('@nativescript/webpack/nativescript-target'); +const { CleanWebpackPlugin } = require('clean-webpack-plugin'); +const CopyWebpackPlugin = require('copy-webpack-plugin'); +const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer'); +const { NativeScriptWorkerPlugin } = require('nativescript-worker-loader/NativeScriptWorkerPlugin'); +const TerserPlugin = require('terser-webpack-plugin'); const hashSalt = Date.now().toString(); -module.exports = env => { - // Add your custom Activities, Services and other android app components here. - const appComponents = env.appComponents || []; - appComponents.push(...[ - "@nativescript/core/ui/frame", - "@nativescript/core/ui/frame/activity", - ]); +module.exports = (env) => { + // Add your custom Activities, Services and other android app components here. + const appComponents = env.appComponents || []; + appComponents.push(...['@nativescript/core/ui/frame', '@nativescript/core/ui/frame/activity']); - const platform = env && (env.android && "android" || env.ios && "ios" || env.platform); - if (!platform) { - throw new Error("You need to provide a target platform!"); - } + const platform = env && ((env.android && 'android') || (env.ios && 'ios') || env.platform); + if (!platform) { + throw new Error('You need to provide a target platform!'); + } - const platforms = ["ios", "android"]; - const projectRoot = __dirname; + const platforms = ['ios', 'android']; + const projectRoot = __dirname; - if (env.platform) { - platforms.push(env.platform); - } + if (env.platform) { + platforms.push(env.platform); + } - // Default destination inside platforms//... - const dist = resolve(projectRoot, nsWebpack.getAppPath(platform, projectRoot)); + // Default destination inside platforms//... + const dist = resolve(projectRoot, nsWebpack.getAppPath(platform, projectRoot)); - const { - // The 'appPath' and 'appResourcesPath' values are fetched from - // the nsconfig.json configuration file. - appPath = "src", - appResourcesPath = "App_Resources", + const { + // The 'appPath' and 'appResourcesPath' values are fetched from + // the nsconfig.json configuration file. + appPath = 'src', + appResourcesPath = 'App_Resources', - // 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, - testing, // --env.testing - verbose, // --env.verbose - snapshotInDocker, // --env.snapshotInDocker - skipSnapshotTools, // --env.skipSnapshotTools - compileSnapshot // --env.compileSnapshot - } = 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, + testing, // --env.testing + verbose, // --env.verbose + snapshotInDocker, // --env.snapshotInDocker + skipSnapshotTools, // --env.skipSnapshotTools + ci, // --env.ci + compileSnapshot, // --env.compileSnapshot + } = env; - const useLibs = compileSnapshot; - const isAnySourceMapEnabled = !!sourceMap || !!hiddenSourceMap; - const externals = nsWebpack.getConvertedExternals(env.externals); - let appFullPath = resolve(projectRoot, appPath); - if (!fs.existsSync(appFullPath)) { - // some apps use 'app' directory - appFullPath = resolve(projectRoot, 'app'); - } - const hasRootLevelScopedModules = nsWebpack.hasRootLevelScopedModules({ projectDir: projectRoot }); - let coreModulesPackageName = "tns-core-modules"; - const alias = env.alias || {}; - alias['~/package.json'] = resolve(projectRoot, 'package.json'); - alias['~'] = appFullPath; + const useLibs = compileSnapshot; + const isAnySourceMapEnabled = !!sourceMap || !!hiddenSourceMap; + const externals = nsWebpack.getConvertedExternals(env.externals); - if (hasRootLevelScopedModules) { - coreModulesPackageName = "@nativescript/core"; - alias["tns-core-modules"] = coreModulesPackageName; - } - const appResourcesFullPath = resolve(projectRoot, appResourcesPath); + let appFullPath = resolve(projectRoot, appPath); + if (!fs.existsSync(appFullPath)) { + // some apps use 'app' directory + appFullPath = resolve(projectRoot, 'app'); + } + const hasRootLevelScopedModules = nsWebpack.hasRootLevelScopedModules({ projectDir: projectRoot }); + let coreModulesPackageName = 'tns-core-modules'; + const alias = env.alias || {}; + alias['~/package.json'] = resolve(projectRoot, 'package.json'); + alias['~'] = appFullPath; - const copyIgnore = { ignore: [`${relative(appPath, appResourcesFullPath)}/**`] }; + if (hasRootLevelScopedModules) { + coreModulesPackageName = '@nativescript/core'; + alias['tns-core-modules'] = coreModulesPackageName; + } + const appResourcesFullPath = resolve(projectRoot, appResourcesPath); - const entryModule = nsWebpack.getEntryModule(appFullPath, platform); - const entryPath = `.${sep}${entryModule}.js`; - const entries = env.entries || {}; - entries.bundle = entryPath; + const copyIgnore = { ignore: [`${relative(appPath, appResourcesFullPath)}/**`] }; - const areCoreModulesExternal = Array.isArray(env.externals) && env.externals.some(e => e.indexOf("@nativescript") > -1); - if (platform === "ios" && !areCoreModulesExternal && !testing) { - entries["tns_modules/@nativescript/core/inspector_modules"] = "inspector_modules"; - }; + const entryModule = nsWebpack.getEntryModule(appFullPath, platform); + const entryPath = `.${sep}${entryModule}.js`; + const entries = env.entries || {}; + entries.bundle = entryPath; - let sourceMapFilename = nsWebpack.getSourceMapFilename(hiddenSourceMap, __dirname, dist); + const areCoreModulesExternal = Array.isArray(env.externals) && env.externals.some((e) => e.indexOf('@nativescript') > -1); + if (platform === 'ios' && !areCoreModulesExternal && !testing) { + entries['tns_modules/@nativescript/core/inspector_modules'] = 'inspector_modules'; + } - 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")}`); - } + 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')}`); + } - nsWebpack.processAppComponents(appComponents, platform); - const config = { - mode: production ? "production" : "development", - context: appFullPath, - externals, - watchOptions: { - ignored: [ - appResourcesFullPath, - // Don't watch hidden files - "**/.*", - ] - }, - target: nativescriptTarget, - entry: entries, - output: { - pathinfo: false, - path: dist, - sourceMapFilename, - libraryTarget: "commonjs2", - filename: "[name].js", - globalObject: "global", - hashSalt - }, - resolve: { - extensions: [".js", ".scss", ".css"], - // Resolve {N} system modules from @nativescript/core - modules: [ - resolve(__dirname, `node_modules/${coreModulesPackageName}`), - resolve(__dirname, "node_modules"), - `node_modules/${coreModulesPackageName}`, - "node_modules", - ], - alias, - // resolve symlinks to symlinked modules - symlinks: true - }, - resolveLoader: { - // don't resolve symlinks to symlinked loaders - symlinks: false - }, - node: { - // Disable node shims that conflict with NativeScript - "http": false, - "timers": false, - "setImmediate": false, - "fs": "empty", - "__dirname": false, - }, - devtool: hiddenSourceMap ? "hidden-source-map" : (sourceMap ? "inline-source-map" : "none"), - optimization: { - runtimeChunk: "single", - noEmitOnErrors: true, - splitChunks: { - cacheGroups: { - vendor: { - name: "vendor", - chunks: "all", - test: (module, chunks) => { - const moduleName = module.nameForCondition ? module.nameForCondition() : ''; - return /[\\/]node_modules[\\/]/.test(moduleName) || - appComponents.some(comp => comp === moduleName); + nsWebpack.processAppComponents(appComponents, platform); + const config = { + mode: production ? 'production' : 'development', + context: appFullPath, + externals, + watchOptions: { + ignored: [ + appResourcesFullPath, + // Don't watch hidden files + '**/.*', + ], + }, + target: nativescriptTarget, + entry: entries, + output: { + pathinfo: false, + path: dist, + sourceMapFilename, + libraryTarget: 'commonjs2', + filename: '[name].js', + globalObject: 'global', + hashSalt, + }, + resolve: { + extensions: ['.js', '.scss', '.css'], + // Resolve {N} system modules from @nativescript/core + modules: [resolve(__dirname, `node_modules/${coreModulesPackageName}`), resolve(__dirname, 'node_modules'), `node_modules/${coreModulesPackageName}`, 'node_modules'], + alias, + // resolve symlinks to symlinked modules + symlinks: true, + }, + resolveLoader: { + // don't resolve symlinks to symlinked loaders + symlinks: false, + }, + node: { + // Disable node shims that conflict with NativeScript + http: false, + timers: false, + setImmediate: false, + fs: 'empty', + __dirname: false, + }, + devtool: hiddenSourceMap ? 'hidden-source-map' : sourceMap ? 'inline-source-map' : 'none', + optimization: { + runtimeChunk: 'single', + noEmitOnErrors: true, + splitChunks: { + cacheGroups: { + vendor: { + name: 'vendor', + chunks: 'all', + test: (module, chunks) => { + const moduleName = module.nameForCondition ? module.nameForCondition() : ''; + return /[\\/]node_modules[\\/]/.test(moduleName) || appComponents.some((comp) => comp === moduleName); + }, + enforce: true, + }, + }, + }, + minimize: !!uglify, + minimizer: [ + new TerserPlugin({ + parallel: true, + cache: !ci, + sourceMap: isAnySourceMapEnabled, + terserOptions: { + output: { + comments: false, + semicolons: !isAnySourceMapEnabled, + }, + compress: { + // The Android SBG has problems parsing the output + // when these options are enabled + collapse_vars: platform !== 'android', + sequences: platform !== 'android', + // For v8 Compatibility + keep_infinity: true, // for V8 + reduce_funcs: false, // for V8 + // custom + drop_console: production, + drop_debugger: true, + global_defs: { + __UGLIFIED__: true, + }, + }, + // Required for Element Level CSS, Observable Events, & Android Frame + keep_classnames: true, + }, + }), + ], + }, + module: { + rules: [ + { + include: join(appFullPath, entryPath), + use: [ + // Require all Android app components + platform === 'android' && { + loader: '@nativescript/webpack/helpers/android-app-components-loader', + options: { modules: appComponents }, + }, - }, - enforce: true, - }, - } - }, - minimize: !!uglify, - minimizer: [ - new TerserPlugin({ - parallel: true, - cache: true, - sourceMap: isAnySourceMapEnabled, - terserOptions: { - output: { - comments: false, - semicolons: !isAnySourceMapEnabled - }, - compress: { - // The Android SBG has problems parsing the output - // when these options are enabled - 'collapse_vars': platform !== "android", - sequences: platform !== "android", - } - } - }) - ], - }, - module: { - rules: [ - { - include: join(appFullPath, entryPath), - use: [ - // Require all Android app components - platform === "android" && { - loader: "@nativescript/webpack/helpers/android-app-components-loader", - options: { modules: appComponents } - }, + { + loader: '@nativescript/webpack/bundle-config-loader', + options: { + loadCss: !snapshot, // load the application css if in debug mode + unitTesting, + appFullPath, + projectRoot, + ignoredFiles: nsWebpack.getUserDefinedEntries(entries, platform), + }, + }, + ].filter((loader) => !!loader), + }, - { - loader: "@nativescript/webpack/bundle-config-loader", - options: { - loadCss: !snapshot, // load the application css if in debug mode - unitTesting, - appFullPath, - projectRoot, - ignoredFiles: nsWebpack.getUserDefinedEntries(entries, platform) - } - }, - ].filter(loader => !!loader) - }, + { + test: /\.(js|css|scss|html|xml)$/, + use: '@nativescript/webpack/hmr/hot-loader', + }, - { - test: /\.(js|css|scss|html|xml)$/, - use: "@nativescript/webpack/hmr/hot-loader" - }, + { test: /\.(html|xml)$/, use: '@nativescript/webpack/helpers/xml-namespace-loader' }, - { test: /\.(html|xml)$/, use: "@nativescript/webpack/helpers/xml-namespace-loader" }, + { + test: /\.css$/, + use: '@nativescript/webpack/helpers/css2json-loader', + }, - { - test: /\.css$/, - use: "@nativescript/webpack/helpers/css2json-loader" - }, + { + test: /\.scss$/, + use: ['@nativescript/webpack/helpers/css2json-loader', 'sass-loader'], + }, + ], + }, + plugins: [ + // Define useful constants like TNS_WEBPACK + new webpack.DefinePlugin({ + 'global.TNS_WEBPACK': 'true', + 'global.isAndroid': platform === 'android', + 'global.isIOS': platform === 'ios', + process: 'global.process', + }), + // Remove all files from the out dir. + new CleanWebpackPlugin({ + cleanOnceBeforeBuildPatterns: itemsToClean, + verbose: !!verbose, + }), + // Copy assets + new CopyWebpackPlugin([{ from: { glob: 'assets/**', dot: false } }, { from: { glob: 'fonts/**', dot: false } }, { from: { glob: '**/*.jpg', dot: false } }, { from: { glob: '**/*.png', dot: false } }], copyIgnore), + new nsWebpack.GenerateNativeScriptEntryPointsPlugin('bundle'), - { - test: /\.scss$/, - use: [ - "@nativescript/webpack/helpers/css2json-loader", - "sass-loader" - ] - }, - ] - }, - plugins: [ - // Define useful constants like TNS_WEBPACK - new webpack.DefinePlugin({ - "global.TNS_WEBPACK": "true", - "global.isAndroid": platform === 'android', - "global.isIOS": platform === 'ios', - "process": "global.process", - }), - // Remove all files from the out dir. - new CleanWebpackPlugin({ - cleanOnceBeforeBuildPatterns: itemsToClean, - verbose: !!verbose - }), - // Copy assets - new CopyWebpackPlugin([ - { from: { glob: 'assets/**', dot: false } }, - { from: { glob: 'fonts/**', dot: false } }, - { from: { glob: '**/*.jpg', dot: false } }, - { from: { glob: '**/*.png', dot: false } }, - ], copyIgnore), - new nsWebpack.GenerateNativeScriptEntryPointsPlugin("bundle"), + // For instructions on how to set up workers with webpack + // check out https://github.com/nativescript/worker-loader + new NativeScriptWorkerPlugin(), + new nsWebpack.PlatformFSPlugin({ + platform, + platforms, + }), + // Does IPC communication with the {N} CLI to notify events when running in watch mode. + new nsWebpack.WatchStateLoggerPlugin(), + ], + }; - // For instructions on how to set up workers with webpack - // check out https://github.com/nativescript/worker-loader - new NativeScriptWorkerPlugin(), - new nsWebpack.PlatformFSPlugin({ - platform, - platforms, - }), - // Does IPC communication with the {N} CLI to notify events when running in watch mode. - new nsWebpack.WatchStateLoggerPlugin() - ], - }; + if (report) { + // Generate report files for bundles content + config.plugins.push( + new BundleAnalyzerPlugin({ + analyzerMode: 'static', + openAnalyzer: false, + generateStatsFile: true, + reportFilename: resolve(projectRoot, 'report', `report.html`), + statsFilename: resolve(projectRoot, 'report', `stats.json`), + }) + ); + } - if (report) { - // Generate report files for bundles content - config.plugins.push(new BundleAnalyzerPlugin({ - analyzerMode: "static", - openAnalyzer: false, - generateStatsFile: true, - reportFilename: resolve(projectRoot, "report", `report.html`), - statsFilename: resolve(projectRoot, "report", `stats.json`), - })); - } + if (snapshot) { + config.plugins.push( + new nsWebpack.NativeScriptSnapshotPlugin({ + chunk: 'vendor', + requireModules: ['@nativescript/core/bundle-entry-points'], + projectRoot, + webpackConfig: config, + snapshotInDocker, + skipSnapshotTools, + useLibs, + }) + ); + } - if (snapshot) { - config.plugins.push(new nsWebpack.NativeScriptSnapshotPlugin({ - chunk: "vendor", - requireModules: [ - "@nativescript/core/bundle-entry-points", - ], - projectRoot, - webpackConfig: config, - snapshotInDocker, - skipSnapshotTools, - useLibs - })); - } + if (hmr) { + config.plugins.push(new webpack.HotModuleReplacementPlugin()); + } - if (hmr) { - config.plugins.push(new webpack.HotModuleReplacementPlugin()); - } - - return config; + return config; }; diff --git a/packages/webpack/templates/webpack.react.js b/packages/webpack/templates/webpack.react.js index d9c3f9062..ebd0f4d52 100644 --- a/packages/webpack/templates/webpack.react.js +++ b/packages/webpack/templates/webpack.react.js @@ -2,87 +2,86 @@ * @see https://github.com/NativeScript/NativeScript/tree/feat/ns7-finishing-touches/packages/webpack/templates * @see https://github.com/NativeScript/NativeScript/pull/8801/files */ -const webpackConfig = require("./webpack.typescript"); -const webpack = require("webpack"); +const webpackConfig = require('./webpack.typescript'); +const webpack = require('webpack'); const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin'); module.exports = (env) => { - env = env || {}; - const hmr = env.hmr; - const production = env.production; - const isAnySourceMapEnabled = !!env.sourceMap || !!env.hiddenSourceMap; + env = env || {}; + const hmr = env.hmr; + const production = env.production; + const isAnySourceMapEnabled = !!env.sourceMap || !!env.hiddenSourceMap; - const baseConfig = webpackConfig(env); + const baseConfig = webpackConfig(env); - /** Find the rule for transpiling ts files ("ts-loader"), and modify it to test for .tsx files too. */ - const tsxRule = baseConfig.module.rules.find(rule => rule.use && rule.use.loader === "ts-loader"); - tsxRule.test = /\.(ts|tsx)$/; - tsxRule.use = [ - /** - * Add React Refresh HMR support. - * @see https://github.com/pmmmwh/react-refresh-webpack-plugin/blob/55028c6355b31e697e21bf3e9a48613a7b94bee7/examples/typescript-without-babel/webpack.config.js#L18-L21 - */ - hmr && !production && { - loader: "babel-loader", - options: { - sourceMaps: isAnySourceMapEnabled ? "inline" : false, - babelrc: false, - plugins: ['react-refresh/babel'] - } - }, - tsxRule.use, - ].filter(Boolean); + /** Find the rule for transpiling ts files ("ts-loader"), and modify it to test for .tsx files too. */ + const tsxRule = baseConfig.module.rules.find((rule) => rule.use && rule.use.loader === 'ts-loader'); + tsxRule.test = /\.(ts|tsx)$/; + tsxRule.use = [ + /** + * Add React Refresh HMR support. + * @see https://github.com/pmmmwh/react-refresh-webpack-plugin/blob/55028c6355b31e697e21bf3e9a48613a7b94bee7/examples/typescript-without-babel/webpack.config.js#L18-L21 + */ + hmr && + !production && { + loader: 'babel-loader', + options: { + sourceMaps: isAnySourceMapEnabled ? 'inline' : false, + babelrc: false, + plugins: ['react-refresh/babel'], + }, + }, + tsxRule.use, + ].filter(Boolean); - /** - * Modify "nativescript-dev-webpack/hmr/hot-loader" to test for .tsx files - * (and also js files, which it should have been doing to begin with!) - */ - const nativeScriptDevWebpackHotLoader = baseConfig.module.rules.find(rule => - rule.use === "@nativescript/webpack/hmr/hot-loader" - ); - nativeScriptDevWebpackHotLoader.test = /\.(ts|tsx|js|css|scss|html|xml)$/; + /** + * Modify "nativescript-dev-webpack/hmr/hot-loader" to test for .tsx files + * (and also js files, which it should have been doing to begin with!) + */ + const nativeScriptDevWebpackHotLoader = baseConfig.module.rules.find((rule) => rule.use === '@nativescript/webpack/hmr/hot-loader'); + nativeScriptDevWebpackHotLoader.test = /\.(ts|tsx|js|css|scss|html|xml)$/; - /** We don't officially support JSX. Makes the webpack config rather more complicated to set up. */ - baseConfig.resolve.extensions = [".tsx", ...baseConfig.resolve.extensions]; - baseConfig.resolve.alias["react-dom"] = "react-nativescript"; + /** We don't officially support JSX. Makes the webpack config rather more complicated to set up. */ + baseConfig.resolve.extensions = ['.tsx', ...baseConfig.resolve.extensions]; + baseConfig.resolve.alias['react-dom'] = 'react-nativescript'; - /** Augment NativeScript's existing DefinePlugin definitions with a few more of our own. */ - const existingDefinePlugin = baseConfig.plugins.find(plugin => - plugin && plugin.constructor && plugin.constructor.name === "DefinePlugin" - ); - baseConfig.plugins.splice( - baseConfig.plugins.indexOf(existingDefinePlugin), - 1, - new webpack.DefinePlugin({ - ...existingDefinePlugin.definitions, - /** For various libraries in the React ecosystem. */ - "__DEV__": production ? "false" : "true", - "__TEST__": "false", - /** - * Primarily for React Fast Refresh plugin, but technically the allowHmrInProduction option could be used instead. - * Worth including anyway, as there are plenty of Node libraries that use this flag. - */ - "process.env.NODE_ENV": JSON.stringify(production ? "production" : "development"), - }), - ); + /** Augment NativeScript's existing DefinePlugin definitions with a few more of our own. */ + const existingDefinePlugin = baseConfig.plugins.find((plugin) => plugin && plugin.constructor && plugin.constructor.name === 'DefinePlugin'); + baseConfig.plugins.splice( + baseConfig.plugins.indexOf(existingDefinePlugin), + 1, + new webpack.DefinePlugin({ + ...existingDefinePlugin.definitions, + /** For various libraries in the React ecosystem. */ + __DEV__: production ? 'false' : 'true', + __TEST__: 'false', + /** + * Primarily for React Fast Refresh plugin, but technically the allowHmrInProduction option could be used instead. + * Worth including anyway, as there are plenty of Node libraries that use this flag. + */ + 'process.env.NODE_ENV': JSON.stringify(production ? 'production' : 'development'), + }) + ); - if(hmr && !production){ - baseConfig.plugins.push(new ReactRefreshWebpackPlugin({ - /** - * Maybe one day we'll implement an Error Overlay, but the work involved is too daunting for now. - * @see https://github.com/pmmmwh/react-refresh-webpack-plugin/issues/79#issuecomment-644324557 - */ - overlay: false, - /** - * If you (temporarily) want to enable HMR on a production build: - * 1) Set `forceEnable` to `true` - * 2) Remove the `!production` condition on `tsxRule` to ensure that babel-loader gets used. - */ - forceEnable: false, - })); - } else { - baseConfig.plugins = baseConfig.plugins.filter(p => !(p && p.constructor && p.constructor.name === "HotModuleReplacementPlugin")); - } + if (hmr && !production) { + baseConfig.plugins.push( + new ReactRefreshWebpackPlugin({ + /** + * Maybe one day we'll implement an Error Overlay, but the work involved is too daunting for now. + * @see https://github.com/pmmmwh/react-refresh-webpack-plugin/issues/79#issuecomment-644324557 + */ + overlay: false, + /** + * If you (temporarily) want to enable HMR on a production build: + * 1) Set `forceEnable` to `true` + * 2) Remove the `!production` condition on `tsxRule` to ensure that babel-loader gets used. + */ + forceEnable: false, + }) + ); + } else { + baseConfig.plugins = baseConfig.plugins.filter((p) => !(p && p.constructor && p.constructor.name === 'HotModuleReplacementPlugin')); + } - return baseConfig; -}; \ No newline at end of file + return baseConfig; +}; diff --git a/packages/webpack/templates/webpack.svelte.js b/packages/webpack/templates/webpack.svelte.js index c552dbae5..96cad1a7f 100644 --- a/packages/webpack/templates/webpack.svelte.js +++ b/packages/webpack/templates/webpack.svelte.js @@ -1,34 +1,31 @@ -const { join, relative, resolve, sep } = require("path"); +const { join, relative, resolve, sep } = require('path'); const fs = require('fs'); -const webpack = require("webpack"); -const nsWebpack = require("@nativescript/webpack"); -const nativescriptTarget = require("@nativescript/webpack/nativescript-target"); -const { getNoEmitOnErrorFromTSConfig } = require("@nativescript/webpack/utils/tsconfig-utils"); -const { CleanWebpackPlugin } = require("clean-webpack-plugin"); -const CopyWebpackPlugin = require("copy-webpack-plugin"); +const webpack = require('webpack'); +const nsWebpack = require('@nativescript/webpack'); +const nativescriptTarget = require('@nativescript/webpack/nativescript-target'); +const { getNoEmitOnErrorFromTSConfig } = require('@nativescript/webpack/utils/tsconfig-utils'); +const { CleanWebpackPlugin } = require('clean-webpack-plugin'); +const CopyWebpackPlugin = require('copy-webpack-plugin'); const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin'); -const { BundleAnalyzerPlugin } = require("webpack-bundle-analyzer"); -const { NativeScriptWorkerPlugin } = require("nativescript-worker-loader/NativeScriptWorkerPlugin"); -const TerserPlugin = require("terser-webpack-plugin"); +const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer'); +const { NativeScriptWorkerPlugin } = require('nativescript-worker-loader/NativeScriptWorkerPlugin'); +const TerserPlugin = require('terser-webpack-plugin'); const hashSalt = Date.now().toString(); -const preprocessConfig = require("./svelte.config.js"); -const svelteNativePreprocessor = require("svelte-native-preprocessor"); +const preprocessConfig = require('./svelte.config.js'); +const svelteNativePreprocessor = require('svelte-native-preprocessor'); -module.exports = env => { +module.exports = (env) => { // Add your custom Activities, Services and other Android app components here. const appComponents = env.appComponents || []; - appComponents.push(...[ - "@nativescript/core/ui/frame", - "@nativescript/core/ui/frame/activity", - ]); + appComponents.push(...['@nativescript/core/ui/frame', '@nativescript/core/ui/frame/activity']); - const platform = env && (env.android && "android" || env.ios && "ios" || env.platform); + const platform = env && ((env.android && 'android') || (env.ios && 'ios') || env.platform); if (!platform) { - throw new Error("You need to provide a target platform!"); + throw new Error('You need to provide a target platform!'); } - const platforms = ["ios", "android"]; + const platforms = ['ios', 'android']; const projectRoot = __dirname; if (env.platform) { @@ -41,8 +38,8 @@ module.exports = env => { const { // The 'appPath' and 'appResourcesPath' values are fetched from // the nsconfig.json configuration file. - appPath = "src", - appResourcesPath = "App_Resources", + appPath = 'src', + appResourcesPath = 'App_Resources', // You can provide the following flags when running 'tns run android|ios' snapshot, // --env.snapshot @@ -55,9 +52,10 @@ module.exports = env => { unitTesting, // --env.unitTesting, testing, // --env.testing verbose, // --env.verbose + ci, // --env.ci snapshotInDocker, // --env.snapshotInDocker skipSnapshotTools, // --env.skipSnapshotTools - compileSnapshot // --env.compileSnapshot + compileSnapshot, // --env.compileSnapshot } = env; const useLibs = compileSnapshot; @@ -70,14 +68,14 @@ module.exports = env => { appFullPath = resolve(projectRoot, 'app'); } const hasRootLevelScopedModules = nsWebpack.hasRootLevelScopedModules({ projectDir: projectRoot }); - let coreModulesPackageName = "tns-core-modules"; + let coreModulesPackageName = 'tns-core-modules'; const alias = env.alias || {}; alias['~/package.json'] = resolve(projectRoot, 'package.json'); alias['~'] = appFullPath; if (hasRootLevelScopedModules) { - coreModulesPackageName = "@nativescript/core"; - alias["tns-core-modules"] = coreModulesPackageName; + coreModulesPackageName = '@nativescript/core'; + alias['tns-core-modules'] = coreModulesPackageName; } const appResourcesFullPath = resolve(projectRoot, appResourcesPath); @@ -88,34 +86,34 @@ module.exports = env => { const entries = env.entries || {}; entries.bundle = entryPath; - const tsConfigPath = resolve(projectRoot, "tsconfig.json"); + const tsConfigPath = resolve(projectRoot, 'tsconfig.json'); - const areCoreModulesExternal = Array.isArray(env.externals) && env.externals.some(e => e.indexOf("@nativescript") > -1); - if (platform === "ios" && !areCoreModulesExternal && !testing) { - entries["tns_modules/@nativescript/core/inspector_modules"] = "inspector_modules"; - }; + const areCoreModulesExternal = Array.isArray(env.externals) && env.externals.some((e) => e.indexOf('@nativescript') > -1); + if (platform === 'ios' && !areCoreModulesExternal && !testing) { + entries['tns_modules/@nativescript/core/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")}`); + 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 noEmitOnErrorFromTSConfig = getNoEmitOnErrorFromTSConfig(tsConfigPath); nsWebpack.processAppComponents(appComponents, platform); const config = { - mode: production ? "production" : "development", + mode: production ? 'production' : 'development', context: appFullPath, externals, watchOptions: { ignored: [ appResourcesFullPath, // Don't watch hidden files - "**/.*", - ] + '**/.*', + ], }, target: nativescriptTarget, entry: entries, @@ -123,74 +121,78 @@ module.exports = env => { pathinfo: false, path: dist, sourceMapFilename, - libraryTarget: "commonjs2", - filename: "[name].js", - globalObject: "global", - hashSalt + libraryTarget: 'commonjs2', + filename: '[name].js', + globalObject: 'global', + hashSalt, }, resolve: { - extensions: [".ts", ".mjs", ".js", ".svelte", ".scss", ".css"], + extensions: ['.ts', '.mjs', '.js', '.svelte', '.scss', '.css'], // Resolve {N} system modules from @nativescript/core - modules: [ - resolve(__dirname, `node_modules/${coreModulesPackageName}`), - resolve(__dirname, "node_modules"), - `node_modules/${coreModulesPackageName}`, - "node_modules", - ], + modules: [resolve(__dirname, `node_modules/${coreModulesPackageName}`), resolve(__dirname, 'node_modules'), `node_modules/${coreModulesPackageName}`, 'node_modules'], alias, // resolve symlinks to symlinked modules - symlinks: true + symlinks: true, }, resolveLoader: { // don't resolve symlinks to symlinked loaders - symlinks: false + symlinks: false, }, node: { // Disable node shims that conflict with NativeScript - "http": false, - "timers": false, - "setImmediate": false, - "fs": "empty", - "__dirname": false, + http: false, + timers: false, + setImmediate: false, + fs: 'empty', + __dirname: false, }, - devtool: hiddenSourceMap ? "hidden-source-map" : (sourceMap ? "inline-source-map" : "none"), + devtool: hiddenSourceMap ? 'hidden-source-map' : sourceMap ? 'inline-source-map' : 'none', optimization: { - runtimeChunk: "single", + runtimeChunk: 'single', noEmitOnErrors: noEmitOnErrorFromTSConfig, splitChunks: { cacheGroups: { vendor: { - name: "vendor", - chunks: "all", + name: 'vendor', + chunks: 'all', test: (module, chunks) => { const moduleName = module.nameForCondition ? module.nameForCondition() : ''; - return /[\\/]node_modules[\\/]/.test(moduleName) || - appComponents.some(comp => comp === moduleName); - + return /[\\/]node_modules[\\/]/.test(moduleName) || appComponents.some((comp) => comp === moduleName); }, enforce: true, }, - } + }, }, minimize: !!uglify, minimizer: [ new TerserPlugin({ parallel: true, - cache: true, + cache: !ci, sourceMap: isAnySourceMapEnabled, terserOptions: { output: { comments: false, - semicolons: !isAnySourceMapEnabled + semicolons: !isAnySourceMapEnabled, }, compress: { // The Android SBG has problems parsing the output // when these options are enabled - 'collapse_vars': platform !== "android", - sequences: platform !== "android", - } - } - }) + collapse_vars: platform !== 'android', + sequences: platform !== 'android', + // For v8 Compatibility + keep_infinity: true, // for V8 + reduce_funcs: false, // for V8 + // custom + drop_console: production, + drop_debugger: true, + global_defs: { + __UGLIFIED__: true, + }, + }, + // Required for Element Level CSS, Observable Events, & Android Frame + keep_classnames: true, + }, + }), ], }, module: { @@ -199,42 +201,39 @@ module.exports = env => { include: join(appFullPath, entryPath), use: [ // Require all Android app components - platform === "android" && { - loader: "@nativescript/webpack/helpers/android-app-components-loader", - options: { modules: appComponents } + platform === 'android' && { + loader: '@nativescript/webpack/helpers/android-app-components-loader', + options: { modules: appComponents }, }, { - loader: "@nativescript/webpack/bundle-config-loader", + loader: '@nativescript/webpack/bundle-config-loader', options: { loadCss: !snapshot, // load the application css if in debug mode unitTesting, appFullPath, projectRoot, - ignoredFiles: nsWebpack.getUserDefinedEntries(entries, platform) - } + ignoredFiles: nsWebpack.getUserDefinedEntries(entries, platform), + }, }, - ].filter(loader => !!loader) + ].filter((loader) => !!loader), }, { test: /\.(ts|css|scss|html|xml)$/, - use: "@nativescript/webpack/hmr/hot-loader" + use: '@nativescript/webpack/hmr/hot-loader', }, - { test: /\.(html|xml)$/, use: "@nativescript/webpack/helpers/xml-namespace-loader" }, + { test: /\.(html|xml)$/, use: '@nativescript/webpack/helpers/xml-namespace-loader' }, { test: /\.css$/, - use: "@nativescript/webpack/helpers/css2json-loader" + use: '@nativescript/webpack/helpers/css2json-loader', }, { test: /\.scss$/, - use: [ - "@nativescript/webpack/helpers/css2json-loader", - "sass-loader" - ] + use: ['@nativescript/webpack/helpers/css2json-loader', 'sass-loader'], }, { @@ -244,7 +243,7 @@ module.exports = env => { { test: /\.ts$/, use: { - loader: "ts-loader", + loader: 'ts-loader', options: { configFile: tsConfigPath, // https://github.com/TypeStrong/ts-loader/blob/ea2fcf925ec158d0a536d1e766adfec6567f5fb4/README.md#faster-builds @@ -253,15 +252,13 @@ module.exports = env => { allowTsInNodeModules: true, compilerOptions: { sourceMap: isAnySourceMapEnabled, - declaration: false + declaration: false, }, getCustomTransformers: (program) => ({ - before: [ - require("@nativescript/webpack/transformers/ns-transform-native-classes").default - ] - }) + before: [require('@nativescript/webpack/transformers/ns-transform-native-classes').default], + }), }, - } + }, }, { test: /\.svelte$/, @@ -275,35 +272,30 @@ module.exports = env => { hotReload: env.production ? false : true, hotOptions: { injectCss: false, - native: true - } - } - } - ] - } - ] + native: true, + }, + }, + }, + ], + }, + ], }, plugins: [ // Define useful constants like TNS_WEBPACK new webpack.DefinePlugin({ - "global.TNS_WEBPACK": "true", - "global.isAndroid": platform === 'android', - "global.isIOS": platform === 'ios', - "process": "global.process", + 'global.TNS_WEBPACK': 'true', + 'global.isAndroid': platform === 'android', + 'global.isIOS': platform === 'ios', + process: 'global.process', }), // Remove all files from the out dir. new CleanWebpackPlugin({ cleanOnceBeforeBuildPatterns: itemsToClean, - verbose: !!verbose + verbose: !!verbose, }), // Copy assets - new CopyWebpackPlugin([ - { from: { glob: 'assets/**', dot: false } }, - { from: { glob: 'fonts/**', dot: false } }, - { from: { glob: '**/*.jpg', dot: false } }, - { from: { glob: '**/*.png', dot: false } }, - ], copyIgnore), - new nsWebpack.GenerateNativeScriptEntryPointsPlugin("bundle"), + new CopyWebpackPlugin([{ from: { glob: 'assets/**', dot: false } }, { from: { glob: 'fonts/**', dot: false } }, { from: { glob: '**/*.jpg', dot: false } }, { from: { glob: '**/*.png', dot: false } }], copyIgnore), + new nsWebpack.GenerateNativeScriptEntryPointsPlugin('bundle'), // For instructions on how to set up workers with webpack // check out https://github.com/nativescript/worker-loader new NativeScriptWorkerPlugin(), @@ -322,36 +314,38 @@ module.exports = env => { memoryLimit: 4096, diagnosticOptions: { syntactic: true, - semantic: true - } - } - }) + semantic: true, + }, + }, + }), ], }; if (report) { // Generate report files for bundles content - config.plugins.push(new BundleAnalyzerPlugin({ - analyzerMode: "static", - openAnalyzer: false, - generateStatsFile: true, - reportFilename: resolve(projectRoot, "report", `report.html`), - statsFilename: resolve(projectRoot, "report", `stats.json`), - })); + config.plugins.push( + new BundleAnalyzerPlugin({ + analyzerMode: 'static', + openAnalyzer: false, + generateStatsFile: true, + reportFilename: resolve(projectRoot, 'report', `report.html`), + statsFilename: resolve(projectRoot, 'report', `stats.json`), + }) + ); } if (snapshot) { - config.plugins.push(new nsWebpack.NativeScriptSnapshotPlugin({ - chunk: "vendor", - requireModules: [ - "@nativescript/core/bundle-entry-points", - ], - projectRoot, - webpackConfig: config, - snapshotInDocker, - skipSnapshotTools, - useLibs - })); + config.plugins.push( + new nsWebpack.NativeScriptSnapshotPlugin({ + chunk: 'vendor', + requireModules: ['@nativescript/core/bundle-entry-points'], + projectRoot, + webpackConfig: config, + snapshotInDocker, + skipSnapshotTools, + useLibs, + }) + ); } if (hmr) { diff --git a/packages/webpack/templates/webpack.typescript.js b/packages/webpack/templates/webpack.typescript.js index cb43e5966..3fdd56dcd 100644 --- a/packages/webpack/templates/webpack.typescript.js +++ b/packages/webpack/templates/webpack.typescript.js @@ -1,338 +1,332 @@ -const { join, relative, resolve, sep } = require("path"); +const { join, relative, resolve, sep } = require('path'); const fs = require('fs'); -const webpack = require("webpack"); -const nsWebpack = require("@nativescript/webpack"); -const nativescriptTarget = require("@nativescript/webpack/nativescript-target"); -const { getNoEmitOnErrorFromTSConfig } = require("@nativescript/webpack/utils/tsconfig-utils"); -const { CleanWebpackPlugin } = require("clean-webpack-plugin"); -const CopyWebpackPlugin = require("copy-webpack-plugin"); +const webpack = require('webpack'); +const nsWebpack = require('@nativescript/webpack'); +const nativescriptTarget = require('@nativescript/webpack/nativescript-target'); +const { getNoEmitOnErrorFromTSConfig } = require('@nativescript/webpack/utils/tsconfig-utils'); +const { CleanWebpackPlugin } = require('clean-webpack-plugin'); +const CopyWebpackPlugin = require('copy-webpack-plugin'); const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin'); -const { BundleAnalyzerPlugin } = require("webpack-bundle-analyzer"); -const { NativeScriptWorkerPlugin } = require("nativescript-worker-loader/NativeScriptWorkerPlugin"); -const TerserPlugin = require("terser-webpack-plugin"); +const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer'); +const { NativeScriptWorkerPlugin } = require('nativescript-worker-loader/NativeScriptWorkerPlugin'); +const TerserPlugin = require('terser-webpack-plugin'); const hashSalt = Date.now().toString(); -module.exports = env => { - // Add your custom Activities, Services and other Android app components here. - const appComponents = env.appComponents || []; - appComponents.push(...[ - "@nativescript/core/ui/frame", - "@nativescript/core/ui/frame/activity", - ]); +module.exports = (env) => { + // Add your custom Activities, Services and other Android app components here. + const appComponents = env.appComponents || []; + appComponents.push(...['@nativescript/core/ui/frame', '@nativescript/core/ui/frame/activity']); - const platform = env && (env.android && "android" || env.ios && "ios" || env.platform); - if (!platform) { - throw new Error("You need to provide a target platform!"); - } + const platform = env && ((env.android && 'android') || (env.ios && 'ios') || env.platform); + if (!platform) { + throw new Error('You need to provide a target platform!'); + } - const platforms = ["ios", "android"]; - const projectRoot = __dirname; + const platforms = ['ios', 'android']; + const projectRoot = __dirname; - if (env.platform) { - platforms.push(env.platform); - } + if (env.platform) { + platforms.push(env.platform); + } - // Default destination inside platforms//... - const dist = resolve(projectRoot, nsWebpack.getAppPath(platform, projectRoot)); + // Default destination inside platforms//... + const dist = resolve(projectRoot, nsWebpack.getAppPath(platform, projectRoot)); - const { - // The 'appPath' and 'appResourcesPath' values are fetched from - // the nsconfig.json configuration file. - appPath = "src", - appResourcesPath = "App_Resources", + const { + // The 'appPath' and 'appResourcesPath' values are fetched from + // the nsconfig.json configuration file. + appPath = 'src', + appResourcesPath = 'App_Resources', - // 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, - testing, // --env.testing - verbose, // --env.verbose - snapshotInDocker, // --env.snapshotInDocker - skipSnapshotTools, // --env.skipSnapshotTools - compileSnapshot // --env.compileSnapshot - } = 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, + testing, // --env.testing + verbose, // --env.verbose + ci, // --env.ci + snapshotInDocker, // --env.snapshotInDocker + skipSnapshotTools, // --env.skipSnapshotTools + compileSnapshot, // --env.compileSnapshot + } = env; - const useLibs = compileSnapshot; - const isAnySourceMapEnabled = !!sourceMap || !!hiddenSourceMap; - const externals = nsWebpack.getConvertedExternals(env.externals); + const useLibs = compileSnapshot; + const isAnySourceMapEnabled = !!sourceMap || !!hiddenSourceMap; + const externals = nsWebpack.getConvertedExternals(env.externals); - let appFullPath = resolve(projectRoot, appPath); - if (!fs.existsSync(appFullPath)) { - // some apps use 'app' directory - appFullPath = resolve(projectRoot, 'app'); - } - const hasRootLevelScopedModules = nsWebpack.hasRootLevelScopedModules({ projectDir: projectRoot }); - let coreModulesPackageName = "tns-core-modules"; - const alias = env.alias || {}; - alias['~/package.json'] = resolve(projectRoot, 'package.json'); - alias['~'] = appFullPath; + let appFullPath = resolve(projectRoot, appPath); + if (!fs.existsSync(appFullPath)) { + // some apps use 'app' directory + appFullPath = resolve(projectRoot, 'app'); + } + const hasRootLevelScopedModules = nsWebpack.hasRootLevelScopedModules({ projectDir: projectRoot }); + let coreModulesPackageName = 'tns-core-modules'; + const alias = env.alias || {}; + alias['~/package.json'] = resolve(projectRoot, 'package.json'); + alias['~'] = appFullPath; - if (hasRootLevelScopedModules) { - coreModulesPackageName = "@nativescript/core"; - alias["tns-core-modules"] = coreModulesPackageName; - } - const appResourcesFullPath = resolve(projectRoot, appResourcesPath); + if (hasRootLevelScopedModules) { + coreModulesPackageName = '@nativescript/core'; + alias['tns-core-modules'] = coreModulesPackageName; + } + const appResourcesFullPath = resolve(projectRoot, appResourcesPath); - const copyIgnore = { ignore: [`${relative(appPath, appResourcesFullPath)}/**`] }; + const copyIgnore = { ignore: [`${relative(appPath, appResourcesFullPath)}/**`] }; - const entryModule = nsWebpack.getEntryModule(appFullPath, platform); - const entryPath = `.${sep}${entryModule}.ts`; - const entries = env.entries || {}; - entries.bundle = entryPath; + const entryModule = nsWebpack.getEntryModule(appFullPath, platform); + const entryPath = `.${sep}${entryModule}.ts`; + const entries = env.entries || {}; + entries.bundle = entryPath; - const tsConfigPath = resolve(projectRoot, "tsconfig.json"); + const tsConfigPath = resolve(projectRoot, 'tsconfig.json'); - const areCoreModulesExternal = Array.isArray(env.externals) && env.externals.some(e => e.indexOf("@nativescript") > -1); - if (platform === "ios" && !areCoreModulesExternal && !testing) { - entries["tns_modules/@nativescript/core/inspector_modules"] = "inspector_modules"; - }; + const areCoreModulesExternal = Array.isArray(env.externals) && env.externals.some((e) => e.indexOf('@nativescript') > -1); + if (platform === 'ios' && !areCoreModulesExternal && !testing) { + entries['tns_modules/@nativescript/core/inspector_modules'] = 'inspector_modules'; + } - let sourceMapFilename = nsWebpack.getSourceMapFilename(hiddenSourceMap, __dirname, dist); + 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 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 noEmitOnErrorFromTSConfig = getNoEmitOnErrorFromTSConfig(tsConfigPath); + const noEmitOnErrorFromTSConfig = getNoEmitOnErrorFromTSConfig(tsConfigPath); - nsWebpack.processAppComponents(appComponents, platform); - const config = { - mode: production ? "production" : "development", - context: appFullPath, - externals, - watchOptions: { - ignored: [ - appResourcesFullPath, - // Don't watch hidden files - "**/.*", - ] - }, - target: nativescriptTarget, - entry: entries, - output: { - pathinfo: false, - path: dist, - sourceMapFilename, - libraryTarget: "commonjs2", - filename: "[name].js", - globalObject: "global", - hashSalt - }, - resolve: { - extensions: [".ts", ".js", ".scss", ".css"], - // Resolve {N} system modules from @nativescript/core - modules: [ - resolve(__dirname, `node_modules/${coreModulesPackageName}`), - resolve(__dirname, "node_modules"), - `node_modules/${coreModulesPackageName}`, - "node_modules", - ], - alias, - // resolve symlinks to symlinked modules - symlinks: true - }, - resolveLoader: { - // don't resolve symlinks to symlinked loaders - symlinks: false - }, - node: { - // Disable node shims that conflict with NativeScript - "http": false, - "timers": false, - "setImmediate": false, - "fs": "empty", - "__dirname": false, - }, - devtool: hiddenSourceMap ? "hidden-source-map" : (sourceMap ? "inline-source-map" : "none"), - optimization: { - runtimeChunk: "single", - noEmitOnErrors: noEmitOnErrorFromTSConfig, - splitChunks: { - cacheGroups: { - vendor: { - name: "vendor", - chunks: "all", - test: (module, chunks) => { - const moduleName = module.nameForCondition ? module.nameForCondition() : ''; - return /[\\/]node_modules[\\/]/.test(moduleName) || - appComponents.some(comp => comp === moduleName); + nsWebpack.processAppComponents(appComponents, platform); + const config = { + mode: production ? 'production' : 'development', + context: appFullPath, + externals, + watchOptions: { + ignored: [ + appResourcesFullPath, + // Don't watch hidden files + '**/.*', + ], + }, + target: nativescriptTarget, + entry: entries, + output: { + pathinfo: false, + path: dist, + sourceMapFilename, + libraryTarget: 'commonjs2', + filename: '[name].js', + globalObject: 'global', + hashSalt, + }, + resolve: { + extensions: ['.ts', '.js', '.scss', '.css'], + // Resolve {N} system modules from @nativescript/core + modules: [resolve(__dirname, `node_modules/${coreModulesPackageName}`), resolve(__dirname, 'node_modules'), `node_modules/${coreModulesPackageName}`, 'node_modules'], + alias, + // resolve symlinks to symlinked modules + symlinks: true, + }, + resolveLoader: { + // don't resolve symlinks to symlinked loaders + symlinks: false, + }, + node: { + // Disable node shims that conflict with NativeScript + http: false, + timers: false, + setImmediate: false, + fs: 'empty', + __dirname: false, + }, + devtool: hiddenSourceMap ? 'hidden-source-map' : sourceMap ? 'inline-source-map' : 'none', + optimization: { + runtimeChunk: 'single', + noEmitOnErrors: noEmitOnErrorFromTSConfig, + splitChunks: { + cacheGroups: { + vendor: { + name: 'vendor', + chunks: 'all', + test: (module, chunks) => { + const moduleName = module.nameForCondition ? module.nameForCondition() : ''; + return /[\\/]node_modules[\\/]/.test(moduleName) || appComponents.some((comp) => comp === moduleName); + }, + enforce: true, + }, + }, + }, + minimize: !!uglify, + minimizer: [ + new TerserPlugin({ + parallel: true, + cache: !ci, + sourceMap: isAnySourceMapEnabled, + terserOptions: { + output: { + comments: false, + semicolons: !isAnySourceMapEnabled, + }, + compress: { + // The Android SBG has problems parsing the output + // when these options are enabled + collapse_vars: platform !== 'android', + sequences: platform !== 'android', + // For v8 Compatibility + keep_infinity: true, // for V8 + reduce_funcs: false, // for V8 + // custom + drop_console: production, + drop_debugger: true, + global_defs: { + __UGLIFIED__: true, + }, + }, + // Required for Element Level CSS, Observable Events, & Android Frame + keep_classnames: true, + }, + }), + ], + }, + module: { + rules: [ + { + include: join(appFullPath, entryPath), + use: [ + // Require all Android app components + platform === 'android' && { + loader: '@nativescript/webpack/helpers/android-app-components-loader', + options: { modules: appComponents }, + }, - }, - enforce: true, - }, - } - }, - minimize: !!uglify, - minimizer: [ - new TerserPlugin({ - parallel: true, - cache: true, - sourceMap: isAnySourceMapEnabled, - terserOptions: { - output: { - comments: false, - semicolons: !isAnySourceMapEnabled - }, - compress: { - // The Android SBG has problems parsing the output - // when these options are enabled - 'collapse_vars': platform !== "android", - sequences: platform !== "android", - } - } - }) - ], - }, - module: { - rules: [ - { - include: join(appFullPath, entryPath), - use: [ - // Require all Android app components - platform === "android" && { - loader: "@nativescript/webpack/helpers/android-app-components-loader", - options: { modules: appComponents } - }, + { + loader: '@nativescript/webpack/bundle-config-loader', + options: { + loadCss: !snapshot, // load the application css if in debug mode + unitTesting, + appFullPath, + projectRoot, + ignoredFiles: nsWebpack.getUserDefinedEntries(entries, platform), + }, + }, + ].filter((loader) => !!loader), + }, - { - loader: "@nativescript/webpack/bundle-config-loader", - options: { - loadCss: !snapshot, // load the application css if in debug mode - unitTesting, - appFullPath, - projectRoot, - ignoredFiles: nsWebpack.getUserDefinedEntries(entries, platform) - } - }, - ].filter(loader => !!loader) - }, + { + test: /\.(ts|css|scss|html|xml)$/, + use: '@nativescript/webpack/hmr/hot-loader', + }, - { - test: /\.(ts|css|scss|html|xml)$/, - use: "@nativescript/webpack/hmr/hot-loader" - }, + { test: /\.(html|xml)$/, use: '@nativescript/webpack/helpers/xml-namespace-loader' }, - { test: /\.(html|xml)$/, use: "@nativescript/webpack/helpers/xml-namespace-loader" }, + { + test: /\.css$/, + use: '@nativescript/webpack/helpers/css2json-loader', + }, - { - test: /\.css$/, - use: "@nativescript/webpack/helpers/css2json-loader" - }, + { + test: /\.scss$/, + use: ['@nativescript/webpack/helpers/css2json-loader', 'sass-loader'], + }, - { - test: /\.scss$/, - use: [ - "@nativescript/webpack/helpers/css2json-loader", - "sass-loader" - ] - }, + { + test: /\.ts$/, + use: { + loader: 'ts-loader', + options: { + configFile: tsConfigPath, + // 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, + declaration: false, + }, + getCustomTransformers: (program) => ({ + before: [require('@nativescript/webpack/transformers/ns-transform-native-classes').default], + }), + }, + }, + }, + ], + }, + plugins: [ + // Define useful constants like TNS_WEBPACK + new webpack.DefinePlugin({ + 'global.TNS_WEBPACK': 'true', + 'global.isAndroid': platform === 'android', + 'global.isIOS': platform === 'ios', + process: 'global.process', + }), + // Remove all files from the out dir. + new CleanWebpackPlugin({ + cleanOnceBeforeBuildPatterns: itemsToClean, + verbose: !!verbose, + }), + // Copy assets + new CopyWebpackPlugin([{ from: { glob: 'assets/**', dot: false } }, { from: { glob: 'fonts/**', dot: false } }, { from: { glob: '**/*.jpg', dot: false } }, { from: { glob: '**/*.png', dot: false } }], copyIgnore), + new nsWebpack.GenerateNativeScriptEntryPointsPlugin('bundle'), + // For instructions on how to set up workers with webpack + // check out https://github.com/nativescript/worker-loader + new NativeScriptWorkerPlugin(), + new nsWebpack.PlatformFSPlugin({ + platform, + platforms, + }), + // 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({ + async: false, + typescript: { + configFile: tsConfigPath, + memoryLimit: 4096, + diagnosticOptions: { + syntactic: true, + semantic: true, + }, + }, + }), + ], + }; - { - test: /\.ts$/, - use: { - loader: "ts-loader", - options: { - configFile: tsConfigPath, - // 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, - declaration: false - }, - getCustomTransformers: (program) => ({ - before: [ - require("@nativescript/webpack/transformers/ns-transform-native-classes").default - ] - }) - }, - } - }, - ] - }, - plugins: [ - // Define useful constants like TNS_WEBPACK - new webpack.DefinePlugin({ - "global.TNS_WEBPACK": "true", - "global.isAndroid": platform === 'android', - "global.isIOS": platform === 'ios', - "process": "global.process", - }), - // Remove all files from the out dir. - new CleanWebpackPlugin({ - cleanOnceBeforeBuildPatterns: itemsToClean, - verbose: !!verbose - }), - // Copy assets - new CopyWebpackPlugin([ - { from: { glob: 'assets/**', dot: false } }, - { from: { glob: 'fonts/**', dot: false } }, - { from: { glob: '**/*.jpg', dot: false } }, - { from: { glob: '**/*.png', dot: false } }, - ], copyIgnore), - new nsWebpack.GenerateNativeScriptEntryPointsPlugin("bundle"), - // For instructions on how to set up workers with webpack - // check out https://github.com/nativescript/worker-loader - new NativeScriptWorkerPlugin(), - new nsWebpack.PlatformFSPlugin({ - platform, - platforms, - }), - // 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({ - async: false, - typescript: { - configFile: tsConfigPath, - memoryLimit: 4096, - diagnosticOptions: { - syntactic: true, - semantic: true - } - } - }) - ], - }; + if (report) { + // Generate report files for bundles content + config.plugins.push( + new BundleAnalyzerPlugin({ + analyzerMode: 'static', + openAnalyzer: false, + generateStatsFile: true, + reportFilename: resolve(projectRoot, 'report', `report.html`), + statsFilename: resolve(projectRoot, 'report', `stats.json`), + }) + ); + } - if (report) { - // Generate report files for bundles content - config.plugins.push(new BundleAnalyzerPlugin({ - analyzerMode: "static", - openAnalyzer: false, - generateStatsFile: true, - reportFilename: resolve(projectRoot, "report", `report.html`), - statsFilename: resolve(projectRoot, "report", `stats.json`), - })); - } + if (snapshot) { + config.plugins.push( + new nsWebpack.NativeScriptSnapshotPlugin({ + chunk: 'vendor', + requireModules: ['@nativescript/core/bundle-entry-points'], + projectRoot, + webpackConfig: config, + snapshotInDocker, + skipSnapshotTools, + useLibs, + }) + ); + } - if (snapshot) { - config.plugins.push(new nsWebpack.NativeScriptSnapshotPlugin({ - chunk: "vendor", - requireModules: [ - "@nativescript/core/bundle-entry-points", - ], - projectRoot, - webpackConfig: config, - snapshotInDocker, - skipSnapshotTools, - useLibs - })); - } + if (hmr) { + config.plugins.push(new webpack.HotModuleReplacementPlugin()); + } - if (hmr) { - config.plugins.push(new webpack.HotModuleReplacementPlugin()); - } - - return config; + return config; }; diff --git a/packages/webpack/templates/webpack.vue.js b/packages/webpack/templates/webpack.vue.js index 12987e9bc..acd24d991 100644 --- a/packages/webpack/templates/webpack.vue.js +++ b/packages/webpack/templates/webpack.vue.js @@ -1,368 +1,357 @@ -const { join, relative, resolve, sep } = require("path"); +const { join, relative, resolve, sep } = require('path'); -const webpack = require("webpack"); -const { CleanWebpackPlugin } = require("clean-webpack-plugin"); -const CopyWebpackPlugin = require("copy-webpack-plugin"); -const { BundleAnalyzerPlugin } = require("webpack-bundle-analyzer"); -const TerserPlugin = require("terser-webpack-plugin"); +const webpack = require('webpack'); +const { CleanWebpackPlugin } = require('clean-webpack-plugin'); +const CopyWebpackPlugin = require('copy-webpack-plugin'); +const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer'); +const TerserPlugin = require('terser-webpack-plugin'); const VueLoaderPlugin = require('vue-loader/lib/plugin'); -const NsVueTemplateCompiler = require("nativescript-vue-template-compiler"); +const NsVueTemplateCompiler = require('nativescript-vue-template-compiler'); -const nsWebpack = require("@nativescript/webpack"); -const nativescriptTarget = require("@nativescript/webpack/nativescript-target"); -const { NativeScriptWorkerPlugin } = require("nativescript-worker-loader/NativeScriptWorkerPlugin"); +const nsWebpack = require('@nativescript/webpack'); +const nativescriptTarget = require('@nativescript/webpack/nativescript-target'); +const { NativeScriptWorkerPlugin } = require('nativescript-worker-loader/NativeScriptWorkerPlugin'); const hashSalt = Date.now().toString(); -module.exports = env => { - // Add your custom Activities, Services and other android app components here. - const appComponents = env.appComponents || []; - appComponents.push(...[ - "@nativescript/core/ui/frame", - "@nativescript/core/ui/frame/activity", - ]); +module.exports = (env) => { + // Add your custom Activities, Services and other android app components here. + const appComponents = env.appComponents || []; + appComponents.push(...['@nativescript/core/ui/frame', '@nativescript/core/ui/frame/activity']); - const platform = env && (env.android && "android" || env.ios && "ios" || env.platform); - if (!platform) { - throw new Error("You need to provide a target platform!"); - } + const platform = env && ((env.android && 'android') || (env.ios && 'ios') || env.platform); + if (!platform) { + throw new Error('You need to provide a target platform!'); + } - const platforms = ["ios", "android"]; - const projectRoot = __dirname; + const platforms = ['ios', 'android']; + const projectRoot = __dirname; - if (env.platform) { - platforms.push(env.platform); - } + if (env.platform) { + platforms.push(env.platform); + } - // Default destination inside platforms//... - const dist = resolve(projectRoot, nsWebpack.getAppPath(platform, projectRoot)); + // Default destination inside platforms//... + const dist = resolve(projectRoot, nsWebpack.getAppPath(platform, projectRoot)); - const { - // The 'appPath' and 'appResourcesPath' values are fetched from - // the nsconfig.json configuration file. - appPath = "app", - appResourcesPath = "app/App_Resources", + const { + // The 'appPath' and 'appResourcesPath' values are fetched from + // the nsconfig.json configuration file. + appPath = 'app', + appResourcesPath = 'app/App_Resources', - // You can provide the following flags when running 'tns run android|ios' - snapshot, // --env.snapshot - production, // --env.production - report, // --env.report - hmr, // --env.hmr - sourceMap, // --env.sourceMap - hiddenSourceMap, // --env.hiddenSourceMap - unitTesting, // --env.unitTesting - testing, // --env.testing - verbose, // --env.verbose - snapshotInDocker, // --env.snapshotInDocker - skipSnapshotTools, // --env.skipSnapshotTools - compileSnapshot // --env.compileSnapshot - } = env; + // You can provide the following flags when running 'tns run android|ios' + snapshot, // --env.snapshot + production, // --env.production + report, // --env.report + hmr, // --env.hmr + sourceMap, // --env.sourceMap + hiddenSourceMap, // --env.hiddenSourceMap + unitTesting, // --env.unitTesting + testing, // --env.testing + verbose, // --env.verbose + ci, // --env.ci + snapshotInDocker, // --env.snapshotInDocker + skipSnapshotTools, // --env.skipSnapshotTools + compileSnapshot, // --env.compileSnapshot + } = env; - const useLibs = compileSnapshot; - const isAnySourceMapEnabled = !!sourceMap || !!hiddenSourceMap; - const externals = nsWebpack.getConvertedExternals(env.externals); + const useLibs = compileSnapshot; + const isAnySourceMapEnabled = !!sourceMap || !!hiddenSourceMap; + const externals = nsWebpack.getConvertedExternals(env.externals); - const mode = production ? "production" : "development" + const mode = production ? 'production' : 'development'; - const appFullPath = resolve(projectRoot, appPath); - const hasRootLevelScopedModules = nsWebpack.hasRootLevelScopedModules({ projectDir: projectRoot }); - let coreModulesPackageName = "tns-core-modules"; - const alias = env.alias || {}; - alias['~/package.json'] = resolve(projectRoot, 'package.json'); - alias['~'] = appFullPath; - alias['@'] = appFullPath; - alias['vue'] = 'nativescript-vue'; + const appFullPath = resolve(projectRoot, appPath); + const hasRootLevelScopedModules = nsWebpack.hasRootLevelScopedModules({ projectDir: projectRoot }); + let coreModulesPackageName = 'tns-core-modules'; + const alias = env.alias || {}; + alias['~/package.json'] = resolve(projectRoot, 'package.json'); + alias['~'] = appFullPath; + alias['@'] = appFullPath; + alias['vue'] = 'nativescript-vue'; - if (hasRootLevelScopedModules) { - coreModulesPackageName = "@nativescript/core"; - alias["tns-core-modules"] = coreModulesPackageName; - } + if (hasRootLevelScopedModules) { + coreModulesPackageName = '@nativescript/core'; + alias['tns-core-modules'] = coreModulesPackageName; + } - const appResourcesFullPath = resolve(projectRoot, appResourcesPath); + const appResourcesFullPath = resolve(projectRoot, appResourcesPath); - const copyIgnore = { ignore: [`${relative(appPath, appResourcesFullPath)}/**`] }; + const copyIgnore = { ignore: [`${relative(appPath, appResourcesFullPath)}/**`] }; - const entryModule = nsWebpack.getEntryModule(appFullPath, platform); - const entryPath = `.${sep}${entryModule}`; - const entries = env.entries || {}; - entries.bundle = entryPath; + const entryModule = nsWebpack.getEntryModule(appFullPath, platform); + const entryPath = `.${sep}${entryModule}`; + const entries = env.entries || {}; + entries.bundle = entryPath; - const areCoreModulesExternal = Array.isArray(env.externals) && env.externals.some(e => e.indexOf("@nativescript") > -1); - if (platform === "ios" && !areCoreModulesExternal && !testing) { - entries["tns_modules/@nativescript/core/inspector_modules"] = "inspector_modules"; - }; - console.log(`Bundling application for entryPath ${entryPath}...`); + const areCoreModulesExternal = Array.isArray(env.externals) && env.externals.some((e) => e.indexOf('@nativescript') > -1); + if (platform === 'ios' && !areCoreModulesExternal && !testing) { + entries['tns_modules/@nativescript/core/inspector_modules'] = 'inspector_modules'; + } + console.log(`Bundling application for entryPath ${entryPath}...`); - let sourceMapFilename = nsWebpack.getSourceMapFilename(hiddenSourceMap, __dirname, dist); + 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 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')}`); + } - nsWebpack.processAppComponents(appComponents, platform); - const config = { - mode: mode, - context: appFullPath, - externals, - watchOptions: { - ignored: [ - appResourcesFullPath, - // Don't watch hidden files - "**/.*", - ], - }, - target: nativescriptTarget, - // target: nativeScriptVueTarget, - entry: entries, - output: { - pathinfo: false, - path: dist, - sourceMapFilename, - libraryTarget: "commonjs2", - filename: "[name].js", - globalObject: "global", - hashSalt - }, - resolve: { - extensions: [".vue", ".ts", ".js", ".scss", ".css"], - // Resolve {N} system modules from @nativescript/core - modules: [ - resolve(__dirname, `node_modules/${coreModulesPackageName}`), - resolve(__dirname, "node_modules"), - `node_modules/${coreModulesPackageName}`, - "node_modules", - ], - alias, - // resolve symlinks to symlinked modules - symlinks: true, - }, - resolveLoader: { - // don't resolve symlinks to symlinked loaders - symlinks: false, - }, - node: { - // Disable node shims that conflict with NativeScript - "http": false, - "timers": false, - "setImmediate": false, - "fs": "empty", - "__dirname": false, - }, - devtool: hiddenSourceMap ? "hidden-source-map" : (sourceMap ? "inline-source-map" : "none"), - optimization: { - runtimeChunk: "single", - noEmitOnErrors: true, - splitChunks: { - cacheGroups: { - vendor: { - name: "vendor", - chunks: "all", - test: (module) => { - const moduleName = module.nameForCondition ? module.nameForCondition() : ''; - return /[\\/]node_modules[\\/]/.test(moduleName) || - appComponents.some(comp => comp === moduleName); + nsWebpack.processAppComponents(appComponents, platform); + const config = { + mode: mode, + context: appFullPath, + externals, + watchOptions: { + ignored: [ + appResourcesFullPath, + // Don't watch hidden files + '**/.*', + ], + }, + target: nativescriptTarget, + // target: nativeScriptVueTarget, + entry: entries, + output: { + pathinfo: false, + path: dist, + sourceMapFilename, + libraryTarget: 'commonjs2', + filename: '[name].js', + globalObject: 'global', + hashSalt, + }, + resolve: { + extensions: ['.vue', '.ts', '.js', '.scss', '.css'], + // Resolve {N} system modules from @nativescript/core + modules: [resolve(__dirname, `node_modules/${coreModulesPackageName}`), resolve(__dirname, 'node_modules'), `node_modules/${coreModulesPackageName}`, 'node_modules'], + alias, + // resolve symlinks to symlinked modules + symlinks: true, + }, + resolveLoader: { + // don't resolve symlinks to symlinked loaders + symlinks: false, + }, + node: { + // Disable node shims that conflict with NativeScript + http: false, + timers: false, + setImmediate: false, + fs: 'empty', + __dirname: false, + }, + devtool: hiddenSourceMap ? 'hidden-source-map' : sourceMap ? 'inline-source-map' : 'none', + optimization: { + runtimeChunk: 'single', + noEmitOnErrors: true, + splitChunks: { + cacheGroups: { + vendor: { + name: 'vendor', + chunks: 'all', + test: (module) => { + const moduleName = module.nameForCondition ? module.nameForCondition() : ''; + return /[\\/]node_modules[\\/]/.test(moduleName) || appComponents.some((comp) => comp === moduleName); + }, + enforce: true, + }, + }, + }, + minimize: Boolean(production), + minimizer: [ + new TerserPlugin({ + parallel: true, + cache: !ci, + sourceMap: isAnySourceMapEnabled, + terserOptions: { + output: { + comments: false, + semicolons: !isAnySourceMapEnabled, + }, + compress: { + // The Android SBG has problems parsing the output + // when these options are enabled + collapse_vars: platform !== 'android', + sequences: platform !== 'android', + // For v8 Compatibility + keep_infinity: true, // for V8 + reduce_funcs: false, // for V8 + // custom + drop_console: production, + drop_debugger: true, + global_defs: { + __UGLIFIED__: true, + }, + }, + keep_fnames: true, + // Required for Element Level CSS, Observable Events, & Android Frame + keep_classnames: true, + }, + }), + ], + }, + module: { + rules: [ + { + include: [join(appFullPath, entryPath + '.js'), join(appFullPath, entryPath + '.ts')], + use: [ + // Require all Android app components + platform === 'android' && { + loader: '@nativescript/webpack/helpers/android-app-components-loader', + options: { modules: appComponents }, + }, - }, - enforce: true, - }, - }, - }, - minimize: Boolean(production), - minimizer: [ - new TerserPlugin({ - parallel: true, - cache: true, - sourceMap: isAnySourceMapEnabled, - terserOptions: { - output: { - comments: false, - semicolons: !isAnySourceMapEnabled - }, - compress: { - // The Android SBG has problems parsing the output - // when these options are enabled - 'collapse_vars': platform !== "android", - sequences: platform !== "android", - }, - keep_fnames: true, - }, - }), - ], - }, - module: { - rules: [{ - include: [join(appFullPath, entryPath + ".js"), join(appFullPath, entryPath + ".ts")], - use: [ - // Require all Android app components - platform === "android" && { - loader: "@nativescript/webpack/helpers/android-app-components-loader", - options: { modules: appComponents }, - }, + { + loader: '@nativescript/webpack/bundle-config-loader', + options: { + registerPages: true, // applicable only for non-angular apps + loadCss: !snapshot, // load the application css if in debug mode + unitTesting, + appFullPath, + projectRoot, + ignoredFiles: nsWebpack.getUserDefinedEntries(entries, platform), + }, + }, + ].filter((loader) => Boolean(loader)), + }, + { + test: /[\/|\\]app\.css$/, + use: [ + '@nativescript/webpack/helpers/style-hot-loader', + { + loader: '@nativescript/webpack/helpers/css2json-loader', + options: { useForImports: true }, + }, + ], + }, + { + test: /[\/|\\]app\.scss$/, + use: [ + '@nativescript/webpack/helpers/style-hot-loader', + { + loader: '@nativescript/webpack/helpers/css2json-loader', + options: { useForImports: true }, + }, + 'sass-loader', + ], + }, + { + test: /\.css$/, + exclude: /[\/|\\]app\.css$/, + use: ['@nativescript/webpack/helpers/style-hot-loader', '@nativescript/webpack/helpers/apply-css-loader.js', { loader: 'css-loader', options: { url: false } }], + }, + { + test: /\.scss$/, + exclude: /[\/|\\]app\.scss$/, + use: ['@nativescript/webpack/helpers/style-hot-loader', '@nativescript/webpack/helpers/apply-css-loader.js', { loader: 'css-loader', options: { url: false } }, 'sass-loader'], + }, + { + test: /\.js$/, + loader: 'babel-loader', + }, + { + test: /\.ts$/, + loader: 'ts-loader', + options: { + appendTsSuffixTo: [/\.vue$/], + allowTsInNodeModules: true, + compilerOptions: { + declaration: false, + }, + getCustomTransformers: (program) => ({ + before: [require('@nativescript/webpack/transformers/ns-transform-native-classes').default], + }), + }, + }, + { + test: /\.vue$/, + loader: 'vue-loader', + options: { + compiler: NsVueTemplateCompiler, + }, + }, + ], + }, + plugins: [ + // ... Vue Loader plugin omitted + // make sure to include the plugin! + new VueLoaderPlugin(), + // Define useful constants like TNS_WEBPACK + new webpack.DefinePlugin({ + 'global.TNS_WEBPACK': 'true', + 'global.isAndroid': platform === 'android', + 'global.isIOS': platform === 'ios', + TNS_ENV: JSON.stringify(mode), + process: 'global.process', + }), + // Remove all files from the out dir. + new CleanWebpackPlugin({ + cleanOnceBeforeBuildPatterns: itemsToClean, + verbose: !!verbose, + }), + // Copy assets + new CopyWebpackPlugin([{ from: { glob: 'assets/**', dot: false } }, { from: { glob: 'fonts/**', dot: false } }, { from: { glob: '**/*.jpg', dot: false } }, { from: { glob: '**/*.png', dot: false } }], copyIgnore), + new nsWebpack.GenerateNativeScriptEntryPointsPlugin('bundle'), + // For instructions on how to set up workers with webpack + // check out https://github.com/nativescript/worker-loader + new NativeScriptWorkerPlugin(), + new nsWebpack.PlatformFSPlugin({ + platform, + platforms, + }), + // Does IPC communication with the {N} CLI to notify events when running in watch mode. + new nsWebpack.WatchStateLoggerPlugin(), + ], + }; - { - loader: "@nativescript/webpack/bundle-config-loader", - options: { - registerPages: true, // applicable only for non-angular apps - loadCss: !snapshot, // load the application css if in debug mode - unitTesting, - appFullPath, - projectRoot, - ignoredFiles: nsWebpack.getUserDefinedEntries(entries, platform) - }, - }, - ].filter(loader => Boolean(loader)), - }, - { - test: /[\/|\\]app\.css$/, - use: [ - '@nativescript/webpack/helpers/style-hot-loader', - { - loader: "@nativescript/webpack/helpers/css2json-loader", - options: { useForImports: true } - }, - ], - }, - { - test: /[\/|\\]app\.scss$/, - use: [ - '@nativescript/webpack/helpers/style-hot-loader', - { - loader: "@nativescript/webpack/helpers/css2json-loader", - options: { useForImports: true } - }, - 'sass-loader', - ], - }, - { - test: /\.css$/, - exclude: /[\/|\\]app\.css$/, - use: [ - '@nativescript/webpack/helpers/style-hot-loader', - '@nativescript/webpack/helpers/apply-css-loader.js', - { loader: "css-loader", options: { url: false } }, - ], - }, - { - test: /\.scss$/, - exclude: /[\/|\\]app\.scss$/, - use: [ - '@nativescript/webpack/helpers/style-hot-loader', - '@nativescript/webpack/helpers/apply-css-loader.js', - { loader: "css-loader", options: { url: false } }, - 'sass-loader', - ], - }, - { - test: /\.js$/, - loader: 'babel-loader', - }, - { - test: /\.ts$/, - loader: 'ts-loader', - options: { - appendTsSuffixTo: [/\.vue$/], - allowTsInNodeModules: true, - compilerOptions: { - declaration: false - }, - getCustomTransformers: (program) => ({ - before: [ - require("@nativescript/webpack/transformers/ns-transform-native-classes").default - ] - }) - }, - }, - { - test: /\.vue$/, - loader: "vue-loader", - options: { - compiler: NsVueTemplateCompiler, - }, - }, - ], - }, - plugins: [ - // ... Vue Loader plugin omitted - // make sure to include the plugin! - new VueLoaderPlugin(), - // Define useful constants like TNS_WEBPACK - new webpack.DefinePlugin({ - "global.TNS_WEBPACK": "true", - "global.isAndroid": platform === 'android', - "global.isIOS": platform === 'ios', - "TNS_ENV": JSON.stringify(mode), - "process": "global.process" - }), - // Remove all files from the out dir. - new CleanWebpackPlugin({ - cleanOnceBeforeBuildPatterns: itemsToClean, - verbose: !!verbose - }), - // Copy assets - new CopyWebpackPlugin([ - { from: { glob: 'assets/**', dot: false } }, - { from: { glob: 'fonts/**', dot: false } }, - { from: { glob: '**/*.jpg', dot: false } }, - { from: { glob: '**/*.png', dot: false } }, - ], copyIgnore), - new nsWebpack.GenerateNativeScriptEntryPointsPlugin("bundle"), - // For instructions on how to set up workers with webpack - // check out https://github.com/nativescript/worker-loader - new NativeScriptWorkerPlugin(), - new nsWebpack.PlatformFSPlugin({ - platform, - platforms, - }), - // Does IPC communication with the {N} CLI to notify events when running in watch mode. - new nsWebpack.WatchStateLoggerPlugin() - ], - }; + if (unitTesting) { + config.module.rules.push( + { + test: /-page\.js$/, + use: '@nativescript/webpack/helpers/script-hot-loader', + }, + { + test: /\.(html|xml)$/, + use: '@nativescript/webpack/helpers/markup-hot-loader', + }, - if (unitTesting) { - config.module.rules.push( - { - test: /-page\.js$/, - use: "@nativescript/webpack/helpers/script-hot-loader" - }, - { - test: /\.(html|xml)$/, - use: "@nativescript/webpack/helpers/markup-hot-loader" - }, + { test: /\.(html|xml)$/, use: '@nativescript/webpack/helpers/xml-namespace-loader' } + ); + } - { test: /\.(html|xml)$/, use: "@nativescript/webpack/helpers/xml-namespace-loader" } - ); - } + if (report) { + // Generate report files for bundles content + config.plugins.push( + new BundleAnalyzerPlugin({ + analyzerMode: 'static', + openAnalyzer: false, + generateStatsFile: true, + reportFilename: resolve(projectRoot, 'report', `report.html`), + statsFilename: resolve(projectRoot, 'report', `stats.json`), + }) + ); + } - if (report) { - // Generate report files for bundles content - config.plugins.push(new BundleAnalyzerPlugin({ - analyzerMode: "static", - openAnalyzer: false, - generateStatsFile: true, - reportFilename: resolve(projectRoot, "report", `report.html`), - statsFilename: resolve(projectRoot, "report", `stats.json`), - })); - } + if (snapshot) { + config.plugins.push( + new nsWebpack.NativeScriptSnapshotPlugin({ + chunk: 'vendor', + requireModules: ['@nativescript/core/bundle-entry-points'], + projectRoot, + webpackConfig: config, + snapshotInDocker, + skipSnapshotTools, + useLibs, + }) + ); + } - if (snapshot) { - config.plugins.push(new nsWebpack.NativeScriptSnapshotPlugin({ - chunk: "vendor", - requireModules: [ - "@nativescript/core/bundle-entry-points", - ], - projectRoot, - webpackConfig: config, - snapshotInDocker, - skipSnapshotTools, - useLibs - })); - } + if (hmr) { + config.plugins.push(new webpack.HotModuleReplacementPlugin()); + } - if (hmr) { - config.plugins.push(new webpack.HotModuleReplacementPlugin()); - } - - return config; + return config; };