diff --git a/index.js b/index.js index 39e3bb96..f9a92f11 100644 --- a/index.js +++ b/index.js @@ -25,14 +25,21 @@ exports.getAotEntryModule = function (appDirectory) { return aotEntry; } -exports.getEntryModule = function (appDirectory) { +exports.getEntryModule = function (appDirectory, platform) { verifyEntryModuleDirectory(appDirectory); const entry = getPackageJsonEntry(appDirectory); const tsEntryPath = path.resolve(appDirectory, `${entry}.ts`); const jsEntryPath = path.resolve(appDirectory, `${entry}.js`); - if (!existsSync(tsEntryPath) && !existsSync(jsEntryPath)) { + let entryExists = existsSync(tsEntryPath) || existsSync(jsEntryPath); + if (!entryExists && platform) { + const platformTsEntryPath = path.resolve(appDirectory, `${entry}.${platform}.ts`); + const platformJsEntryPath = path.resolve(appDirectory, `${entry}.${platform}.js`); + entryExists = existsSync(platformTsEntryPath) || existsSync(platformJsEntryPath); + } + + if (!entryExists) { throw new Error(`The entry module ${entry} specified in ` + `${appDirectory}/package.json doesn't exist!`) } diff --git a/package.json b/package.json index 92e0e09e..6423ff34 100644 --- a/package.json +++ b/package.json @@ -100,6 +100,8 @@ }, "devDependencies": { "@ngtools/webpack": "~7.2.0", + "@angular/compiler": "~7.2.0", + "@angular/compiler-cli": "~7.2.0", "@types/jasmine": "^3.3.7", "@types/node": "^10.12.12", "@types/proxyquire": "1.3.28", diff --git a/plugins/NativeScriptAngularCompilerPlugin.ts b/plugins/NativeScriptAngularCompilerPlugin.ts new file mode 100644 index 00000000..299b97d6 --- /dev/null +++ b/plugins/NativeScriptAngularCompilerPlugin.ts @@ -0,0 +1,28 @@ +import { parse, join } from "path"; +import { AngularCompilerPlugin } from "@ngtools/webpack"; + +export function getAngularCompilerPlugin(platform: string): any { + class NativeScriptAngularCompilerPlugin extends AngularCompilerPlugin { + // This is the bridge between the @ngtols/webpack loader and the AngularCompilerPlugin plugin itself: + // https://github.com/angular/angular-cli/blob/bf52b26219ffc16bed2dd55716e21773b415fd2a/packages/ngtools/webpack/src/loader.ts#L49 + // The problem is that the loader does not call the `hostReplacementPaths` method when asking for the compiledFile. + // By overriding this method, we work around this issue and support platform specific files from the loader + // that are not compiled by the AngularCompilerPlugin plugin. e.g. main.ts is the webpack entry point and + // it's loaded by the @ngtools/webpack loader but its not compiled by the plugin because the TypeScript Compiler + // knowns only about main.android.ts and main.ios.ts (main.ts is not imported/required anywhere in the app). + getCompiledFile(file) { + try { + if (platform) { + const parsed = parse(file); + const platformFile = join(parsed.dir, `${parsed.name}.${platform}${parsed.ext}`); + return super.getCompiledFile(platformFile); + } + } + catch (e) { } + + return super.getCompiledFile(file); + } + } + + return NativeScriptAngularCompilerPlugin; +} diff --git a/templates/webpack.angular.js b/templates/webpack.angular.js index 2f196cb2..ed384adb 100644 --- a/templates/webpack.angular.js +++ b/templates/webpack.angular.js @@ -12,8 +12,8 @@ const CopyWebpackPlugin = require("copy-webpack-plugin"); const { BundleAnalyzerPlugin } = require("webpack-bundle-analyzer"); const { NativeScriptWorkerPlugin } = require("nativescript-worker-loader/NativeScriptWorkerPlugin"); const UglifyJsPlugin = require("uglifyjs-webpack-plugin"); -const { AngularCompilerPlugin } = require("@ngtools/webpack"); -const hashSalt = Date.now().toString(); +const { getAngularCompilerPlugin } = require("nativescript-dev-webpack/plugins/NativeScriptAngularCompilerPlugin"); +const hashSalt = Date.now().toString(); module.exports = env => { // Add your custom Activities, Services and other Android app components here. @@ -27,6 +27,7 @@ module.exports = env => { throw new Error("You need to provide a target platform!"); } + const AngularCompilerPlugin = getAngularCompilerPlugin(platform); const projectRoot = __dirname; // Default destination inside platforms//... @@ -54,7 +55,7 @@ module.exports = env => { const appFullPath = resolve(projectRoot, appPath); const appResourcesFullPath = resolve(projectRoot, appResourcesPath); const tsConfigName = "tsconfig.tns.json"; - const entryModule = `${nsWebpack.getEntryModule(appFullPath)}.ts`; + const entryModule = `${nsWebpack.getEntryModule(appFullPath, platform)}.ts`; const entryPath = `.${sep}${entryModule}`; const entries = { bundle: entryPath }; if (platform === "ios") { @@ -261,10 +262,10 @@ module.exports = env => { // configures the WebPack runtime to be generated inside the snapshot // module and no `runtime.js` module exist. (snapshot ? [] : ["./runtime"]) - .concat([ - "./vendor", - "./bundle", - ]) + .concat([ + "./vendor", + "./bundle", + ]) ), // For instructions on how to set up workers with webpack // check out https://github.com/nativescript/worker-loader diff --git a/templates/webpack.config.spec.ts b/templates/webpack.config.spec.ts index 8a17cb6f..35db7d4b 100644 --- a/templates/webpack.config.spec.ts +++ b/templates/webpack.config.spec.ts @@ -36,6 +36,7 @@ const webpackConfigAngular = proxyquire('./webpack.angular', { 'nativescript-dev-webpack/transformers/ns-replace-lazy-loader': { nsReplaceLazyLoader: () => { return FakeLazyTransformerFlag } }, 'nativescript-dev-webpack/transformers/ns-support-hmr-ng': { nsSupportHmrNg: () => { return FakeHmrTransformerFlag } }, 'nativescript-dev-webpack/utils/ast-utils': { getMainModulePath: () => { return "fakePath"; } }, + 'nativescript-dev-webpack/plugins/NativeScriptAngularCompilerPlugin': { getAngularCompilerPlugin: () => { return AngularCompilerStub; } }, '@ngtools/webpack': { AngularCompilerPlugin: AngularCompilerStub } diff --git a/templates/webpack.javascript.js b/templates/webpack.javascript.js index a927d9bf..626df1c3 100644 --- a/templates/webpack.javascript.js +++ b/templates/webpack.javascript.js @@ -49,7 +49,7 @@ module.exports = env => { const appFullPath = resolve(projectRoot, appPath); const appResourcesFullPath = resolve(projectRoot, appResourcesPath); - const entryModule = nsWebpack.getEntryModule(appFullPath); + const entryModule = nsWebpack.getEntryModule(appFullPath, platform); const entryPath = `.${sep}${entryModule}.js`; const entries = { bundle: entryPath }; if (platform === "ios") { diff --git a/templates/webpack.typescript.js b/templates/webpack.typescript.js index 730c38ee..5e7903ba 100644 --- a/templates/webpack.typescript.js +++ b/templates/webpack.typescript.js @@ -49,7 +49,7 @@ module.exports = env => { const appFullPath = resolve(projectRoot, appPath); const appResourcesFullPath = resolve(projectRoot, appResourcesPath); - const entryModule = nsWebpack.getEntryModule(appFullPath); + const entryModule = nsWebpack.getEntryModule(appFullPath, platform); const entryPath = `.${sep}${entryModule}.ts`; const entries = { bundle: entryPath }; if (platform === "ios") { diff --git a/templates/webpack.vue.js b/templates/webpack.vue.js index 3361cc3d..298917e6 100644 --- a/templates/webpack.vue.js +++ b/templates/webpack.vue.js @@ -56,7 +56,7 @@ module.exports = env => { const appFullPath = resolve(projectRoot, appPath); const appResourcesFullPath = resolve(projectRoot, appResourcesPath); - const entryModule = nsWebpack.getEntryModule(appFullPath); + const entryModule = nsWebpack.getEntryModule(appFullPath, platform); const entryPath = `.${sep}${entryModule}`; const entries = { bundle: entryPath }; if (platform === "ios") {