diff --git a/packages/webpack5/__tests__/configuration/__snapshots__/vue.spec.ts.snap b/packages/webpack5/__tests__/configuration/__snapshots__/vue.spec.ts.snap index 895a1f62b..2031cef28 100644 --- a/packages/webpack5/__tests__/configuration/__snapshots__/vue.spec.ts.snap +++ b/packages/webpack5/__tests__/configuration/__snapshots__/vue.spec.ts.snap @@ -1,47 +1,136 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`vue configuration works 1`] = ` -Object { - "entry": Object { - "": Array [], - }, - "module": Object { - "rules": Array [ - Object { - "test": /\\\\\\.vue\\$/, - "use": Array [ - Object { - "loader": "vue-loader", - "options": Object { - "compiler": "nativescript-vue-template-compiler", - }, - }, - ], - }, - Object { - "use": Array [ - Object { - "loader": "ts-loader", - "options": Object { - "appendTsSuffixTo": Array [ - /\\\\\\.vue\\$/, - ], - }, - }, - ], - }, - ], - }, - "plugins": Array [ - VueLoaderPlugin {}, - ], - "resolve": Object { - "alias": Object { - "vue": "nativescript-vue", +exports[`vue configuration [android] works 1`] = ` +"{ + resolve: { + symlinks: true, + alias: { + '~/package.json': 'package.json', + '~': 'appFullPath', + '@': 'appFullPath', + vue: 'nativescript-vue' }, - "extensions": Array [ - ".vue", - ], + extensions: [ + '.vue' + ] }, -} + module: { + rules: [ + /* config.module.rule('vue') */ + { + test: /\\\\.vue$/, + use: [ + /* config.module.rule('vue').use('vue-loader') */ + { + loader: 'vue-loader', + options: { + compiler: 'nativescript-vue-template-compiler' + } + } + ] + }, + /* config.module.rule('ts') */ + { + use: [ + /* config.module.rule('ts').use('ts-loader') */ + { + loader: 'ts-loader', + options: { + appendTsSuffixTo: [ + /\\\\.vue$/ + ] + } + } + ] + } + ] + }, + plugins: [ + /* config.plugin('clean') */ + new CleanWebpackPlugin( + { + cleanOnceBeforeBuildPatterns: [ + 'platforms/android/app/src/main/assets/app/**/*' + ], + verbose: true + } + ), + /* config.plugin('vue-plugin') */ + new VueLoaderPlugin() + ], + entry: { + bundle: [ + 'todo/main' + ] + } +}" +`; + +exports[`vue configuration [ios] works 1`] = ` +"{ + resolve: { + symlinks: true, + alias: { + '~/package.json': 'package.json', + '~': 'appFullPath', + '@': 'appFullPath', + vue: 'nativescript-vue' + }, + extensions: [ + '.vue' + ] + }, + module: { + rules: [ + /* config.module.rule('vue') */ + { + test: /\\\\.vue$/, + use: [ + /* config.module.rule('vue').use('vue-loader') */ + { + loader: 'vue-loader', + options: { + compiler: 'nativescript-vue-template-compiler' + } + } + ] + }, + /* config.module.rule('ts') */ + { + use: [ + /* config.module.rule('ts').use('ts-loader') */ + { + loader: 'ts-loader', + options: { + appendTsSuffixTo: [ + /\\\\.vue$/ + ] + } + } + ] + } + ] + }, + plugins: [ + /* config.plugin('clean') */ + new CleanWebpackPlugin( + { + cleanOnceBeforeBuildPatterns: [ + 'platforms/ios/[todo]/app/**/*' + ], + verbose: true + } + ), + /* config.plugin('vue-plugin') */ + new VueLoaderPlugin() + ], + entry: { + inspector_modules: [ + 'tns_modules/@nativescript/core/inspector_modules' + ], + bundle: [ + 'todo/main' + ] + } +}" `; diff --git a/packages/webpack5/__tests__/configuration/vue.spec.ts b/packages/webpack5/__tests__/configuration/vue.spec.ts index 9e1ce57d5..4f69ecff4 100644 --- a/packages/webpack5/__tests__/configuration/vue.spec.ts +++ b/packages/webpack5/__tests__/configuration/vue.spec.ts @@ -1,7 +1,15 @@ -import { vueConfig } from '@nativescript/webpack'; +import { __vue } from '@nativescript/webpack'; describe('vue configuration', () => { - it('works', () => { - expect(vueConfig('')).toMatchSnapshot(); - }); + const platforms = ['ios', 'android']; + + for (let platform of platforms) { + it(`[${platform}] works`, () => { + expect( + __vue({ + [platform]: true, + }).toString() + ).toMatchSnapshot(); + }); + } }); diff --git a/packages/webpack5/package.json b/packages/webpack5/package.json index 96fa4751b..7a8f2cf23 100644 --- a/packages/webpack5/package.json +++ b/packages/webpack5/package.json @@ -16,6 +16,7 @@ "webpack": "^5.4.0" }, "dependencies": { + "clean-webpack-plugin": "^3.0.0", "vue-loader": "^15.9.5", "webpack-chain": "^6.5.1" } diff --git a/packages/webpack5/src/configuration/base.ts b/packages/webpack5/src/configuration/base.ts index afe6cb4c6..bd20179c9 100644 --- a/packages/webpack5/src/configuration/base.ts +++ b/packages/webpack5/src/configuration/base.ts @@ -1,9 +1,52 @@ import Config from 'webpack-chain'; -import { IWebpackEnv } from './index'; +import { IWebpackEnv, WebpackPlatform } from './index'; +import { CleanWebpackPlugin } from 'clean-webpack-plugin'; +import { getDistPath } from '../helpers/projectHelpers'; // todo: add base configuration that's shared across all flavors export default function (env: IWebpackEnv): Config { const config = new Config(); - config.entry(''); + const distPath = getDistPath(env); + + // inspector_modules + config.when(shouldIncludeInspectorModules(env), (config) => { + config.entry('inspector_modules').add('tns_modules/@nativescript/core/inspector_modules').end(); + }); + + config.entry('bundle').add('todo/main').end(); + + // base aliases + config.resolve.alias.set('~/package.json', 'package.json').set('~', 'appFullPath').set('@', 'appFullPath'); + + // resolve symlinks + config.resolve.symlinks(true); + + // items to clean + config.plugin('clean').use(CleanWebpackPlugin, [ + { + cleanOnceBeforeBuildPatterns: [`${distPath}/**/*`], + verbose: true, + }, + ]); + return config; } + +function shouldIncludeInspectorModules(env: IWebpackEnv): boolean { + const platform = determinePlatformFromEnv(env); + // todo: check if core modules are external + // todo: check if we are testing + return platform === WebpackPlatform.ios; +} + +function determinePlatformFromEnv(env: IWebpackEnv): WebpackPlatform { + if (env?.android) { + return WebpackPlatform.android; + } + + if (env?.ios) { + return WebpackPlatform.ios; + } + + throw new Error('You need to provide a target platform!'); +} diff --git a/packages/webpack5/src/configuration/index.ts b/packages/webpack5/src/configuration/index.ts index 630a3cb7d..f53b4be2c 100644 --- a/packages/webpack5/src/configuration/index.ts +++ b/packages/webpack5/src/configuration/index.ts @@ -7,19 +7,36 @@ import svelte from './svelte'; import typescript from './typescript'; import vue from './vue'; +// export chain configs +// todo: rename if needed +export { base as __base, angular as __angular, javascript as __javascript, react as __react, svelte as __svelte, typescript as __typescript, vue as __vue }; + // export final configs -// todo: perhaps we can export chain configs as well +export const baseConfig = (env: IWebpackEnv) => base(env).toConfig(); -export const baseConfig = (env) => base(env).toConfig(); - -export const angularConfig = (env) => angular(env).toConfig(); -export const javascriptConfig = (env) => javascript(env).toConfig(); -export const reactConfig = (env) => react(env).toConfig(); -export const svelteConfig = (env) => svelte(env).toConfig(); -export const typescriptConfig = (env) => typescript(env).toConfig(); -export const vueConfig = (env) => vue(env).toConfig(); +export const angularConfig = (env: IWebpackEnv) => angular(env).toConfig(); +export const javascriptConfig = (env: IWebpackEnv) => javascript(env).toConfig(); +export const reactConfig = (env: IWebpackEnv) => react(env).toConfig(); +export const svelteConfig = (env: IWebpackEnv) => svelte(env).toConfig(); +export const typescriptConfig = (env: IWebpackEnv) => typescript(env).toConfig(); +export const vueConfig = (env: IWebpackEnv) => vue(env).toConfig(); export interface IWebpackEnv { - hmr: boolean; + [name: string]: any; + + appPath?: string; + appResourcesPath?: string; + + android?: boolean; + ios?: boolean; + + production?: boolean; + report?: boolean; + hmr?: boolean; // todo: add others } + +export enum WebpackPlatform { + 'ios', + 'android', +} diff --git a/packages/webpack5/src/helpers/projectHelpers.ts b/packages/webpack5/src/helpers/projectHelpers.ts index 1a13d3f8f..1b1ca17ba 100644 --- a/packages/webpack5/src/helpers/projectHelpers.ts +++ b/packages/webpack5/src/helpers/projectHelpers.ts @@ -1,27 +1,40 @@ +import { existsSync } from 'fs'; +import { resolve } from 'path'; +import { IWebpackEnv } from '@nativescript/webpack'; -import { existsSync } from "fs"; -import { resolve } from "path"; +export function getDistPath(env: IWebpackEnv) { + if (env.ios) { + return `platforms/ios/[todo]/app`; + } + + if (env.android) { + return `platforms/android/app/src/main/assets/app`; + } + + // todo: additional platforms + // perhaps we could combine platform specifics into "plugins" + // 3rd party platforms would be treated the same +} export function getPackageJson(projectDir: string) { - const packageJsonPath = getPackageJsonPath(projectDir); - const result = readJsonFile(packageJsonPath); + const packageJsonPath = getPackageJsonPath(projectDir); + const result = readJsonFile(packageJsonPath); - return result; + return result; } -export function readJsonFile(filePath:string) { - return require(filePath) as { - main:string - // to be extended? - }; +export function readJsonFile(filePath: string) { + return require(filePath) as { + main: string; + // to be extended? + }; } -export function getPackageJsonPath (projectDir: string) { - const packagePath = resolve(projectDir, "package.json"); - if (existsSync(packagePath)) { - return packagePath; - } else { - return getPackageJsonPath(resolve(projectDir, '..')); - } - - } \ No newline at end of file +export function getPackageJsonPath(projectDir: string) { + const packagePath = resolve(projectDir, 'package.json'); + if (existsSync(packagePath)) { + return packagePath; + } else { + return getPackageJsonPath(resolve(projectDir, '..')); + } +}