From 4f620f6ba60d3be927d738189659a7d56b201204 Mon Sep 17 00:00:00 2001 From: rosen-vladimirov Date: Wed, 15 Jan 2020 15:25:05 +0200 Subject: [PATCH 1/2] feat: allow setting custom webpack config file Currently CLI passes the webpack.config.js at the root of the application as config to the spawned webpack process. This file is managed by both the developers and nativescript-dev-webpack (when you update this package, you often have to update the file, which overrides any custom settings). In order to allow easier upgrades and customizations, add an option in nsconfig.json (`webpackConfigPath`) to set the path to config file passed to webpack process. This way, the `webpack.config.js` can be managed by nativescript-dev-webpack and all customizations can be done in another file. The path to custom file can be set in nsconfig.json and CLI will pass it to webpack. --- lib/definitions/project.d.ts | 10 +++++++- lib/project-data.ts | 2 ++ .../webpack/webpack-compiler-service.ts | 8 +++++-- test/project-data.ts | 24 +++++++++++++++++-- .../webpack/webpack-compiler-service.ts | 24 ++++++++++++++++++- test/stubs.ts | 1 + 6 files changed, 63 insertions(+), 6 deletions(-) diff --git a/lib/definitions/project.d.ts b/lib/definitions/project.d.ts index c02d342aab..6180f374ed 100644 --- a/lib/definitions/project.d.ts +++ b/lib/definitions/project.d.ts @@ -75,7 +75,8 @@ interface INsConfig { appResourcesPath?: string; shared?: boolean; previewAppSchema?: string; - overridePods?: string + overridePods?: string; + webpackConfigPath?: string; } interface IProjectData extends ICreateProjectData { @@ -106,6 +107,13 @@ interface IProjectData extends ICreateProjectData { */ previewAppSchema: string; + /** + * Defines the path to the configuration file passed to webpack process. + * By default this is the webpack.config.js at the root of the application. + * The value can be changed by setting `webpackConfigPath` in nsconfig.json. + */ + webpackConfigPath: string; + /** * Initializes project data with the given project directory. If none supplied defaults to --path option or cwd. * @param {string} projectDir Project root directory. diff --git a/lib/project-data.ts b/lib/project-data.ts index 813e2d616b..6f96f946f2 100644 --- a/lib/project-data.ts +++ b/lib/project-data.ts @@ -70,6 +70,7 @@ export class ProjectData implements IProjectData { public podfilePath: string; public isShared: boolean; public previewAppSchema: string; + public webpackConfigPath: string; constructor(private $fs: IFileSystem, private $errors: IErrors, @@ -145,6 +146,7 @@ export class ProjectData implements IProjectData { this.podfilePath = path.join(this.appResourcesDirectoryPath, this.$devicePlatformsConstants.iOS, constants.PODFILE_NAME); this.isShared = !!(this.nsConfig && this.nsConfig.shared); this.previewAppSchema = this.nsConfig && this.nsConfig.previewAppSchema; + this.webpackConfigPath = (this.nsConfig && this.nsConfig.webpackConfigPath) ? path.resolve(this.projectDir, this.nsConfig.webpackConfigPath) : path.join(this.projectDir, "webpack.config.js"); return; } diff --git a/lib/services/webpack/webpack-compiler-service.ts b/lib/services/webpack/webpack-compiler-service.ts index 10da3ceb94..0b353499c8 100644 --- a/lib/services/webpack/webpack-compiler-service.ts +++ b/lib/services/webpack/webpack-compiler-service.ts @@ -12,6 +12,7 @@ export class WebpackCompilerService extends EventEmitter implements IWebpackComp constructor( private $errors: IErrors, private $childProcess: IChildProcess, + public $fs: IFileSystem, public $hooksService: IHooksService, public $hostInfo: IHostInfo, private $logger: ILogger, @@ -153,15 +154,18 @@ export class WebpackCompilerService extends EventEmitter implements IWebpackComp @performanceLog() private async startWebpackProcess(platformData: IPlatformData, projectData: IProjectData, prepareData: IPrepareData): Promise { + if (!this.$fs.exists(projectData.webpackConfigPath)) { + this.$errors.fail(`The webpack configuration file ${projectData.webpackConfigPath} does not exist. Ensure you have such file or set correct path in nsconfig.json`); + } + const envData = this.buildEnvData(platformData.platformNameLowerCase, projectData, prepareData); const envParams = await this.buildEnvCommandLineParams(envData, platformData, projectData, prepareData); const additionalNodeArgs = semver.major(process.version) <= 8 ? ["--harmony"] : []; - const args = [ ...additionalNodeArgs, "--preserve-symlinks", path.join(projectData.projectDir, "node_modules", "webpack", "bin", "webpack.js"), - `--config=${path.join(projectData.projectDir, "webpack.config.js")}`, + `--config=${projectData.webpackConfigPath}`, ...envParams ]; diff --git a/test/project-data.ts b/test/project-data.ts index 19ba822181..3cf98eceb2 100644 --- a/test/project-data.ts +++ b/test/project-data.ts @@ -42,7 +42,8 @@ describe("projectData", () => { return testInjector; }; - const prepareTest = (opts?: { packageJsonData?: { dependencies?: IStringDictionary, devDependencies: IStringDictionary }, nsconfigData?: { shared: boolean } }): IProjectData => { + const projectDir = "projectDir"; + const prepareTest = (opts?: { packageJsonData?: { dependencies?: IStringDictionary, devDependencies: IStringDictionary }, nsconfigData?: { shared?: boolean, webpackConfigPath?: string } }): IProjectData => { const testInjector = createTestInjector(); const fs = testInjector.resolve("fs"); fs.exists = (filePath: string) => filePath && (path.basename(filePath) === "package.json" || (path.basename(filePath) === "nsconfig.json" && opts && opts.nsconfigData)); @@ -64,7 +65,7 @@ describe("projectData", () => { }; const projectHelper: IProjectHelper = testInjector.resolve("projectHelper"); - projectHelper.projectDir = "projectDir"; + projectHelper.projectDir = projectDir; const projectData: IProjectData = testInjector.resolve("projectData"); projectData.initializeProjectData(); @@ -142,4 +143,23 @@ describe("projectData", () => { assert.isTrue(projectData.isShared); }); }); + + describe("webpackConfigPath", () => { + it("default path to webpack.config.js is set when nsconfig.json does not set value", () => { + const projectData = prepareTest(); + assert.equal(projectData.webpackConfigPath, path.join(projectDir, "webpack.config.js")); + }); + + it("returns correct path when full path is set in nsconfig.json", () => { + const pathToConfig = path.resolve(path.join("/testDir", "innerDir", "mywebpack.config.js")); + const projectData = prepareTest({ nsconfigData: { webpackConfigPath: pathToConfig } }); + assert.equal(projectData.webpackConfigPath, pathToConfig); + }); + + it("returns correct path when relative path is set in nsconfig.json", () => { + const pathToConfig = path.resolve(path.join("projectDir", "innerDir", "mywebpack.config.js")); + const projectData = prepareTest({ nsconfigData: { webpackConfigPath: path.join("./innerDir", "mywebpack.config.js") } }); + assert.equal(projectData.webpackConfigPath, pathToConfig); + }); + }); }); diff --git a/test/services/webpack/webpack-compiler-service.ts b/test/services/webpack/webpack-compiler-service.ts index 22fb85686d..8da3183c24 100644 --- a/test/services/webpack/webpack-compiler-service.ts +++ b/test/services/webpack/webpack-compiler-service.ts @@ -1,6 +1,7 @@ import { Yok } from "../../../lib/common/yok"; import { WebpackCompilerService } from "../../../lib/services/webpack/webpack-compiler-service"; import { assert } from "chai"; +import { ErrorsStub } from "../../stubs"; const iOSPlatformName = "ios"; const androidPlatformName = "android"; @@ -17,10 +18,13 @@ function createTestInjector(): IInjector { testInjector.register("hooksService", {}); testInjector.register("hostInfo", {}); testInjector.register("logger", {}); - testInjector.register("errors", {}); + testInjector.register("errors", ErrorsStub); testInjector.register("packageInstallationManager", {}); testInjector.register("mobileHelper", {}); testInjector.register("cleanupService", {}); + testInjector.register("fs", { + exists: (filePath: string) => true + }); return testInjector; } @@ -87,4 +91,22 @@ describe("WebpackCompilerService", () => { assert.deepEqual(androidResult.emittedFiles, ["bundle.hash6.hot-update.js", "hash6.hot-update.json"]); }); }); + + describe("compileWithWatch", () => { + it("fails when the value set for webpackConfigPath is not existant file", async () => { + const webpackConfigPath = "some path.js"; + testInjector.resolve("fs").exists = (filePath: string) => filePath !== webpackConfigPath; + await assert.isRejected(webpackCompilerService.compileWithWatch({ platformNameLowerCase: "android" }, { webpackConfigPath }, {}), + `The webpack configuration file ${webpackConfigPath} does not exist. Ensure you have such file or set correct path in nsconfig.json`); + }); + }); + + describe("compileWithoutWatch", () => { + it("fails when the value set for webpackConfigPath is not existant file", async () => { + const webpackConfigPath = "some path.js"; + testInjector.resolve("fs").exists = (filePath: string) => filePath !== webpackConfigPath; + await assert.isRejected(webpackCompilerService.compileWithoutWatch({ platformNameLowerCase: "android" }, { webpackConfigPath }, {}), + `The webpack configuration file ${webpackConfigPath} does not exist. Ensure you have such file or set correct path in nsconfig.json`); + }); + }); }); diff --git a/test/stubs.ts b/test/stubs.ts index 6e12d8a4ac..af3d18a719 100644 --- a/test/stubs.ts +++ b/test/stubs.ts @@ -328,6 +328,7 @@ export class NodePackageManagerStub implements INodePackageManager { export class ProjectDataStub implements IProjectData { projectDir: string; projectName: string; + webpackConfigPath: string; get platformsDir(): string { return this.platformsDirCache || (this.projectDir && join(this.projectDir, "platforms")) || ""; } From 5634f41a1ddb43b3edb04cef6b91e5b01a747a5f Mon Sep 17 00:00:00 2001 From: rosen-vladimirov Date: Wed, 15 Jan 2020 15:30:06 +0200 Subject: [PATCH 2/2] chore: set version to 6.4.0 --- npm-shrinkwrap.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index eb1117574b..400806a91c 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -1,6 +1,6 @@ { "name": "nativescript", - "version": "6.3.3", + "version": "6.4.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 612a03d301..3f42f9ae0d 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "nativescript", "preferGlobal": true, - "version": "6.3.3", + "version": "6.4.0", "author": "Telerik ", "description": "Command-line interface for building NativeScript projects", "bin": {