diff --git a/.gitignore b/.gitignore index cee7d177..8f8de90d 100644 --- a/.gitignore +++ b/.gitignore @@ -2,34 +2,34 @@ node_modules *.tgz package-lock.json +*.js.map plugins/NativeScriptAngularCompilerPlugin.d.ts plugins/NativeScriptAngularCompilerPlugin.js -plugins/NativeScriptAngularCompilerPlugin.js.map transformers/*.d.ts transformers/*.js -transformers/*.js.map utils/*.d.ts utils/*.js -utils/*.js.map + +hmr/*.d.ts +hmr/*.js plugins/PlatformFSPlugin.d.ts plugins/PlatformFSPlugin.js -plugins/PlatformFSPlugin.js.map plugins/WatchStateLoggerPlugin.d.ts plugins/WatchStateLoggerPlugin.js -plugins/WatchStateLoggerPlugin.js.map host/resolver.d.ts host/resolver.js -host/resolver.js.map jasmine-config/reporter.d.ts jasmine-config/reporter.js -jasmine-config/reporter.js.map + +bundle-config-loader.d.ts +bundle-config-loader.js **/*.spec.js* **/*.spec.d.ts* diff --git a/.vscode/launch.json b/.vscode/launch.json index d77d2b08..3cd1efa9 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -19,6 +19,16 @@ "args": [ "--env.android", "--env.aot" ], "runtimeArgs": [ "--preserve-symlinks" ], "stopOnEntry": true, + }, + { + "type": "node", + "request": "launch", + "name": "TypeScriptApp Webpack", + "cwd": "${workspaceFolder}/demo/TypeScriptApp", + "program": "${workspaceFolder}/demo/TypeScriptApp/node_modules/.bin/webpack", + "args": [ "--env.android" ], + "stopOnEntry": true, + "preLaunchTask": "npm:tsc" } ] } \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 00000000..79199e22 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,13 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=733558 + // for the documentation about the tasks.json format + "version": "2.0.0", + "tasks": [ + { + "label":"npm:tsc", + "type": "npm", + "script": "tsc", + "problemMatcher": [] + } + ] +} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index c06f845e..3336338e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,43 @@ + +# [1.0.0](https://github.com/NativeScript/nativescript-dev-webpack/compare/0.24.1...1.0.0) (2019-07-10) + + +### Bug Fixes + +* allow overriding the `global.process` object from both the app and the plugins ([8c4292e](https://github.com/NativeScript/nativescript-dev-webpack/commit/8c4292e)) +* auto accept new or deleted files ([#972](https://github.com/NativeScript/nativescript-dev-webpack/issues/972)) ([bd893ce](https://github.com/NativeScript/nativescript-dev-webpack/commit/bd893ce)) +* avoid generating invalid JavaScript when merging IIFE files ([7586d4c](https://github.com/NativeScript/nativescript-dev-webpack/commit/7586d4c)) +* create PropertyAssignment instead of string literal (Identifier) when modifying the NgModule - in some cases (e.g. when there is a decomposition in another NgModule property), the TypeScipt program is trying to read `node.name.kind` on each property causing an exception for Identifiers) ([a70fb3b](https://github.com/NativeScript/nativescript-dev-webpack/commit/a70fb3b)) +* do not add inspector_modules entry when core modules are an external module ([e0cd8c1](https://github.com/NativeScript/nativescript-dev-webpack/commit/e0cd8c1)) +* do not show warning for format differences in templates ([#947](https://github.com/NativeScript/nativescript-dev-webpack/issues/947)) ([a352064](https://github.com/NativeScript/nativescript-dev-webpack/commit/a352064)) +* don't restart application when lazy loaded code is changed in angular app with uglify option ([121c3b2](https://github.com/NativeScript/nativescript-dev-webpack/commit/121c3b2)) +* emit inspector_modules as a module ([be2a5a6](https://github.com/NativeScript/nativescript-dev-webpack/commit/be2a5a6)) +* fix app.css file path on windows machines ([7d734d8](https://github.com/NativeScript/nativescript-dev-webpack/commit/7d734d8)) +* fix hmr for platform specific files in linked plugins ([#946](https://github.com/NativeScript/nativescript-dev-webpack/issues/946)) ([9e8c921](https://github.com/NativeScript/nativescript-dev-webpack/commit/9e8c921)) +* follow the symlinks in JavaScript apps ([#941](https://github.com/NativeScript/nativescript-dev-webpack/issues/941)) ([f0c62fb](https://github.com/NativeScript/nativescript-dev-webpack/commit/f0c62fb)) +* hmr should work with uglify ([#953](https://github.com/NativeScript/nativescript-dev-webpack/issues/953)) ([874e4f8](https://github.com/NativeScript/nativescript-dev-webpack/commit/874e4f8)) +* **xml-ns-loader:** remove wrong register of xml ([#940](https://github.com/NativeScript/nativescript-dev-webpack/issues/940)) ([bc2f6f1](https://github.com/NativeScript/nativescript-dev-webpack/commit/bc2f6f1)) +* inject app.css file from unit-test-runner on test command ([#949](https://github.com/NativeScript/nativescript-dev-webpack/issues/949)) ([a216ed3](https://github.com/NativeScript/nativescript-dev-webpack/commit/a216ed3)) +* log the real snapshot tool error by trying to evaluate the input file script ([1a9c4b2](https://github.com/NativeScript/nativescript-dev-webpack/commit/1a9c4b2)) +* migrate demo apps to android x ([c2d6684](https://github.com/NativeScript/nativescript-dev-webpack/commit/c2d6684)) +* unify the entry points handling and enable custom applications in android ([de10041](https://github.com/NativeScript/nativescript-dev-webpack/commit/de10041)) +* **hooks:** improve hooks handling ([#961](https://github.com/NativeScript/nativescript-dev-webpack/issues/961)) ([f558607](https://github.com/NativeScript/nativescript-dev-webpack/commit/f558607)) + +### Features + +* introduce webpack only workflow ([#882](https://github.com/NativeScript/nativescript-dev-webpack/issues/882)) ([2de4c68](https://github.com/NativeScript/nativescript-dev-webpack/commit/2de4c68)) +* no need of "page" suffix ([#966](https://github.com/NativeScript/nativescript-dev-webpack/pull/966)) ([d4a8dec](https://github.com/NativeScript/nativescript-dev-webpack/commit/d4a8dec803acf39b7cdeb4f3bc8c23284046fe67)) +* support for file qualifiers ([#966](https://github.com/NativeScript/nativescript-dev-webpack/pull/966)) ([d4a8dec](https://github.com/NativeScript/nativescript-dev-webpack/commit/d4a8dec803acf39b7cdeb4f3bc8c23284046fe67)) +* universal hmr loader ([#966](https://github.com/NativeScript/nativescript-dev-webpack/pull/966)) ([d4a8dec](https://github.com/NativeScript/nativescript-dev-webpack/commit/d4a8dec803acf39b7cdeb4f3bc8c23284046fe67)) + +### BREAKING CHANGES: + +* the file names of the NativeScript pages are not required to end with `-page` or `-root`. All `xml`, `css`, `js`, `ts` and `scss` files are not included in the bundle. + +* the plugin is not working with NativeScript CLI older than 6.0.0 (`nativescript@6.0.0`). + +* the Webpack mode it set to `production` based on the `--release` flag of the NativeScript CLI, instead of the `--env.uglify` one. + ## [0.24.1](https://github.com/NativeScript/nativescript-dev-webpack/compare/0.24.0...0.24.1) (2019-06-06) diff --git a/bundle-config-loader.js b/bundle-config-loader.ts similarity index 60% rename from bundle-config-loader.js rename to bundle-config-loader.ts index 4daa915b..f1f0458a 100644 --- a/bundle-config-loader.js +++ b/bundle-config-loader.ts @@ -1,8 +1,29 @@ -const unitTestingConfigLoader = require("./unit-testing-config-loader"); +import * as unitTestingConfigLoader from "./unit-testing-config-loader"; +import { loader } from "webpack"; +import { getOptions } from "loader-utils"; +import * as escapeRegExp from "escape-string-regexp"; -module.exports = function (source, map) { - this.cacheable(); - const { angular = false, loadCss = true, unitTesting, projectRoot, appFullPath, registerModules = /(root|page)\.(xml|css|js|ts|scss)$/ } = this.query; +// Matches all source, markup and style files that are not in App_Resources +const defaultMatch = "(? { + console.log("HMR: Accept module '" + context.id + "' from '" + module.id + "'"); + }); + } ${source} `; } @@ -68,3 +94,6 @@ module.exports = function (source, map) { this.callback(null, source, map); }; + + +export default loader; \ No newline at end of file diff --git a/demo/.gitignore b/demo/.gitignore index dcdcde1a..ee19ca4e 100644 --- a/demo/.gitignore +++ b/demo/.gitignore @@ -16,4 +16,5 @@ tsconfig.aot.json vendor.js vendor.ts -tsconfig.esm.json \ No newline at end of file +tsconfig.esm.json +mochawesome-report \ No newline at end of file diff --git a/demo/AngularApp/.vscode/launch.json b/demo/AngularApp/.vscode/launch.json index c8276a2a..4c86d32e 100644 --- a/demo/AngularApp/.vscode/launch.json +++ b/demo/AngularApp/.vscode/launch.json @@ -16,11 +16,8 @@ "999999", "--colors", "--opts", - "./e2e/config/mocha.opts", - "--runType", - "android23", - "--reuseDevice" - // "${workspaceFolder}/test" + "../config/mocha.opts", + "android" ], "internalConsoleOptions": "openOnSessionStart" }, diff --git a/demo/AngularApp/e2e/tests.e2e-spec.ts b/demo/AngularApp/e2e/tests.e2e-spec.ts index 47e67d10..aa8c75be 100644 --- a/demo/AngularApp/e2e/tests.e2e-spec.ts +++ b/demo/AngularApp/e2e/tests.e2e-spec.ts @@ -1,29 +1,14 @@ -import { AppiumDriver, createDriver, SearchOptions } from "nativescript-dev-appium"; +import { AppiumDriver, createDriver, nsCapabilities } from "nativescript-dev-appium"; import { assert } from "chai"; describe("sample scenario", async function () { let driver: AppiumDriver; before(async function () { + nsCapabilities.testReporter.context = this; driver = await createDriver(); }); - beforeEach(async function () { - try { - const items = await getItems(); - } catch (err) { - try { - const lblNinjas = await driver.findElementByText("Ninjas!"); - } - catch (err) { - console.log("Navigating to ninjas page ..."); - await driver.navBack(); - } - console.log("Navigating to main page ..."); - await driver.navBack(); - } - }); - afterEach(async function () { if (this.currentTest.state === "failed") { await driver.logTestArtifacts(this.currentTest.title); @@ -36,7 +21,7 @@ describe("sample scenario", async function () { }); it("should navigate to a ninja", async function () { - const btnNinjas = await driver.findElementByText("Ninjas"); + const btnNinjas = await driver.waitForElement("Ninjas"); await btnNinjas.click(); const itemMichaelangelo = await driver.findElementByText("Michaelangelo"); @@ -61,10 +46,10 @@ describe("sample scenario", async function () { for (let styleType in styleTypes) { it(`should find an element with ${styleType} style applied`, async function () { const element = await driver.findElementByText(styleTypes[styleType]); + driver.imageHelper.options.keepOriginalImageSize = false; + driver.imageHelper.options.isDeviceSpecific = false; const result = await driver.compareElement(element, "style"); assert.isTrue(result); }); } - - const getItems = async function () { return driver.isAndroid ? await driver.findElementsByText("(Android)") : await driver.findElementsByText("(ios)"); } }); diff --git a/demo/AngularApp/e2e/tsconfig.json b/demo/AngularApp/e2e/tsconfig.json index abb4a3a7..74d502ac 100644 --- a/demo/AngularApp/e2e/tsconfig.json +++ b/demo/AngularApp/e2e/tsconfig.json @@ -5,6 +5,7 @@ "experimentalDecorators": true, "emitDecoratorMetadata": true, "importHelpers": false, + "sourceMap": true, "types": [ "mocha", "chai", diff --git a/demo/AngularApp/webpack.config.js b/demo/AngularApp/webpack.config.js index 014685ff..9ad1ba8f 100644 --- a/demo/AngularApp/webpack.config.js +++ b/demo/AngularApp/webpack.config.js @@ -33,7 +33,6 @@ module.exports = env => { // Default destination inside platforms//... const dist = resolve(projectRoot, nsWebpack.getAppPath(platform, projectRoot)); - const appResourcesPlatformDir = platform === "android" ? "Android" : "iOS"; const { // The 'appPath' and 'appResourcesPath' values are fetched from @@ -110,6 +109,7 @@ module.exports = env => { itemsToClean.push(`${join(projectRoot, "platforms", "android", "app", "build", "configurations", "nativescript-android-snapshot")}`); } + nsWebpack.processAppComponents(appComponents, platform); const config = { mode: production ? "production" : "development", context: appFullPath, @@ -214,6 +214,7 @@ module.exports = env => { unitTesting, appFullPath, projectRoot, + ignoredFiles: nsWebpack.getUserDefinedEntries(entries, platform) } }, ].filter(loader => !!loader) diff --git a/demo/JavaScriptApp/e2e/config/appium.capabilities.json b/demo/JavaScriptApp/e2e/config/appium.capabilities.json deleted file mode 100644 index b4c9be76..00000000 --- a/demo/JavaScriptApp/e2e/config/appium.capabilities.json +++ /dev/null @@ -1,122 +0,0 @@ -{ - "android19": { - "platformName": "Android", - "platformVersion": "4.4", - "deviceName": "Emulator-Api19-Default", - "avd": "Emulator-Api19-Default", - "lt": 60000, - "newCommandTimeout": 720, - "noReset": false, - "fullReset": false, - "app": "" - }, - "android21": { - "platformName": "Android", - "platformVersion": "5.0", - "deviceName": "Emulator-Api21-Default", - "avd": "Emulator-Api21-Default", - "lt": 60000, - "newCommandTimeout": 720, - "noReset": false, - "fullReset": false, - "app": "" - }, - "android23": { - "platformName": "Android", - "platformVersion": "6.0", - "deviceName": "Emulator-Api23-Default", - "avd": "Emulator-Api23-Default", - "lt": 60000, - "newCommandTimeout": 720, - "noReset": false, - "fullReset": false, - "app": "" - }, - "android24": { - "platformName": "Android", - "platformVersion": "7.0", - "deviceName": "Emulator-Api24-Default", - "avd": "Emulator-Api24-Default", - "lt": 60000, - "newCommandTimeout": 720, - "noReset": false, - "fullReset": false, - "app": "" - }, - "android25": { - "platformName": "Android", - "platformVersion": "7.1", - "deviceName": "Emulator-Api25-Google", - "avd": "Emulator-Api25-Google", - "lt": 60000, - "newCommandTimeout": 720, - "noReset": false, - "fullReset": false, - "app": "" - }, - "android26": { - "platformName": "Android", - "platformVersion": "8.0", - "deviceName": "Emulator-Api26-Google", - "avd": "Emulator-Api26-Google", - "lt": 60000, - "newCommandTimeout": 720, - "noReset": false, - "fullReset": false, - "app": "" - }, - "android27": { - "platformName": "Android", - "platformVersion": "27", - "deviceName": "Emulator-Api27-Google", - "avd": "Emulator-Api27-Google", - "lt": 60000, - "newCommandTimeout": 720, - "noReset": false, - "fullReset": false, - "app": "" - }, - "android28": { - "platformName": "Android", - "platformVersion": "28", - "deviceName": "Emulator-Api28-Google", - "avd": "Emulator-Api28-Google", - "lt": 60000, - "newCommandTimeout": 720, - "noReset": false, - "fullReset": false, - "app": "" - }, - "sim.iPhone7": { - "platformName": "iOS", - "platformVersion": "/12.*/", - "deviceName": "iPhone 7", - "noReset": false, - "fullReset": false, - "app": "" - }, - "sim.iPhone8": { - "platformName": "iOS", - "platformVersion": "/12*/", - "deviceName": "iPhone 8", - "noReset": false, - "fullReset": false, - "app": "" - }, - "sim.iPhoneX": { - "platformName": "iOS", - "platformVersion": "/12*/", - "deviceName": "iPhone X", - "noReset": false, - "fullReset": false, - "app": "" - }, - "sim.iPhoneXS": { - "platformName": "ios", - "platformVersion": "/12*/", - "deviceName": "iPhone XS", - "noReset": false, - "fullReset": false, - "app": "" - } -} \ No newline at end of file diff --git a/demo/JavaScriptApp/e2e/tests.e2e-spec.js b/demo/JavaScriptApp/e2e/tests.e2e-spec.js index bd889360..43ea4512 100644 --- a/demo/JavaScriptApp/e2e/tests.e2e-spec.js +++ b/demo/JavaScriptApp/e2e/tests.e2e-spec.js @@ -9,16 +9,6 @@ describe("sample scenario", function () { driver = await nsAppium.createDriver(); })); - beforeEach(async function () { - try { - const lblPlatform = await getPlatformLabel(); - } - catch (err) { - console.log("Navigating to main page ..."); - await driver.navBack(); - } - }); - afterEach(async function () { if (this.currentTest.state === "failed") { await driver.logTestArtifacts(this.currentTest.title); @@ -53,12 +43,10 @@ describe("sample scenario", function () { it(`should find an element with ${styleType} style applied`, async function () { const element = await driver.findElementByText(styleTypes[styleType]); + driver.imageHelper.options.keepOriginalImageSize = false; + driver.imageHelper.options.isDeviceSpecific = false; const result = await driver.compareElement(element, "style"); - chai.assert.isTrue(result); + assert.isTrue(result); }); } - - const getPlatformLabel = async function() { - return driver.isAndroid ? await driver.findElementByText("android") : await driver.findElementByText("ios"); - } }); \ No newline at end of file diff --git a/demo/JavaScriptApp/webpack.config.js b/demo/JavaScriptApp/webpack.config.js index e285ce31..ddcf17ea 100644 --- a/demo/JavaScriptApp/webpack.config.js +++ b/demo/JavaScriptApp/webpack.config.js @@ -28,7 +28,6 @@ module.exports = env => { // Default destination inside platforms//... const dist = resolve(projectRoot, nsWebpack.getAppPath(platform, projectRoot)); - const appResourcesPlatformDir = platform === "android" ? "Android" : "iOS"; const { // The 'appPath' and 'appResourcesPath' values are fetched from @@ -70,6 +69,7 @@ module.exports = env => { itemsToClean.push(`${join(projectRoot, "platforms", "android", "app", "build", "configurations", "nativescript-android-snapshot")}`); } + nsWebpack.processAppComponents(appComponents, platform); const config = { mode: production ? "production" : "development", context: appFullPath, @@ -103,7 +103,7 @@ module.exports = env => { '~': appFullPath }, // don't resolve symlinks to symlinked modules - symlinks: false + symlinks: true }, resolveLoader: { // don't resolve symlinks to symlinked loaders @@ -174,24 +174,15 @@ module.exports = env => { unitTesting, appFullPath, projectRoot, + ignoredFiles: nsWebpack.getUserDefinedEntries(entries, platform) } }, ].filter(loader => !!loader) }, { - test: /-page\.js$/, - use: "nativescript-dev-webpack/script-hot-loader" - }, - - { - test: /\.(css|scss)$/, - use: "nativescript-dev-webpack/style-hot-loader" - }, - - { - test: /\.(html|xml)$/, - use: "nativescript-dev-webpack/markup-hot-loader" + test: /\.(js|css|scss|html|xml)$/, + use: "nativescript-dev-webpack/hmr/hot-loader" }, { test: /\.(html|xml)$/, use: "nativescript-dev-webpack/xml-namespace-loader" }, @@ -234,7 +225,7 @@ module.exports = env => { platforms, }), // Does IPC communication with the {N} CLI to notify events when running in watch mode. - new nsWebpack.WatchStateLoggerPlugin(), + new nsWebpack.WatchStateLoggerPlugin() ], }; diff --git a/demo/TypeScriptApp/.vscode/launch.json b/demo/TypeScriptApp/.vscode/launch.json index f0519850..60b22ed9 100644 --- a/demo/TypeScriptApp/.vscode/launch.json +++ b/demo/TypeScriptApp/.vscode/launch.json @@ -17,10 +17,7 @@ "--colors", "--opts", "./e2e/config/mocha.opts", - "--runType", - "android23", - "--reuseDevice" - // "${workspaceFolder}/test" + "-a" ], "internalConsoleOptions": "openOnSessionStart" }, diff --git a/demo/TypeScriptApp/e2e/config/appium.capabilities.json b/demo/TypeScriptApp/e2e/config/appium.capabilities.json deleted file mode 100644 index 3cd2bab2..00000000 --- a/demo/TypeScriptApp/e2e/config/appium.capabilities.json +++ /dev/null @@ -1,106 +0,0 @@ -{ - "android19": { - "platformName": "Android", - "platformVersion": "4.4", - "deviceName": "Emulator-Api19-Default", - "avd": "Emulator-Api19-Default", - "lt": 60000, - "appActivity": "com.tns.NativeScriptActivity", - "newCommandTimeout": 720, - "noReset": true, - "fullReset": false, - "app": "" - }, - "android21": { - "platformName": "Android", - "platformVersion": "5.0", - "deviceName": "Emulator-Api21-Default", - "avd": "Emulator-Api21-Default", - "lt": 60000, - "appActivity": "com.tns.NativeScriptActivity", - "newCommandTimeout": 720, - "noReset": true, - "fullReset": false, - "app": "" - }, - "android23": { - "platformName": "Android", - "platformVersion": "6.0", - "deviceName": "Emulator-Api23-Default", - "avd": "Emulator-Api23-Default", - "lt": 60000, - "appActivity": "com.tns.NativeScriptActivity", - "newCommandTimeout": 720, - "noReset": true, - "fullReset": false, - "app": "" - }, - "android24": { - "platformName": "Android", - "platformVersion": "7.0", - "deviceName": "Emulator-Api24-Default", - "avd": "Emulator-Api24-Default", - "lt": 60000, - "appActivity": "com.tns.NativeScriptActivity", - "newCommandTimeout": 720, - "noReset": true, - "fullReset": false, - "app": "" - }, - "android25": { - "platformName": "Android", - "platformVersion": "7.1", - "deviceName": "Emulator-Api25-Google", - "avd": "Emulator-Api25-Google", - "lt": 60000, - "appActivity": "com.tns.NativeScriptActivity", - "newCommandTimeout": 720, - "noReset": true, - "fullReset": false, - "app": "" - }, - "android26": { - "platformName": "Android", - "platformVersion": "8.0", - "deviceName": "Emulator-Api26-Google", - "avd": "Emulator-Api26-Google", - "lt": 60000, - "appActivity": "com.tns.NativeScriptActivity", - "newCommandTimeout": 720, - "noReset": true, - "fullReset": false, - "app": "" - }, - "sim.iPhone7.iOS100": { - "platformName": "iOS", - "platformVersion": "10.0", - "deviceName": "iPhone 7 100", - "noReset": true, - "fullReset": false, - "app": "" - }, - "sim.iPhone8.iOS110": { - "platformName": "iOS", - "platformVersion": "11.2", - "deviceName": "iPhone 8 110", - "noReset": true, - "fullReset": false, - "app": "" - }, - "sim.iPhoneX.iOS110": { - "platformName": "iOS", - "platformVersion": "11.2", - "deviceName": "iPhone X", - "noReset": true, - "fullReset": false, - "app": "" - }, - "sim.iPhoneX.iOS111": { - "platformName": "iOS", - "platformVersion": "11.1", - "deviceName": "iPhone X", - "noReset": true, - "fullReset": false, - "app": "" - } -} diff --git a/demo/TypeScriptApp/e2e/config/mocha.opts b/demo/TypeScriptApp/e2e/config/mocha.opts deleted file mode 100644 index c21dcca6..00000000 --- a/demo/TypeScriptApp/e2e/config/mocha.opts +++ /dev/null @@ -1,5 +0,0 @@ ---timeout 999999 ---recursive e2e ---reporter mochawesome ---reporter-options quiet=true,html=true,inline=true,autoOpen=true ---exit \ No newline at end of file diff --git a/demo/TypeScriptApp/e2e/tests.e2e-spec.ts b/demo/TypeScriptApp/e2e/tests.e2e-spec.ts index 37920f3c..3f549eff 100644 --- a/demo/TypeScriptApp/e2e/tests.e2e-spec.ts +++ b/demo/TypeScriptApp/e2e/tests.e2e-spec.ts @@ -9,19 +9,9 @@ describe("sample scenario", () => { driver = await createDriver(); }); - beforeEach(async function () { - try { - const lblPlatform = await getPlatformLabel(); - } catch (err) { - console.log("Navigating to main page ..."); - await driver.navBack(); - } - }); - afterEach(async function () { if (this.currentTest.state === "failed") { - await driver.logPageSource(this.currentTest.title); - await driver.logScreenshot(this.currentTest.title); + await driver.logTestArtifacts(this.currentTest.title); } }); @@ -33,7 +23,6 @@ describe("sample scenario", () => { it("should the button on second page work", async function () { const btnNav = await driver.findElementByText("btnNav"); await btnNav.tap(); - const secondPage = await driver.findElementByText("Second Page"); const btnZero = await driver.findElementByText("0"); await btnZero.tap(); @@ -64,10 +53,10 @@ describe("sample scenario", () => { for (let styleType in styleTypes) { it(`should find an element with ${styleType} style applied`, async function () { const element = await driver.findElementByText(styleTypes[styleType]); + driver.imageHelper.options.keepOriginalImageSize = false; + driver.imageHelper.options.isDeviceSpecific = false; const result = await driver.compareElement(element, "style"); assert.isTrue(result); }); } - - const getPlatformLabel = async function () { return driver.isAndroid ? await driver.findElementByText("android") : await driver.findElementByText("ios"); } }); \ No newline at end of file diff --git a/demo/TypeScriptApp/webpack.config.js b/demo/TypeScriptApp/webpack.config.js index 74dfb0dd..9bc21ca6 100644 --- a/demo/TypeScriptApp/webpack.config.js +++ b/demo/TypeScriptApp/webpack.config.js @@ -29,7 +29,6 @@ module.exports = env => { // Default destination inside platforms//... const dist = resolve(projectRoot, nsWebpack.getAppPath(platform, projectRoot)); - const appResourcesPlatformDir = platform === "android" ? "Android" : "iOS"; const { // The 'appPath' and 'appResourcesPath' values are fetched from @@ -74,6 +73,7 @@ module.exports = env => { itemsToClean.push(`${join(projectRoot, "platforms", "android", "app", "build", "configurations", "nativescript-android-snapshot")}`); } + nsWebpack.processAppComponents(appComponents, platform); const config = { mode: production ? "production" : "development", context: appFullPath, @@ -180,24 +180,15 @@ module.exports = env => { unitTesting, appFullPath, projectRoot, + ignoredFiles: nsWebpack.getUserDefinedEntries(entries, platform) } }, ].filter(loader => !!loader) }, { - test: /-page\.ts$/, - use: "nativescript-dev-webpack/script-hot-loader" - }, - - { - test: /\.(css|scss)$/, - use: "nativescript-dev-webpack/style-hot-loader" - }, - - { - test: /\.(html|xml)$/, - use: "nativescript-dev-webpack/markup-hot-loader" + test: /\.(ts|css|scss|html|xml)$/, + use: "nativescript-dev-webpack/hmr/hot-loader" }, { test: /\.(html|xml)$/, use: "nativescript-dev-webpack/xml-namespace-loader" }, @@ -265,7 +256,7 @@ module.exports = env => { async: false, useTypescriptIncrementalApi: true, memoryLimit: 4096 - }), + }) ], }; diff --git a/demo/config/mocha.opts b/demo/config/mocha.opts index 8e77e681..c21dcca6 100644 --- a/demo/config/mocha.opts +++ b/demo/config/mocha.opts @@ -1,4 +1,4 @@ ---timeout 80000 +--timeout 999999 --recursive e2e --reporter mochawesome --reporter-options quiet=true,html=true,inline=true,autoOpen=true diff --git a/hmr/hmr-update.js b/hmr/hmr-update.js deleted file mode 100644 index 9536d4fe..00000000 --- a/hmr/hmr-update.js +++ /dev/null @@ -1,7 +0,0 @@ -module.exports = () => { - const update = require("../hot"); - const fileSystemModule = require("tns-core-modules/file-system"); - const applicationFiles = fileSystemModule.knownFolders.currentApp(); - const latestHash = __webpack_require__["h"](); - return update(latestHash, filename => applicationFiles.getFile(filename)); -} \ No newline at end of file diff --git a/hmr/hmr-update.ts b/hmr/hmr-update.ts new file mode 100644 index 00000000..6ad9b3d1 --- /dev/null +++ b/hmr/hmr-update.ts @@ -0,0 +1,10 @@ +import * as hot from "../hot"; +import { knownFolders } from "tns-core-modules/file-system"; + +declare const __webpack_require__: any; + +export function hmrUpdate() { + const applicationFiles = knownFolders.currentApp(); + const latestHash = __webpack_require__["h"](); + return hot(latestHash, filename => applicationFiles.getFile(filename)); +} \ No newline at end of file diff --git a/hmr/hot-loader.ts b/hmr/hot-loader.ts new file mode 100644 index 00000000..2a0fca71 --- /dev/null +++ b/hmr/hot-loader.ts @@ -0,0 +1,44 @@ +import { loader } from "webpack"; +import { convertToUnixPath } from "../lib/utils"; +import { extname } from "path"; +import { getOptions } from "loader-utils"; + +const extMap = { + ".css": "style", + ".scss": "style", + ".less": "style", + ".js": "script", + ".ts": "script", + ".xml": "markup", + ".html": "markup", +} + +const loader: loader.Loader = function (source, map) { + const moduleRelativePath = this.resourcePath.replace(this.rootContext, "."); + const modulePath = convertToUnixPath(moduleRelativePath); + const ext = extname(modulePath).toLowerCase(); + const moduleType = extMap[ext] || "unknown"; + + const options = getOptions(this) || {}; + const alwaysSelfAccept = options.alwaysSelfAccept; + const trace = options.trace; + + const shouldAutoAcceptCheck = `&& global._isModuleLoadedForUI && global._isModuleLoadedForUI("${modulePath}")`; + const traceCode = `console.log("[hot-loader]: Self-accept module: ${modulePath}");`; + + const hotCode = ` +if (module.hot ${alwaysSelfAccept ? "" : shouldAutoAcceptCheck} ) { + ${trace ? traceCode : ""} + module.hot.accept(); + module.hot.dispose(() => { + global.hmrRefresh({ type: "${moduleType}", path: "${modulePath}" }); + }); +}`; + + this.callback(null, `${source}; ${hotCode} `, map); +}; + +export default loader; + + + diff --git a/hmr/index.js b/hmr/index.js deleted file mode 100644 index bdda024f..00000000 --- a/hmr/index.js +++ /dev/null @@ -1 +0,0 @@ -module.exports.hmrUpdate = require("./hmr-update"); \ No newline at end of file diff --git a/hmr/index.ts b/hmr/index.ts new file mode 100644 index 00000000..24abe3c0 --- /dev/null +++ b/hmr/index.ts @@ -0,0 +1 @@ +export { hmrUpdate } from "./hmr-update"; \ No newline at end of file diff --git a/index.js b/index.js index e76ce2cb..2ed399dc 100644 --- a/index.js +++ b/index.js @@ -98,6 +98,41 @@ exports.getConvertedExternals = (externals) => { return modifiedExternals; }; + +/** + * The `require.context` call in `bundle-config-loader` will ask the FS for files and + * the PlatformFSPlugin will return files without `.${platform}`. The SplitChunksPlugin will + * compare the `appComponents` with the files returned from the `PlatformFSPlugin` and when they + * do not match because of the platform extension, it will duplicate the custom components + * in `bundle` (activity.js - included by the `require.context` call in `bundle-config-loader`) + * and `vendor` (activity.android.js - included by `android-app-components-loader` and `SplitChunksPlugin`). + * We are post-processing the `appComponents` in order to unify the file names and avoid getting + * a build-time SBG exception for duplicate native class definition. + */ +exports.processAppComponents = (appComponents, platform) => { + for (const key in appComponents) { + appComponents[key] = appComponents[key].replace(`.${platform}`, ""); + } +}; + +/** + * The `bundle-config-loader` needs this in order to skip the custom entries in its `require.context` call. + * If we don't skip them, custom entries like custom Android application will be included in both `application.js` + * (because its defined as an entry) and `bundle.js` (included by the `require.context` call in `bundle-config-loader`) + * causing a build-time SBG exception for duplicate native class definition. + * We are removing the extension in order to unify the file names with the `PlatformFSPlugin`. + */ +exports.getUserDefinedEntries = (entries, platform) => { + const userDefinedEntries = []; + for (const entry in entries) { + if (entry !== "bundle" && entry !== "tns_modules/tns-core-modules/inspector_modules") { + userDefinedEntries.push(entries[entry].replace(`.${platform}`, "")); + } + } + + return userDefinedEntries; +}; + const sanitize = name => name .split("") .filter(char => /[a-zA-Z0-9]/.test(char)) diff --git a/jasmine-config/jasmine.json b/jasmine-config/jasmine.json index 84db3eb2..8d3ecdc5 100644 --- a/jasmine-config/jasmine.json +++ b/jasmine-config/jasmine.json @@ -1,7 +1,8 @@ { "spec_dir": ".", "spec_files": [ - "./!(node_modules)/**/*.spec.js", + "!node_modules/**/*.spec.js", + "!demo/**/*.spec.js", "./*.spec.js" ], "helpers": [ diff --git a/package.json b/package.json index f5bce176..90a97bf6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "nativescript-dev-webpack", - "version": "1.0.0", + "version": "1.1.0", "main": "index", "description": "", "homepage": "http://www.telerik.com", @@ -28,10 +28,11 @@ "url": "https://github.com/NativeScript/nativescript-dev-webpack.git" }, "scripts": { + "tsc": "tsc", "postinstall": "node postinstall.js", "preuninstall": "node preuninstall.js", "postpack": "rm -rf node_modules", - "prepare": "tsc && npm run jasmine", + "prepare": "npm run tsc && npm run jasmine", "test": "npm run prepare && npm run jasmine", "jasmine": "jasmine --config=jasmine-config/jasmine.json", "version": "rm package-lock.json && conventional-changelog -p angular -i CHANGELOG.md -s && git add CHANGELOG.md" @@ -49,9 +50,10 @@ "clean-webpack-plugin": "~1.0.0", "copy-webpack-plugin": "~4.6.0", "css-loader": "~2.1.1", - "fork-ts-checker-webpack-plugin": "1.3.0", "extra-watch-webpack-plugin": "1.0.3", + "fork-ts-checker-webpack-plugin": "1.3.0", "global-modules-path": "2.0.0", + "loader-utils": "^1.2.3", "minimatch": "3.0.4", "nativescript-hook": "0.2.4", "nativescript-worker-loader": "~0.9.0", @@ -77,13 +79,16 @@ "@angular/compiler-cli": "8.0.0", "@ngtools/webpack": "8.0.0", "@types/jasmine": "^3.3.7", + "@types/loader-utils": "^1.1.3", "@types/node": "^10.12.12", "@types/proxyquire": "1.3.28", "@types/semver": "^6.0.0", + "@types/webpack": "^4.4.34", "conventional-changelog-cli": "^1.3.22", "jasmine": "^3.2.0", "jasmine-spec-reporter": "^4.2.1", "proxyquire": "2.1.0", + "tns-core-modules": "next", "typescript": "~3.4.0" } } diff --git a/snapshot/android/snapshot-generator.js b/snapshot/android/snapshot-generator.js index 2bb1a7eb..8c177809 100644 --- a/snapshot/android/snapshot-generator.js +++ b/snapshot/android/snapshot-generator.js @@ -43,19 +43,31 @@ module.exports = SnapshotGenerator; SnapshotGenerator.SNAPSHOT_PACKAGE_NANE = "nativescript-android-snapshot"; -SnapshotGenerator.prototype.preprocessInputFiles = function(inputFiles, outputFile) { +SnapshotGenerator.prototype.preprocessInputFiles = function (inputFiles, outputFile) { // Make some modifcations on the original bundle and save it on the specified path const bundlePreambleContent = fs.readFileSync(BUNDLE_PREAMBLE_PATH, "utf8"); const bundleEndingContent = fs.readFileSync(BUNDLE_ENDING_PATH, "utf8"); - const inputFilesContent = inputFiles.map(file => fs.readFileSync(file, "utf8")).join("\n"); + // IMPORTANT: join by "\n;" as we are joining IIFE functions and if the snapshot tool is used + // along with Uglify configuration for replacing `;` with `/n`, we will generate invalid JavaScript + // Example: + // (function() { + // some code here + // })() + // // sourceMapUrl...... + // ** when we join without `;` here, the next IIFE is assumed as a function call to the result of the first IIFE + // (function() { + // some code here + // })() + // // sourceMapUrl...... + const inputFilesContent = inputFiles.map(file => fs.readFileSync(file, "utf8")).join("\n;"); const snapshotFileContent = bundlePreambleContent + "\n" + inputFilesContent + "\n" + bundleEndingContent; fs.writeFileSync(outputFile, snapshotFileContent, { encoding: "utf8" }); } const snapshotToolsDownloads = {}; -SnapshotGenerator.prototype.downloadMksnapshotTool = function(snapshotToolsPath, v8Version, targetArch) { +SnapshotGenerator.prototype.downloadMksnapshotTool = function (snapshotToolsPath, v8Version, targetArch) { const hostOS = getHostOS(); const mksnapshotToolRelativePath = join("mksnapshot-tools", "v8-v" + v8Version, hostOS + "-" + os.arch(), "mksnapshot-" + targetArch); const mksnapshotToolPath = join(snapshotToolsPath, mksnapshotToolRelativePath); @@ -84,7 +96,7 @@ SnapshotGenerator.prototype.downloadMksnapshotTool = function(snapshotToolsPath, return snapshotToolsDownloads[mksnapshotToolPath]; } -SnapshotGenerator.prototype.convertToAndroidArchName = function(archName) { +SnapshotGenerator.prototype.convertToAndroidArchName = function (archName) { switch (archName) { case "arm": return "armeabi-v7a"; case "arm64": return "arm64-v8a"; @@ -94,7 +106,7 @@ SnapshotGenerator.prototype.convertToAndroidArchName = function(archName) { } } -SnapshotGenerator.prototype.runMksnapshotTool = function(snapshotToolsPath, inputFile, v8Version, targetArchs, buildCSource, mksnapshotParams) { +SnapshotGenerator.prototype.runMksnapshotTool = function (snapshotToolsPath, inputFile, v8Version, targetArchs, buildCSource, mksnapshotParams) { // Cleans the snapshot build folder shelljs.rm("-rf", join(this.buildPath, "snapshots")); @@ -120,14 +132,22 @@ SnapshotGenerator.prototype.runMksnapshotTool = function(snapshotToolsPath, inpu const command = `${currentArchMksnapshotToolPath} ${inputFile} --startup_blob ${join(currentArchBlobOutputPath, `${SNAPSHOT_BLOB_NAME}.blob`)} ${params}`; return new Promise((resolve, reject) => { - const child = child_process.exec(command, {encoding: "utf8"}, (error, stdout, stderr) => { + const child = child_process.exec(command, { encoding: "utf8" }, (error, stdout, stderr) => { const errorHeader = `Target architecture: ${androidArch}\n`; + let errorFooter = ``; + if (stderr.length || error) { + try { + require(inputFile); + } catch (e) { + errorFooter = `\nJavaScript execution error: ${e.stack}$`; + } + } if (stderr.length) { - const message = `${errorHeader}${stderr}`; + const message = `${errorHeader}${stderr}${errorFooter}`; reject(new Error(message)); } else if (error) { - error.message = `${errorHeader}${error.message}`; + error.message = `${errorHeader}${error.message}${errorFooter}`; reject(error); } else { console.log(stdout); @@ -139,7 +159,7 @@ SnapshotGenerator.prototype.runMksnapshotTool = function(snapshotToolsPath, inpu if (buildCSource) { const currentArchSrcOutputPath = join(this.buildPath, "snapshots/src", androidArch); shelljs.mkdir("-p", currentArchSrcOutputPath); - shellJsExecuteInDir(currentArchBlobOutputPath, function() { + shellJsExecuteInDir(currentArchBlobOutputPath, function () { shelljs.exec(`xxd -i ${SNAPSHOT_BLOB_NAME}.blob > ${join(currentArchSrcOutputPath, `${SNAPSHOT_BLOB_NAME}.c`)}`); }); } @@ -150,7 +170,7 @@ SnapshotGenerator.prototype.runMksnapshotTool = function(snapshotToolsPath, inpu }); } -SnapshotGenerator.prototype.buildSnapshotLibs = function(androidNdkBuildPath, targetArchs) { +SnapshotGenerator.prototype.buildSnapshotLibs = function (androidNdkBuildPath, targetArchs) { // Compile *.c files to produce *.so libraries with ndk-build tool const ndkBuildPath = join(this.buildPath, "ndk-build"); const androidArchs = targetArchs.map(arch => this.convertToAndroidArchName(arch)); @@ -159,22 +179,22 @@ SnapshotGenerator.prototype.buildSnapshotLibs = function(androidNdkBuildPath, ta shelljs.cp("-r", NDK_BUILD_SEED_PATH, ndkBuildPath); fs.writeFileSync(join(ndkBuildPath, "jni/Application.mk"), "APP_ABI := " + androidArchs.join(" ")); // create Application.mk file shelljs.mv(join(this.buildPath, "snapshots/src/*"), join(ndkBuildPath, "jni")); - shellJsExecuteInDir(ndkBuildPath, function(){ + shellJsExecuteInDir(ndkBuildPath, function () { shelljs.exec(androidNdkBuildPath); }); return join(ndkBuildPath, "libs"); } -SnapshotGenerator.prototype.buildIncludeGradle = function() { +SnapshotGenerator.prototype.buildIncludeGradle = function () { shelljs.cp(INCLUDE_GRADLE_PATH, join(this.buildPath, "include.gradle")); } -SnapshotGenerator.prototype.generate = function(options) { +SnapshotGenerator.prototype.generate = function (options) { // Arguments validation options = options || {}; if (!options.v8Version) { throw new Error("No v8 version specified."); } if (!options.snapshotToolsPath) { throw new Error("snapshotToolsPath option is not specified."); } - const preprocessedInputFile = options.preprocessedInputFile || join(this.buildPath, "inputFile.preprocessed"); + const preprocessedInputFile = options.preprocessedInputFile || join(this.buildPath, "inputFile.preprocessed"); console.log("***** Starting snapshot generation using V8 version: ", options.v8Version); diff --git a/templates/webpack.angular.js b/templates/webpack.angular.js index 22b0b558..d7cd1e78 100644 --- a/templates/webpack.angular.js +++ b/templates/webpack.angular.js @@ -32,7 +32,6 @@ module.exports = env => { // Default destination inside platforms//... const dist = resolve(projectRoot, nsWebpack.getAppPath(platform, projectRoot)); - const appResourcesPlatformDir = platform === "android" ? "Android" : "iOS"; const { // The 'appPath' and 'appResourcesPath' values are fetched from @@ -109,6 +108,7 @@ module.exports = env => { itemsToClean.push(`${join(projectRoot, "platforms", "android", "app", "build", "configurations", "nativescript-android-snapshot")}`); } + nsWebpack.processAppComponents(appComponents, platform); const config = { mode: production ? "production" : "development", context: appFullPath, @@ -213,6 +213,7 @@ module.exports = env => { unitTesting, appFullPath, projectRoot, + ignoredFiles: nsWebpack.getUserDefinedEntries(entries, platform) } }, ].filter(loader => !!loader) diff --git a/templates/webpack.javascript.js b/templates/webpack.javascript.js index b976e827..2d004846 100644 --- a/templates/webpack.javascript.js +++ b/templates/webpack.javascript.js @@ -27,7 +27,6 @@ module.exports = env => { // Default destination inside platforms//... const dist = resolve(projectRoot, nsWebpack.getAppPath(platform, projectRoot)); - const appResourcesPlatformDir = platform === "android" ? "Android" : "iOS"; const { // The 'appPath' and 'appResourcesPath' values are fetched from @@ -69,6 +68,8 @@ module.exports = env => { itemsToClean.push(`${join(projectRoot, "platforms", "android", "app", "build", "configurations", "nativescript-android-snapshot")}`); } + + nsWebpack.processAppComponents(appComponents, platform); const config = { mode: production ? "production" : "development", context: appFullPath, @@ -173,24 +174,15 @@ module.exports = env => { unitTesting, appFullPath, projectRoot, + ignoredFiles: nsWebpack.getUserDefinedEntries(entries, platform) } }, ].filter(loader => !!loader) }, { - test: /-page\.js$/, - use: "nativescript-dev-webpack/script-hot-loader" - }, - - { - test: /\.(css|scss)$/, - use: "nativescript-dev-webpack/style-hot-loader" - }, - - { - test: /\.(html|xml)$/, - use: "nativescript-dev-webpack/markup-hot-loader" + test: /\.(js|css|scss|html|xml)$/, + use: "nativescript-dev-webpack/hmr/hot-loader" }, { test: /\.(html|xml)$/, use: "nativescript-dev-webpack/xml-namespace-loader" }, diff --git a/templates/webpack.typescript.js b/templates/webpack.typescript.js index b04e72e2..a6bda652 100644 --- a/templates/webpack.typescript.js +++ b/templates/webpack.typescript.js @@ -28,7 +28,6 @@ module.exports = env => { // Default destination inside platforms//... const dist = resolve(projectRoot, nsWebpack.getAppPath(platform, projectRoot)); - const appResourcesPlatformDir = platform === "android" ? "Android" : "iOS"; const { // The 'appPath' and 'appResourcesPath' values are fetched from @@ -73,6 +72,7 @@ module.exports = env => { itemsToClean.push(`${join(projectRoot, "platforms", "android", "app", "build", "configurations", "nativescript-android-snapshot")}`); } + nsWebpack.processAppComponents(appComponents, platform); const config = { mode: production ? "production" : "development", context: appFullPath, @@ -179,24 +179,15 @@ module.exports = env => { unitTesting, appFullPath, projectRoot, + ignoredFiles: nsWebpack.getUserDefinedEntries(entries, platform) } }, ].filter(loader => !!loader) }, - - { - test: /-page\.ts$/, - use: "nativescript-dev-webpack/script-hot-loader" - }, - - { - test: /\.(css|scss)$/, - use: "nativescript-dev-webpack/style-hot-loader" - }, - + { - test: /\.(html|xml)$/, - use: "nativescript-dev-webpack/markup-hot-loader" + test: /\.(ts|css|scss|html|xml)$/, + use: "nativescript-dev-webpack/hmr/hot-loader" }, { test: /\.(html|xml)$/, use: "nativescript-dev-webpack/xml-namespace-loader" }, diff --git a/templates/webpack.vue.js b/templates/webpack.vue.js index 600c399c..b0539c0e 100644 --- a/templates/webpack.vue.js +++ b/templates/webpack.vue.js @@ -31,7 +31,6 @@ module.exports = env => { // Default destination inside platforms//... const dist = resolve(projectRoot, nsWebpack.getAppPath(platform, projectRoot)); - const appResourcesPlatformDir = platform === "android" ? "Android" : "iOS"; const { // The 'appPath' and 'appResourcesPath' values are fetched from @@ -76,6 +75,7 @@ module.exports = env => { itemsToClean.push(`${join(projectRoot, "platforms", "android", "app", "build", "configurations", "nativescript-android-snapshot")}`); } + nsWebpack.processAppComponents(appComponents, platform); const config = { mode: mode, context: appFullPath, @@ -186,6 +186,7 @@ module.exports = env => { unitTesting, appFullPath, projectRoot, + ignoredFiles: nsWebpack.getUserDefinedEntries(entries, platform) }, }, ].filter(loader => Boolean(loader)), diff --git a/unit-testing-config-loader.js b/unit-testing-config-loader.js index b92fa3a6..e3d4a2ff 100644 --- a/unit-testing-config-loader.js +++ b/unit-testing-config-loader.js @@ -1,10 +1,19 @@ const { join, relative } = require("path"); +const { existsSync } = require("fs"); const { convertSlashesInPath } = require("./projectHelpers"); +function getRunnerFullPath(projectRoot) { + const runnerRootPath = join(projectRoot, "node_modules", "nativescript-unit-test-runner"); + const runnerAppPath = join(runnerRootPath, "app"); + const result = existsSync(runnerAppPath) ? runnerAppPath : runnerRootPath; + + return result; +} + module.exports = function ({ appFullPath, projectRoot, angular, rootPagesRegExp }) { // TODO: Consider to use the files property from karma.conf.js const testFilesRegExp = /tests\/.*\.(ts|js)/; - const runnerFullPath = join(projectRoot, "node_modules", "nativescript-unit-test-runner"); + const runnerFullPath = getRunnerFullPath(projectRoot); const runnerRelativePath = convertSlashesInPath(relative(appFullPath, runnerFullPath)); const appCssFilePath = convertSlashesInPath(join(runnerRelativePath, "app.css")); let source = `