diff --git a/packages/webpack5/__tests__/configuration/__snapshots__/angular.spec.ts.snap b/packages/webpack5/__tests__/configuration/__snapshots__/angular.spec.ts.snap index 321401b82..f3b4c2d99 100644 --- a/packages/webpack5/__tests__/configuration/__snapshots__/angular.spec.ts.snap +++ b/packages/webpack5/__tests__/configuration/__snapshots__/angular.spec.ts.snap @@ -19,8 +19,8 @@ exports[`angular configuration for android 1`] = ` resolve: { symlinks: true, alias: { - '~': 'appFullPath', - '@': 'appFullPath' + '~': '__jest__/src', + '@': '__jest__/src' }, extensions: [ '.android.ts', @@ -251,8 +251,8 @@ exports[`angular configuration for ios 1`] = ` resolve: { symlinks: true, alias: { - '~': 'appFullPath', - '@': 'appFullPath' + '~': '__jest__/src', + '@': '__jest__/src' }, extensions: [ '.ios.ts', diff --git a/packages/webpack5/__tests__/configuration/__snapshots__/javascript.spec.ts.snap b/packages/webpack5/__tests__/configuration/__snapshots__/javascript.spec.ts.snap new file mode 100644 index 000000000..1b61257d6 --- /dev/null +++ b/packages/webpack5/__tests__/configuration/__snapshots__/javascript.spec.ts.snap @@ -0,0 +1,470 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`javascript configuration for android 1`] = ` +"{ + mode: 'development', + externals: [ + 'package.json', + '~/package.json' + ], + devtool: 'inline-source-map', + target: 'node', + output: { + path: '__jest__/platforms/android/app/src/main/assets/app', + pathinfo: false, + publicPath: '', + libraryTarget: 'commonjs', + globalObject: 'global' + }, + resolve: { + symlinks: true, + alias: { + '~': '__jest__/src', + '@': '__jest__/src' + }, + extensions: [ + '.android.ts', + '.ts', + '.android.js', + '.js', + '.android.css', + '.css', + '.android.scss', + '.scss', + '.android.json', + '.json' + ] + }, + resolveLoader: { + modules: [ + 'node_modules/@nativescript/webpack/dist/loaders', + 'node_modules' + ] + }, + module: { + rules: [ + /* config.module.rule('ts') */ + { + test: [ + /\\\\.ts$/ + ], + use: [ + /* config.module.rule('ts').use('ts-loader') */ + { + loader: 'ts-loader', + options: { + transpileOnly: true, + allowTsInNodeModules: true, + compilerOptions: { + sourceMap: true, + declaration: false + }, + getCustomTransformers: function () { /* omitted long function */ } + } + } + ] + }, + /* config.module.rule('js') */ + { + test: /\\\\.js$/, + exclude: [ + /node_modules/ + ], + use: [ + /* config.module.rule('js').use('babel-loader') */ + { + loader: 'babel-loader', + options: { + generatorOpts: { + compact: false + } + } + } + ] + }, + /* config.module.rule('css') */ + { + test: /\\\\.css$/, + use: [ + /* config.module.rule('css').use('apply-css-loader') */ + { + loader: 'apply-css-loader' + }, + /* config.module.rule('css').use('css2json-loader') */ + { + loader: 'css2json-loader' + } + ] + }, + /* config.module.rule('scss') */ + { + test: /\\\\.scss$/, + use: [ + /* config.module.rule('scss').use('apply-css-loader') */ + { + loader: 'apply-css-loader' + }, + /* config.module.rule('scss').use('css2json-loader') */ + { + loader: 'css2json-loader' + }, + /* config.module.rule('scss').use('sass-loader') */ + { + loader: 'sass-loader' + } + ] + }, + /* config.module.rule('xml') */ + { + test: /\\\\.xml$/, + use: [ + /* config.module.rule('xml').use('xml-namespace-loader') */ + { + loader: 'xml-namespace-loader' + } + ] + } + ] + }, + optimization: { + splitChunks: { + cacheGroups: { + defaultVendor: { + test: /[\\\\\\\\/]node_modules[\\\\\\\\/]/, + priority: -10, + name: 'vendor', + chunks: 'all' + } + } + }, + minimizer: [ + /* config.optimization.minimizer('TerserPlugin') */ + new TerserPlugin( + { + terserOptions: { + compress: { + collapse_vars: false, + sequences: false + }, + keep_fnames: true + } + } + ) + ] + }, + plugins: [ + /* config.plugin('ForkTsCheckerWebpackPlugin') */ + new ForkTsCheckerWebpackPlugin( + { + typescript: { + memoryLimit: 4096 + } + } + ), + /* config.plugin('CleanWebpackPlugin') */ + new CleanWebpackPlugin( + { + cleanOnceBeforeBuildPatterns: [ + '__jest__/platforms/android/app/src/main/assets/app/**/*' + ], + verbose: false + } + ), + /* config.plugin('DefinePlugin') */ + new DefinePlugin( + { + __DEV__: true, + __NS_WEBPACK__: true, + __CSS_PARSER__: '\\"css-tree\\"', + __ANDROID__: true, + __IOS__: false, + 'global.isAndroid': true, + 'global.isIOS': false, + process: 'global.process' + } + ), + /* config.plugin('CopyWebpackPlugin') */ + new CopyPlugin( + { + patterns: [ + { + from: 'assets/**', + context: '__jest__/src', + noErrorOnMissing: true, + globOptions: { + dot: false + } + }, + { + from: 'fonts/**', + context: '__jest__/src', + noErrorOnMissing: true, + globOptions: { + dot: false + } + }, + { + from: '**/*.+(jpg|png)', + context: '__jest__/src', + noErrorOnMissing: true, + globOptions: { + dot: false + } + } + ] + } + ), + /* config.plugin('WatchStatePlugin') */ + new WatchStatePlugin(), + /* config.plugin('VirtualModulesPlugin') */ + new VirtualModulesPlugin( + { + '__jest__/src/__virtual_entry__.js': 'require(\\\\'@nativescript/core/bundle-entry-points\\\\')\\\\nconst context = require.context(\\"~/\\", /* deep: */ true, /* filter: */ /.(xml|js)$/);\\\\nglobal.registerWebpackModules(context);' + } + ) + ], + entry: { + bundle: [ + '@nativescript/core/globals/index.js', + '__jest__/src/app.js', + '__jest__/src/__virtual_entry__.js' + ] + } +}" +`; + +exports[`javascript configuration for ios 1`] = ` +"{ + mode: 'development', + externals: [ + 'package.json', + '~/package.json' + ], + devtool: 'inline-source-map', + target: 'node', + output: { + path: '__jest__/platforms/ios/__jest__/app', + pathinfo: false, + publicPath: '', + libraryTarget: 'commonjs', + globalObject: 'global' + }, + resolve: { + symlinks: true, + alias: { + '~': '__jest__/src', + '@': '__jest__/src' + }, + extensions: [ + '.ios.ts', + '.ts', + '.ios.js', + '.js', + '.ios.css', + '.css', + '.ios.scss', + '.scss', + '.ios.json', + '.json' + ] + }, + resolveLoader: { + modules: [ + 'node_modules/@nativescript/webpack/dist/loaders', + 'node_modules' + ] + }, + module: { + rules: [ + /* config.module.rule('ts') */ + { + test: [ + /\\\\.ts$/ + ], + use: [ + /* config.module.rule('ts').use('ts-loader') */ + { + loader: 'ts-loader', + options: { + transpileOnly: true, + allowTsInNodeModules: true, + compilerOptions: { + sourceMap: true, + declaration: false + }, + getCustomTransformers: function () { /* omitted long function */ } + } + } + ] + }, + /* config.module.rule('js') */ + { + test: /\\\\.js$/, + exclude: [ + /node_modules/ + ], + use: [ + /* config.module.rule('js').use('babel-loader') */ + { + loader: 'babel-loader', + options: { + generatorOpts: { + compact: false + } + } + } + ] + }, + /* config.module.rule('css') */ + { + test: /\\\\.css$/, + use: [ + /* config.module.rule('css').use('apply-css-loader') */ + { + loader: 'apply-css-loader' + }, + /* config.module.rule('css').use('css2json-loader') */ + { + loader: 'css2json-loader' + } + ] + }, + /* config.module.rule('scss') */ + { + test: /\\\\.scss$/, + use: [ + /* config.module.rule('scss').use('apply-css-loader') */ + { + loader: 'apply-css-loader' + }, + /* config.module.rule('scss').use('css2json-loader') */ + { + loader: 'css2json-loader' + }, + /* config.module.rule('scss').use('sass-loader') */ + { + loader: 'sass-loader' + } + ] + }, + /* config.module.rule('xml') */ + { + test: /\\\\.xml$/, + use: [ + /* config.module.rule('xml').use('xml-namespace-loader') */ + { + loader: 'xml-namespace-loader' + } + ] + } + ] + }, + optimization: { + splitChunks: { + cacheGroups: { + defaultVendor: { + test: /[\\\\\\\\/]node_modules[\\\\\\\\/]/, + priority: -10, + name: 'vendor', + chunks: 'all' + } + } + }, + minimizer: [ + /* config.optimization.minimizer('TerserPlugin') */ + new TerserPlugin( + { + terserOptions: { + compress: { + collapse_vars: true, + sequences: true + }, + keep_fnames: true + } + } + ) + ] + }, + plugins: [ + /* config.plugin('ForkTsCheckerWebpackPlugin') */ + new ForkTsCheckerWebpackPlugin( + { + typescript: { + memoryLimit: 4096 + } + } + ), + /* config.plugin('CleanWebpackPlugin') */ + new CleanWebpackPlugin( + { + cleanOnceBeforeBuildPatterns: [ + '__jest__/platforms/ios/__jest__/app/**/*' + ], + verbose: false + } + ), + /* config.plugin('DefinePlugin') */ + new DefinePlugin( + { + __DEV__: true, + __NS_WEBPACK__: true, + __CSS_PARSER__: '\\"css-tree\\"', + __ANDROID__: false, + __IOS__: true, + 'global.isAndroid': false, + 'global.isIOS': true, + process: 'global.process' + } + ), + /* config.plugin('CopyWebpackPlugin') */ + new CopyPlugin( + { + patterns: [ + { + from: 'assets/**', + context: '__jest__/src', + noErrorOnMissing: true, + globOptions: { + dot: false + } + }, + { + from: 'fonts/**', + context: '__jest__/src', + noErrorOnMissing: true, + globOptions: { + dot: false + } + }, + { + from: '**/*.+(jpg|png)', + context: '__jest__/src', + noErrorOnMissing: true, + globOptions: { + dot: false + } + } + ] + } + ), + /* config.plugin('WatchStatePlugin') */ + new WatchStatePlugin(), + /* config.plugin('VirtualModulesPlugin') */ + new VirtualModulesPlugin( + { + '__jest__/src/__virtual_entry__.js': 'require(\\\\'@nativescript/core/bundle-entry-points\\\\')\\\\nconst context = require.context(\\"~/\\", /* deep: */ true, /* filter: */ /.(xml|js)$/);\\\\nglobal.registerWebpackModules(context);' + } + ) + ], + entry: { + bundle: [ + '@nativescript/core/globals/index.js', + '__jest__/src/app.js', + '__jest__/src/__virtual_entry__.js' + ], + 'tns_modules/@nativescript/core/inspector_modules': [ + '@nativescript/core/inspector_modules' + ] + } +}" +`; diff --git a/packages/webpack5/__tests__/configuration/__snapshots__/react.spec.ts.snap b/packages/webpack5/__tests__/configuration/__snapshots__/react.spec.ts.snap index 6b2b24480..1f3045790 100644 --- a/packages/webpack5/__tests__/configuration/__snapshots__/react.spec.ts.snap +++ b/packages/webpack5/__tests__/configuration/__snapshots__/react.spec.ts.snap @@ -19,8 +19,8 @@ exports[`react configuration > android > adds ReactRefreshWebpackPlugin when HMR resolve: { symlinks: true, alias: { - '~': 'appFullPath', - '@': 'appFullPath', + '~': '__jest__/src', + '@': '__jest__/src', 'react-dom': 'react-nativescript' }, extensions: [ @@ -263,8 +263,8 @@ exports[`react configuration > android > base config 1`] = ` resolve: { symlinks: true, alias: { - '~': 'appFullPath', - '@': 'appFullPath', + '~': '__jest__/src', + '@': '__jest__/src', 'react-dom': 'react-nativescript' }, extensions: [ @@ -485,8 +485,8 @@ exports[`react configuration > ios > adds ReactRefreshWebpackPlugin when HMR ena resolve: { symlinks: true, alias: { - '~': 'appFullPath', - '@': 'appFullPath', + '~': '__jest__/src', + '@': '__jest__/src', 'react-dom': 'react-nativescript' }, extensions: [ @@ -732,8 +732,8 @@ exports[`react configuration > ios > base config 1`] = ` resolve: { symlinks: true, alias: { - '~': 'appFullPath', - '@': 'appFullPath', + '~': '__jest__/src', + '@': '__jest__/src', 'react-dom': 'react-nativescript' }, extensions: [ diff --git a/packages/webpack5/__tests__/configuration/__snapshots__/svelte.spec.ts.snap b/packages/webpack5/__tests__/configuration/__snapshots__/svelte.spec.ts.snap index 9ada8af46..7c6911b64 100644 --- a/packages/webpack5/__tests__/configuration/__snapshots__/svelte.spec.ts.snap +++ b/packages/webpack5/__tests__/configuration/__snapshots__/svelte.spec.ts.snap @@ -19,8 +19,8 @@ exports[`svelte configuration for android 1`] = ` resolve: { symlinks: true, alias: { - '~': 'appFullPath', - '@': 'appFullPath' + '~': '__jest__/src', + '@': '__jest__/src' }, extensions: [ '.android.svelte', @@ -265,8 +265,8 @@ exports[`svelte configuration for ios 1`] = ` resolve: { symlinks: true, alias: { - '~': 'appFullPath', - '@': 'appFullPath' + '~': '__jest__/src', + '@': '__jest__/src' }, extensions: [ '.ios.svelte', diff --git a/packages/webpack5/__tests__/configuration/__snapshots__/vue.spec.ts.snap b/packages/webpack5/__tests__/configuration/__snapshots__/vue.spec.ts.snap index dfe35ed2d..e0498ffb8 100644 --- a/packages/webpack5/__tests__/configuration/__snapshots__/vue.spec.ts.snap +++ b/packages/webpack5/__tests__/configuration/__snapshots__/vue.spec.ts.snap @@ -19,8 +19,8 @@ exports[`vue configuration for android 1`] = ` resolve: { symlinks: true, alias: { - '~': 'appFullPath', - '@': 'appFullPath', + '~': '__jest__/src', + '@': '__jest__/src', vue: 'nativescript-vue' }, extensions: [ @@ -267,8 +267,8 @@ exports[`vue configuration for ios 1`] = ` resolve: { symlinks: true, alias: { - '~': 'appFullPath', - '@': 'appFullPath', + '~': '__jest__/src', + '@': '__jest__/src', vue: 'nativescript-vue' }, extensions: [ diff --git a/packages/webpack5/__tests__/configuration/javascript.spec.ts b/packages/webpack5/__tests__/configuration/javascript.spec.ts new file mode 100644 index 000000000..76a2c6201 --- /dev/null +++ b/packages/webpack5/__tests__/configuration/javascript.spec.ts @@ -0,0 +1,17 @@ +// @ts-ignore +import Config from 'webpack-chain'; +import javascript from '../../src/configuration/javascript'; +import { init } from '../../src'; + +describe.only('javascript configuration', () => { + const platforms = ['ios', 'android']; + + for (let platform of platforms) { + it(`for ${platform}`, () => { + init({ + [platform]: true, + }); + expect(javascript(new Config()).toString()).toMatchSnapshot(); + }); + } +}); diff --git a/packages/webpack5/package.json b/packages/webpack5/package.json index 2e25ad6c3..17ac378c8 100644 --- a/packages/webpack5/package.json +++ b/packages/webpack5/package.json @@ -29,6 +29,7 @@ "css-loader": "^5.0.1", "fork-ts-checker-webpack-plugin": "^6.0.3", "loader-utils": "^2.0.0", + "micromatch": "^4.0.2", "raw-loader": "^4.0.2", "react-refresh": "^0.9.0", "sass": "^1.29.0", @@ -52,7 +53,9 @@ "@types/css": "^0.0.31", "@types/jest": "^26.0.15", "@types/loader-utils": "^2.0.1", + "@types/micromatch": "^4.0.1", "@types/terser-webpack-plugin": "^5.0.2", + "@types/webpack-virtual-modules": "^0.1.0", "jest": "^26.6.3", "memfs": "^3.2.0", "nativescript-vue-template-compiler": "^2.8.2", diff --git a/packages/webpack5/src/configuration/base.ts b/packages/webpack5/src/configuration/base.ts index 95380ec3a..189624337 100644 --- a/packages/webpack5/src/configuration/base.ts +++ b/packages/webpack5/src/configuration/base.ts @@ -13,6 +13,7 @@ import { WatchStatePlugin } from '../plugins/WatchStatePlugin'; import { IWebpackEnv } from '../index'; import { getAbsoluteDistPath, + getEntryDirPath, getEntryPath, getPlatform, } from '../helpers/project'; @@ -106,9 +107,7 @@ export default function (config: Config, env: IWebpackEnv): Config { .add('.json'); // base aliases - config.resolve.alias - .set('~', 'appFullPath') - .set('@', 'appFullPath'); + config.resolve.alias.set('~', getEntryDirPath()).set('@', getEntryDirPath()); // resolve symlinks config.resolve.symlinks(true); diff --git a/packages/webpack5/src/configuration/javascript.ts b/packages/webpack5/src/configuration/javascript.ts index affb354bb..7a87891c0 100644 --- a/packages/webpack5/src/configuration/javascript.ts +++ b/packages/webpack5/src/configuration/javascript.ts @@ -1,16 +1,17 @@ import VirtualModulesPlugin from 'webpack-virtual-modules'; import Config from 'webpack-chain'; - -import { getEntryPath } from '../helpers/project'; -import { IWebpackEnv } from '../index'; -import base from './base'; import dedent from 'ts-dedent'; +import { join } from 'path'; -// todo: add base configuration for core with javascript -export default function (config: Config, env: IWebpackEnv): Config { +import { env as _env, IWebpackEnv } from '../index'; +import { getEntryDirPath } from '../helpers/project'; +import base from './base'; + +export default function (config: Config, env: IWebpackEnv = _env): Config { base(config, env); - const virtualEntryPath = getEntryPath() + '.virtual.js'; + const virtualEntryPath = join(getEntryDirPath(), '__virtual_entry__.js'); + const filterRE = '/.(xml|js|s?css)$/'; config.entry('bundle').add(virtualEntryPath); @@ -18,11 +19,10 @@ export default function (config: Config, env: IWebpackEnv): Config { config.plugin('VirtualModulesPlugin').use(VirtualModulesPlugin, [ { [virtualEntryPath]: dedent` - require('@nativescript/core/bundle-entry-points') - - const context = require.context("./", /* deep: */ true); - global.registerWebpackModules(context); - `, + require('@nativescript/core/bundle-entry-points') + const context = require.context("~/", /* deep: */ true, /* filter: */ ${filterRE}); + global.registerWebpackModules(context); + `, }, ]); diff --git a/packages/webpack5/src/helpers/project.ts b/packages/webpack5/src/helpers/project.ts index a0404b19c..104ff7bae 100644 --- a/packages/webpack5/src/helpers/project.ts +++ b/packages/webpack5/src/helpers/project.ts @@ -1,5 +1,5 @@ import { env, Platform } from '../index'; -import { resolve, basename } from 'path'; +import { resolve, basename, dirname } from 'path'; import { error } from './log'; export function getProjectRootPath(): string { @@ -19,6 +19,10 @@ export function getEntryPath() { return resolve(getProjectRootPath(), packageJson.main); } +export function getEntryDirPath() { + return dirname(getEntryPath()); +} + export function getDistPath() { if (env.ios) { const appName = basename(getProjectRootPath());