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/bundle-config-loader.js b/bundle-config-loader.ts similarity index 74% rename from bundle-config-loader.js rename to bundle-config-loader.ts index 4daa915b..da7d4196 100644 --- a/bundle-config-loader.js +++ b/bundle-config-loader.ts @@ -1,8 +1,19 @@ -const unitTestingConfigLoader = require("./unit-testing-config-loader"); +import unitTestingConfigLoader from "./unit-testing-config-loader"; +import { loader } from "webpack"; +import { getOptions } from "loader-utils"; -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 = /(? { // 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 diff --git a/demo/JavaScriptApp/webpack.config.js b/demo/JavaScriptApp/webpack.config.js index e285ce31..27bfc2db 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 @@ -103,7 +102,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 +173,15 @@ module.exports = env => { unitTesting, appFullPath, projectRoot, + registerModules: /(? !!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 +224,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/webpack.config.js b/demo/TypeScriptApp/webpack.config.js index 74dfb0dd..88f3585f 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 @@ -180,24 +179,15 @@ module.exports = env => { unitTesting, appFullPath, projectRoot, + registerModules: /(? !!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 +255,7 @@ module.exports = env => { async: false, useTypescriptIncrementalApi: true, memoryLimit: 4096 - }), + }) ], }; 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..5f29792d --- /dev/null +++ b/hmr/hmr-update.ts @@ -0,0 +1,10 @@ +import update 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 update(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/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..8004580e 100644 --- a/package.json +++ b/package.json @@ -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,8 +50,8 @@ "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", "minimatch": "3.0.4", "nativescript-hook": "0.2.4", @@ -77,13 +78,17 @@ "@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", + "loader-utils": "^1.2.3", "proxyquire": "2.1.0", + "tns-core-modules": "next", "typescript": "~3.4.0" } } diff --git a/templates/webpack.angular.js b/templates/webpack.angular.js index 22b0b558..f2933c5f 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 diff --git a/templates/webpack.javascript.js b/templates/webpack.javascript.js index b976e827..e6515456 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 @@ -179,18 +178,8 @@ module.exports = env => { }, { - 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..8c7627bf 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 @@ -183,20 +182,10 @@ module.exports = env => { }, ].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..df96d8e1 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