From ff7de65a5eea3ce9ff0d9e048f33d922f03da4ec Mon Sep 17 00:00:00 2001 From: AgentEnder Date: Tue, 14 Nov 2023 11:20:55 -0500 Subject: [PATCH 1/3] fix(web): file-server should accept buildTarget without projectName --- .../file-server/file-server.impl.spec.ts | 57 +++++++++++++++++++ .../executors/file-server/file-server.impl.ts | 22 ++++++- 2 files changed, 77 insertions(+), 2 deletions(-) create mode 100644 packages/web/src/executors/file-server/file-server.impl.spec.ts diff --git a/packages/web/src/executors/file-server/file-server.impl.spec.ts b/packages/web/src/executors/file-server/file-server.impl.spec.ts new file mode 100644 index 0000000000000..a2e29105287a3 --- /dev/null +++ b/packages/web/src/executors/file-server/file-server.impl.spec.ts @@ -0,0 +1,57 @@ +import { ExecutorContext } from '@nx/devkit'; +import { normalizeOptions } from './file-server.impl'; +import { Schema } from './schema'; + +describe('file-server impl', () => { + describe('normalizeOptions', () => { + it('should normalize build target', () => { + const context: ExecutorContext = { + root: '/', + cwd: '/', + isVerbose: false, + projectGraph: { + nodes: { + root: { + data: { + targets: { + build: { configurations: 'production' }, + 'build:test': {}, + }, + }, + } as any, + }, + dependencies: {}, + }, + projectName: 'root', + }; + expect( + normalizeOptions({ buildTarget: 'build' } as Schema, context) + ).toEqual({ + buildTarget: 'root:build', + }); + expect( + normalizeOptions({ buildTarget: 'root:build' } as Schema, context) + ).toEqual({ + buildTarget: 'root:build', + }); + expect( + normalizeOptions({ buildTarget: 'build:production' } as Schema, context) + ).toEqual({ + buildTarget: 'root:build:production', + }); + expect( + normalizeOptions( + { buildTarget: 'root:build:production' } as Schema, + context + ) + ).toEqual({ + buildTarget: 'root:build:production', + }); + expect( + normalizeOptions({ buildTarget: 'build:test' } as Schema, context) + ).toEqual({ + buildTarget: 'root:build:test', + }); + }); + }); +}); diff --git a/packages/web/src/executors/file-server/file-server.impl.ts b/packages/web/src/executors/file-server/file-server.impl.ts index e009812f71942..5230559e47ae8 100644 --- a/packages/web/src/executors/file-server/file-server.impl.ts +++ b/packages/web/src/executors/file-server/file-server.impl.ts @@ -109,6 +109,26 @@ function createFileWatcher( ); } +export function normalizeOptions(options: Schema, context: ExecutorContext) { + const result = { ...options }; + + // Normalizes build target to be project:target:configuration, + // while keeping support for just `target` or `target:configuration` + if (result.buildTarget) { + const { target, project, configuration } = parseTargetString( + options.buildTarget, + context + ); + result.buildTarget = [ + project, + target, + ...(configuration ? [configuration] : []), + ].join(':'); + } + + return result; +} + export default async function* fileServerExecutor( options: Schema, context: ExecutorContext @@ -146,8 +166,6 @@ export default async function* fileServerExecutor( }; if (options.watch) { - const projectRoot = - context.projectsConfigurations.projects[context.projectName].root; disposeWatch = await createFileWatcher(context.projectName, run); } From 6beb85e639658a5d1b4d6823e8a48f62d7f82d53 Mon Sep 17 00:00:00 2001 From: AgentEnder Date: Tue, 14 Nov 2023 11:33:19 -0500 Subject: [PATCH 2/3] cleanup(web): move file-server generator to leave out projectName where possible --- .../packages/cypress/executors/cypress.json | 2 +- .../__snapshots__/application.spec.ts.snap | 8 +++--- .../src/generators/application/lib/add-e2e.ts | 2 +- .../setup-mf/lib/setup-serve-target.ts | 2 +- packages/cypress/docs/cypress-examples.md | 2 +- .../application/application.spec.ts | 10 ++++---- .../generators/application/lib/add-project.ts | 6 ++--- .../lib/add-files.ts | 2 +- .../rules/update-module-federation-project.ts | 2 +- packages/react/src/utils/ct-utils.ts | 25 ++++++++++++++----- packages/vite/src/utils/generator-utils.ts | 14 +++++------ .../__snapshots__/application.spec.ts.snap | 14 +++++------ .../executors/file-server/file-server.impl.ts | 4 ++- .../application/application.spec.ts | 10 ++++---- .../static-serve-configuration.spec.ts | 10 ++++---- .../static-serve-configuration.ts | 15 ++++++----- .../configuration/configuration.spec.ts | 4 +-- .../generators/configuration/configuration.ts | 4 +-- 18 files changed, 77 insertions(+), 59 deletions(-) diff --git a/docs/generated/packages/cypress/executors/cypress.json b/docs/generated/packages/cypress/executors/cypress.json index 82dbf95fbaac6..5db9aa9329d42 100644 --- a/docs/generated/packages/cypress/executors/cypress.json +++ b/docs/generated/packages/cypress/executors/cypress.json @@ -153,7 +153,7 @@ }, "additionalProperties": true, "required": ["cypressConfig"], - "examplesFile": "Depending on your testing type, the Cypress executor is configured in different ways. The following are sample configurations that are created via the [configuration](/packages/cypress/generators/configuration) and [cypress-component-configuration](/packages/cypress/generators/cypress-component-configuration) generators.\n\n{% tabs %}\n{% tab label=\"E2E Testing\" %}\n\n```json\n\"targets\": {\n \"e2e\": {\n \"executor\": \"@nx/cypress:cypress\",\n \"options\": {\n \"cypressConfig\": \"apps/app-e2e/cypres.config.ts\",\n \"devServerTarget\": \"my-react-app:serve\",\n \"testingType\": \"e2e\"\n }\n }\n}\n```\n\n{% callout type=\"note\" title=\"API Testing\" %}\nAPI testing with Cypress is the same setup as e2e testing. Just change which `devServerTarget` is used!\n{% /callout %}\n\n### Providing a Base URL\n\nIf `devServerTarget` is provided, the url returned from started the dev server will be passed to cypress as the `baseUrl` option.\n\nDefining a `baseUrl` in the executor options will override the inferred `baseUrl` from the `devServerTarget`.\n\nThe `baseUrl` defined in the Cypress config file is the last value used if no url is found in the `devServerTarget` or executor options.\n\n### Static Serving\n\nWhen running in CI it doesn't make sense to start up a dev server since there aren't changes to watch for.\n\nYou can use [`@nx/web:file-server`](/packages/web/executors/file-server) to serve the pre-built static files of your frontend project.\n\nIn some _frontend_ application, add a 'static-serve' target.\n\n```json\n\"serve-static\": {\n \"executor\": \"@nx/web:file-server\",\n \"options\":{\n \"buildTarget\": \"frontend:build\"\n }\n}\n```\n\nIn the _e2e_ application add a configuration to change `devServerTarget` to point to the `static-serve` from the _frontend_ application\n\n```json\n\"e2e\": {\n //...\n \"configurations\": {\n \"ci\": {\n \"devServerTarget\": \"frontend:serve-static\"\n }\n }\n}\n```\n\n{% callout type=\"note\" title=\"What about Node projects?\" %}\nThe same can be done for backend node apps with [`@nx/js:node` executor](/packages/js/executors/node)\n{% /callout %}\n\n```bash\nnx e2e my-app-e2e --configuration=ci\n```\n\n{% /tab %}\n{% tab label=\"Component Testing\" %}\n\n{% callout type=\"note\" title=\"Cypress Component Testing\" %}\nWhen adding component testing to a project, it's best to use the framework specific generator, instead `cypress-component-project` directly.\n\n- [React component testing](/packages/react/generators/cypress-component-configuration)\n- [Angular component testing](/packages/angular/generators/cypress-component-configuration)\n\n{% /callout %}\n\n```json\n\"targets\": {\n \"component-test\": {\n \"executor\": \"@nx/cypress:cypress\",\n \"options\": {\n \"cypressConfig\": \"apps/app/cypres.config.ts\",\n \"devServerTarget\": \"my-react-app:build\",\n \"testingType\": \"component\",\n \"skipServe\": true\n }\n }\n}\n```\n\nIt's important `skipServe` is set to true. Nx doesn't need to run the `devServerTarget`, Cypress creates its own dev server for component testing.\nInstead, Nx needs to know what build target to create the correct configuration to pass to Cypress, which is why it's still used in component testing.\n\n{% /tab %}\n{% /tabs %}\n\n### Environment Variables\n\nUsing [executor configurations](recipes/executors/use-executor-configurations#use-executor-configurations) offers flexibility to set environment variables\n\n```json\n\"targets\": {\n \"e2e\": {\n \"executor\": \"@nx/cypress:cypress\",\n \"options\": {\n \"cypressConfig\": \"apps/app-e2e/cypres.config.ts\",\n \"devServerTarget\": \"my-react-app:serve\",\n \"testingType\": \"e2e\"\n },\n \"configurations\": {\n \"qa\": {\n \"env\": {\n \"API_URL\": \"https://api.qa.company.com\"\n }\n },\n \"dev\": {\n \"env\": {\n \"API_URL\": \"http://localhost:3333/api\"\n }\n }\n }\n }\n}\n```\n\nRead more on different ways to use [environment variables for cypress executor](/packages/cypress#environment-variables)\n" + "examplesFile": "Depending on your testing type, the Cypress executor is configured in different ways. The following are sample configurations that are created via the [configuration](/packages/cypress/generators/configuration) and [cypress-component-configuration](/packages/cypress/generators/cypress-component-configuration) generators.\n\n{% tabs %}\n{% tab label=\"E2E Testing\" %}\n\n```json\n\"targets\": {\n \"e2e\": {\n \"executor\": \"@nx/cypress:cypress\",\n \"options\": {\n \"cypressConfig\": \"apps/app-e2e/cypres.config.ts\",\n \"devServerTarget\": \"my-react-app:serve\",\n \"testingType\": \"e2e\"\n }\n }\n}\n```\n\n{% callout type=\"note\" title=\"API Testing\" %}\nAPI testing with Cypress is the same setup as e2e testing. Just change which `devServerTarget` is used!\n{% /callout %}\n\n### Providing a Base URL\n\nIf `devServerTarget` is provided, the url returned from started the dev server will be passed to cypress as the `baseUrl` option.\n\nDefining a `baseUrl` in the executor options will override the inferred `baseUrl` from the `devServerTarget`.\n\nThe `baseUrl` defined in the Cypress config file is the last value used if no url is found in the `devServerTarget` or executor options.\n\n### Static Serving\n\nWhen running in CI it doesn't make sense to start up a dev server since there aren't changes to watch for.\n\nYou can use [`@nx/web:file-server`](/packages/web/executors/file-server) to serve the pre-built static files of your frontend project.\n\nIn some _frontend_ application, add a 'static-serve' target.\n\n```json\n\"serve-static\": {\n \"executor\": \"@nx/web:file-server\",\n \"options\":{\n \"buildTarget\": \"build\"\n }\n}\n```\n\nIn the _e2e_ application add a configuration to change `devServerTarget` to point to the `static-serve` from the _frontend_ application\n\n```json\n\"e2e\": {\n //...\n \"configurations\": {\n \"ci\": {\n \"devServerTarget\": \"frontend:serve-static\"\n }\n }\n}\n```\n\n{% callout type=\"note\" title=\"What about Node projects?\" %}\nThe same can be done for backend node apps with [`@nx/js:node` executor](/packages/js/executors/node)\n{% /callout %}\n\n```bash\nnx e2e my-app-e2e --configuration=ci\n```\n\n{% /tab %}\n{% tab label=\"Component Testing\" %}\n\n{% callout type=\"note\" title=\"Cypress Component Testing\" %}\nWhen adding component testing to a project, it's best to use the framework specific generator, instead `cypress-component-project` directly.\n\n- [React component testing](/packages/react/generators/cypress-component-configuration)\n- [Angular component testing](/packages/angular/generators/cypress-component-configuration)\n\n{% /callout %}\n\n```json\n\"targets\": {\n \"component-test\": {\n \"executor\": \"@nx/cypress:cypress\",\n \"options\": {\n \"cypressConfig\": \"apps/app/cypres.config.ts\",\n \"devServerTarget\": \"my-react-app:build\",\n \"testingType\": \"component\",\n \"skipServe\": true\n }\n }\n}\n```\n\nIt's important `skipServe` is set to true. Nx doesn't need to run the `devServerTarget`, Cypress creates its own dev server for component testing.\nInstead, Nx needs to know what build target to create the correct configuration to pass to Cypress, which is why it's still used in component testing.\n\n{% /tab %}\n{% /tabs %}\n\n### Environment Variables\n\nUsing [executor configurations](recipes/executors/use-executor-configurations#use-executor-configurations) offers flexibility to set environment variables\n\n```json\n\"targets\": {\n \"e2e\": {\n \"executor\": \"@nx/cypress:cypress\",\n \"options\": {\n \"cypressConfig\": \"apps/app-e2e/cypres.config.ts\",\n \"devServerTarget\": \"my-react-app:serve\",\n \"testingType\": \"e2e\"\n },\n \"configurations\": {\n \"qa\": {\n \"env\": {\n \"API_URL\": \"https://api.qa.company.com\"\n }\n },\n \"dev\": {\n \"env\": {\n \"API_URL\": \"http://localhost:3333/api\"\n }\n }\n }\n }\n}\n```\n\nRead more on different ways to use [environment variables for cypress executor](/packages/cypress#environment-variables)\n" }, "description": "Run Cypress E2E tests.", "aliases": [], diff --git a/packages/angular/src/generators/application/__snapshots__/application.spec.ts.snap b/packages/angular/src/generators/application/__snapshots__/application.spec.ts.snap index f082cff7abafc..07e1cef5193d1 100644 --- a/packages/angular/src/generators/application/__snapshots__/application.spec.ts.snap +++ b/packages/angular/src/generators/application/__snapshots__/application.spec.ts.snap @@ -292,7 +292,7 @@ exports[`app --project-name-and-root-format=derived should generate correctly wh "serve-static": { "executor": "@nx/web:file-server", "options": { - "buildTarget": "my-dir-my-app:build", + "buildTarget": "build", "staticFilePath": "dist/apps/my-dir/my-app/browser", }, }, @@ -528,7 +528,7 @@ exports[`app --project-name-and-root-format=derived should generate correctly wh "serve-static": { "executor": "@nx/web:file-server", "options": { - "buildTarget": "my-app:build", + "buildTarget": "build", "staticFilePath": "dist/apps/my-app/browser", }, }, @@ -988,7 +988,7 @@ exports[`app nested should create project configs 1`] = ` "serve-static": { "executor": "@nx/web:file-server", "options": { - "buildTarget": "my-app:build", + "buildTarget": "build", "staticFilePath": "dist/my-dir/my-app/browser", }, }, @@ -1137,7 +1137,7 @@ exports[`app not nested should create project configs 1`] = ` "serve-static": { "executor": "@nx/web:file-server", "options": { - "buildTarget": "my-app:build", + "buildTarget": "build", "staticFilePath": "dist/my-app/browser", }, }, diff --git a/packages/angular/src/generators/application/lib/add-e2e.ts b/packages/angular/src/generators/application/lib/add-e2e.ts index 9719db5b6dce9..4752ebe95dfc7 100644 --- a/packages/angular/src/generators/application/lib/add-e2e.ts +++ b/packages/angular/src/generators/application/lib/add-e2e.ts @@ -79,7 +79,7 @@ function addFileServerTarget( projectConfig.targets[targetName] = { executor: '@nx/web:file-server', options: { - buildTarget: `${options.name}:build`, + buildTarget: 'build', port: options.port, staticFilePath: isUsingApplicationBuilder ? joinPathFragments(options.outputPath, 'browser') diff --git a/packages/angular/src/generators/setup-mf/lib/setup-serve-target.ts b/packages/angular/src/generators/setup-mf/lib/setup-serve-target.ts index 52278f4df58a2..b1cbbd4990c22 100644 --- a/packages/angular/src/generators/setup-mf/lib/setup-serve-target.ts +++ b/packages/angular/src/generators/setup-mf/lib/setup-serve-target.ts @@ -26,7 +26,7 @@ export function setupServeTarget(host: Tree, options: Schema) { executor: '@nx/web:file-server', defaultConfiguration: 'production', options: { - buildTarget: `${options.appName}:build`, + buildTarget: 'build', port: options.port, watch: false, }, diff --git a/packages/cypress/docs/cypress-examples.md b/packages/cypress/docs/cypress-examples.md index 5214dacf712d9..af44cbaa38b9a 100644 --- a/packages/cypress/docs/cypress-examples.md +++ b/packages/cypress/docs/cypress-examples.md @@ -40,7 +40,7 @@ In some _frontend_ application, add a 'static-serve' target. "serve-static": { "executor": "@nx/web:file-server", "options":{ - "buildTarget": "frontend:build" + "buildTarget": "build" } } ``` diff --git a/packages/react/src/generators/application/application.spec.ts b/packages/react/src/generators/application/application.spec.ts index b25be440359fc..b1d99af9e60aa 100644 --- a/packages/react/src/generators/application/application.spec.ts +++ b/packages/react/src/generators/application/application.spec.ts @@ -436,11 +436,11 @@ describe('app', () => { const targetConfig = projectsConfigurations.get('my-app').targets; expect(targetConfig.serve.executor).toEqual('@nx/webpack:dev-server'); expect(targetConfig.serve.options).toEqual({ - buildTarget: 'my-app:build', + buildTarget: 'build', hmr: true, }); expect(targetConfig.serve.configurations.production).toEqual({ - buildTarget: 'my-app:build:production', + buildTarget: 'build:production', hmr: false, }); }); @@ -456,10 +456,10 @@ describe('app', () => { const targetConfig = projectsConfigurations.get('my-app').targets; expect(targetConfig.serve.executor).toEqual('@nx/vite:dev-server'); expect(targetConfig.serve.options).toEqual({ - buildTarget: 'my-app:build', + buildTarget: 'build', }); expect(targetConfig.serve.configurations.production).toEqual({ - buildTarget: 'my-app:build:production', + buildTarget: 'build:production', hmr: false, }); }); @@ -1026,7 +1026,7 @@ describe('app', () => { expect(targetConfig.build.executor).toEqual('@nx/vite:build'); expect(targetConfig.serve.executor).toEqual('@nx/vite:dev-server'); expect(targetConfig.serve.options).toEqual({ - buildTarget: 'my-app:build', + buildTarget: 'build', }); }); diff --git a/packages/react/src/generators/application/lib/add-project.ts b/packages/react/src/generators/application/lib/add-project.ts index 5a2075995e779..7e13f64ff9aaf 100644 --- a/packages/react/src/generators/application/lib/add-project.ts +++ b/packages/react/src/generators/application/lib/add-project.ts @@ -109,15 +109,15 @@ function createServeTarget(options: NormalizedSchema): TargetConfiguration { executor: '@nx/webpack:dev-server', defaultConfiguration: 'development', options: { - buildTarget: `${options.projectName}:build`, + buildTarget: `build`, hmr: true, }, configurations: { development: { - buildTarget: `${options.projectName}:build:development`, + buildTarget: `build:development`, }, production: { - buildTarget: `${options.projectName}:build:production`, + buildTarget: `build:production`, hmr: false, }, }, diff --git a/packages/react/src/generators/cypress-component-configuration/lib/add-files.ts b/packages/react/src/generators/cypress-component-configuration/lib/add-files.ts index 5ae0c0f82753d..051b0b52a6f20 100644 --- a/packages/react/src/generators/cypress-component-configuration/lib/add-files.ts +++ b/packages/react/src/generators/cypress-component-configuration/lib/add-files.ts @@ -28,7 +28,7 @@ export async function addFiles( const actualBundler = options.buildTarget !== undefined && options.bundler ? options.bundler - : await getBundlerFromTarget(found, tree); + : await getBundlerFromTarget(tree, found, projectConfig); if (options.bundler && options.bundler !== actualBundler) { logger.warn( diff --git a/packages/react/src/rules/update-module-federation-project.ts b/packages/react/src/rules/update-module-federation-project.ts index 02c4c787dec50..bfb75cae60365 100644 --- a/packages/react/src/rules/update-module-federation-project.ts +++ b/packages/react/src/rules/update-module-federation-project.ts @@ -57,7 +57,7 @@ export function updateModuleFederationProject( executor: '@nx/web:file-server', defaultConfiguration: 'production', options: { - buildTarget: `${options.projectName}:build`, + buildTarget: 'build', watch: false, port: options.devServerPort, }, diff --git a/packages/react/src/utils/ct-utils.ts b/packages/react/src/utils/ct-utils.ts index 6c244a5da26df..a626dd47f3c94 100644 --- a/packages/react/src/utils/ct-utils.ts +++ b/packages/react/src/utils/ct-utils.ts @@ -1,6 +1,7 @@ import { createProjectGraphAsync, parseTargetString, + ProjectConfiguration, readProjectConfiguration, Tree, updateProjectConfiguration, @@ -58,8 +59,9 @@ function assertValidConfig(config: unknown) { } export async function getBundlerFromTarget( + tree: Tree, found: FoundTarget, - tree: Tree + projectConfig: ProjectConfiguration ): Promise<'vite' | 'webpack'> { if (found.target && found.config?.executor) { return found.config.executor === '@nrwl/vite:build' || @@ -68,11 +70,22 @@ export async function getBundlerFromTarget( : 'webpack'; } - const { target, project } = parseTargetString( - found.target, - await createProjectGraphAsync() - ); - const projectConfig = readProjectConfiguration(tree, project); + const graph = await createProjectGraphAsync(); + const { target, project } = (() => { + try { + return parseTargetString(found.target, graph); + } catch { + return parseTargetString( + [projectConfig.name, found.target].join(':'), + graph + ); + } + })(); + + if (project !== projectConfig.name) { + projectConfig = readProjectConfiguration(tree, project); + } + const executor = projectConfig?.targets?.[target]?.executor; return executor === '@nrwl/vite:build' || executor === '@nx/vite:build' ? 'vite' diff --git a/packages/vite/src/utils/generator-utils.ts b/packages/vite/src/utils/generator-utils.ts index 97ce1e716625f..cd2a5890374ca 100644 --- a/packages/vite/src/utils/generator-utils.ts +++ b/packages/vite/src/utils/generator-utils.ts @@ -256,7 +256,7 @@ export function addOrChangeServeTarget( if (project.targets[target]) { const serveTarget = project.targets[target]; const serveOptions: ViteDevServerExecutorOptions = { - buildTarget: `${options.project}:build`, + buildTarget: `build`, https: project.targets[target].options?.https, hmr: project.targets[target].options?.hmr, open: project.targets[target].options?.open, @@ -271,15 +271,15 @@ export function addOrChangeServeTarget( executor: '@nx/vite:dev-server', defaultConfiguration: 'development', options: { - buildTarget: `${options.project}:build`, + buildTarget: `build`, }, configurations: { development: { - buildTarget: `${options.project}:build:development`, + buildTarget: `build:development`, hmr: true, }, production: { - buildTarget: `${options.project}:build:production`, + buildTarget: `build:production`, hmr: false, }, }, @@ -305,7 +305,7 @@ export function addPreviewTarget( const project = readProjectConfiguration(tree, options.project); const previewOptions: VitePreviewServerExecutorOptions = { - buildTarget: `${options.project}:build`, + buildTarget: `build`, }; project.targets ??= {}; @@ -327,10 +327,10 @@ export function addPreviewTarget( options: previewOptions, configurations: { development: { - buildTarget: `${options.project}:build:development`, + buildTarget: `build:development`, }, production: { - buildTarget: `${options.project}:build:production`, + buildTarget: `build:production`, }, }, }; diff --git a/packages/vue/src/generators/application/__snapshots__/application.spec.ts.snap b/packages/vue/src/generators/application/__snapshots__/application.spec.ts.snap index 2e704767b777f..e5c16b33b91c7 100644 --- a/packages/vue/src/generators/application/__snapshots__/application.spec.ts.snap +++ b/packages/vue/src/generators/application/__snapshots__/application.spec.ts.snap @@ -112,15 +112,15 @@ exports[`application generator should set up project correctly with given option "executor": "@nx/vite:dev-server", "defaultConfiguration": "development", "options": { - "buildTarget": "test:build" + "buildTarget": "build" }, "configurations": { "development": { - "buildTarget": "test:build:development", + "buildTarget": "build:development", "hmr": true }, "production": { - "buildTarget": "test:build:production", + "buildTarget": "build:production", "hmr": false } } @@ -129,14 +129,14 @@ exports[`application generator should set up project correctly with given option "executor": "@nx/vite:preview-server", "defaultConfiguration": "development", "options": { - "buildTarget": "test:build" + "buildTarget": "build" }, "configurations": { "development": { - "buildTarget": "test:build:development" + "buildTarget": "build:development" }, "production": { - "buildTarget": "test:build:production" + "buildTarget": "build:production" } } }, @@ -151,7 +151,7 @@ exports[`application generator should set up project correctly with given option "serve-static": { "executor": "@nx/web:file-server", "options": { - "buildTarget": "test:build" + "buildTarget": "build" } } } diff --git a/packages/web/src/executors/file-server/file-server.impl.ts b/packages/web/src/executors/file-server/file-server.impl.ts index 5230559e47ae8..bd87c1a380e38 100644 --- a/packages/web/src/executors/file-server/file-server.impl.ts +++ b/packages/web/src/executors/file-server/file-server.impl.ts @@ -111,7 +111,7 @@ function createFileWatcher( export function normalizeOptions(options: Schema, context: ExecutorContext) { const result = { ...options }; - + // Normalizes build target to be project:target:configuration, // while keeping support for just `target` or `target:configuration` if (result.buildTarget) { @@ -133,6 +133,8 @@ export default async function* fileServerExecutor( options: Schema, context: ExecutorContext ) { + options = normalizeOptions(options, context); + if (!options.buildTarget && !options.staticFilePath) { throw new Error("You must set either 'buildTarget' or 'staticFilePath'."); } diff --git a/packages/web/src/generators/application/application.spec.ts b/packages/web/src/generators/application/application.spec.ts index 3f89a33c022d3..4652e0a43da2e 100644 --- a/packages/web/src/generators/application/application.spec.ts +++ b/packages/web/src/generators/application/application.spec.ts @@ -393,10 +393,10 @@ describe('app', () => { const targets = readProjectConfiguration(tree, 'my-app').targets; expect(targets.serve.executor).toEqual('@nx/webpack:dev-server'); expect(targets.serve.options).toEqual({ - buildTarget: 'my-app:build', + buildTarget: 'build', }); expect(targets.serve.configurations.production).toEqual({ - buildTarget: 'my-app:build:production', + buildTarget: 'build:production', }); }); @@ -425,10 +425,10 @@ describe('app', () => { const targets = readProjectConfiguration(tree, 'my-app').targets; expect(targets.serve.executor).toEqual('@nx/vite:dev-server'); expect(targets.serve.options).toEqual({ - buildTarget: 'my-app:build', + buildTarget: 'build', }); expect(targets.serve.configurations.production).toEqual({ - buildTarget: 'my-app:build:production', + buildTarget: 'build:production', hmr: false, }); }); @@ -654,7 +654,7 @@ describe('app', () => { expect(targetConfig.build.executor).toEqual('@nx/vite:build'); expect(targetConfig.serve.executor).toEqual('@nx/vite:dev-server'); expect(targetConfig.serve.options).toEqual({ - buildTarget: 'my-app:build', + buildTarget: 'build', }); }); it('should add dependencies in package.json', () => { diff --git a/packages/web/src/generators/static-serve/static-serve-configuration.spec.ts b/packages/web/src/generators/static-serve/static-serve-configuration.spec.ts index 11cfc7a3ec995..dd6e1447cfa33 100644 --- a/packages/web/src/generators/static-serve/static-serve-configuration.spec.ts +++ b/packages/web/src/generators/static-serve/static-serve-configuration.spec.ts @@ -27,7 +27,7 @@ describe('Static serve configuration generator', () => { { "executor": "@nx/web:file-server", "options": { - "buildTarget": "react-app:build", + "buildTarget": "build", }, } `); @@ -41,7 +41,7 @@ describe('Static serve configuration generator', () => { { "executor": "@nx/web:file-server", "options": { - "buildTarget": "angular-app:build", + "buildTarget": "build", }, } `); @@ -54,7 +54,7 @@ describe('Static serve configuration generator', () => { { "executor": "@nx/web:file-server", "options": { - "buildTarget": "storybook:build-storybook", + "buildTarget": "build-storybook", "staticFilePath": "dist/storybook/storybook", }, } @@ -74,7 +74,7 @@ describe('Static serve configuration generator', () => { { "executor": "@nx/web:file-server", "options": { - "buildTarget": "react-app:build", + "buildTarget": "build", }, } `); @@ -99,7 +99,7 @@ describe('Static serve configuration generator', () => { { "executor": "@nx/web:file-server", "options": { - "buildTarget": "angular-app:build", + "buildTarget": "build", "staticFilePath": "dist/angular-app", }, } diff --git a/packages/web/src/generators/static-serve/static-serve-configuration.ts b/packages/web/src/generators/static-serve/static-serve-configuration.ts index 4d2e89efb479d..8a783c138680c 100644 --- a/packages/web/src/generators/static-serve/static-serve-configuration.ts +++ b/packages/web/src/generators/static-serve/static-serve-configuration.ts @@ -32,22 +32,25 @@ function normalizeOptions( tree: Tree, options: WebStaticServeSchema ): NormalizedWebStaticServeSchema { - const target = parseTargetString(options.buildTarget); + const { project, target, configuration } = parseTargetString( + options.buildTarget + ); const opts: NormalizedWebStaticServeSchema = { ...options, targetName: options.targetName || 'serve-static', - projectName: target.project, + projectName: project, + buildTarget: [target, ...(configuration ? [configuration] : [])].join(':'), }; - const projectConfig = readProjectConfiguration(tree, target.project); - const buildTargetConfig = projectConfig?.targets?.[target.target]; + const projectConfig = readProjectConfiguration(tree, project); + const buildTargetConfig = projectConfig?.targets?.[target]; if (!buildTargetConfig) { throw new Error(stripIndents`Unable to read the target configuration for the provided build target, ${opts.buildTarget} Are you sure this target exists?`); } if (projectConfig.targets[opts.targetName]) { - throw new Error(stripIndents`Project ${target.project} already has a '${opts.targetName}' target configured. + throw new Error(stripIndents`Project ${project} already has a '${opts.targetName}' target configured. Either rename or remove the existing '${opts.targetName}' target and try again. Optionally, you can provide a different name with the --target-name option other than '${opts.targetName}'`); } @@ -77,7 +80,7 @@ Optionally, you can provide a different name with the --target-name option other opts.outputPath = buildTargetConfig.options?.outputDir || maybeOutputValue; if (opts.outputPath) { logger.warn(`Automatically detected the output path to be ${opts.outputPath}. -If this is incorrect, the update the staticFilePath option in the ${target.project}:${opts.targetName} target configuration`); +If this is incorrect, the update the staticFilePath option in the ${project}:${opts.targetName} target configuration`); } else { logger.warn( stripIndents`${opts.buildTarget} did not have an outputPath property set and --output-path was not provided. diff --git a/packages/webpack/src/generators/configuration/configuration.spec.ts b/packages/webpack/src/generators/configuration/configuration.spec.ts index 0430b754cd35f..6639a0f50ad13 100644 --- a/packages/webpack/src/generators/configuration/configuration.spec.ts +++ b/packages/webpack/src/generators/configuration/configuration.spec.ts @@ -90,11 +90,11 @@ describe('webpackProject', () => { serve: { executor: '@nx/webpack:dev-server', options: { - buildTarget: 'mypkg:build', + buildTarget: 'build', }, configurations: { production: { - buildTarget: `mypkg:build:production`, + buildTarget: `build:production`, }, }, }, diff --git a/packages/webpack/src/generators/configuration/configuration.ts b/packages/webpack/src/generators/configuration/configuration.ts index 4d2a953f95578..a60dab4146331 100644 --- a/packages/webpack/src/generators/configuration/configuration.ts +++ b/packages/webpack/src/generators/configuration/configuration.ts @@ -140,11 +140,11 @@ function addServeTarget(tree: Tree, options: ConfigurationGeneratorSchema) { serve: { executor: '@nx/webpack:dev-server', options: { - buildTarget: `${options.project}:build`, + buildTarget: `build`, }, configurations: { production: { - buildTarget: `${options.project}:build:production`, + buildTarget: `build:production`, }, }, }, From caf4639796d4bf457a74a224f59780409f9652ae Mon Sep 17 00:00:00 2001 From: AgentEnder Date: Tue, 14 Nov 2023 11:20:55 -0500 Subject: [PATCH 3/3] fix(web): file-server should accept buildTarget without projectName --- packages/web/src/executors/file-server/file-server.impl.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/web/src/executors/file-server/file-server.impl.ts b/packages/web/src/executors/file-server/file-server.impl.ts index bd87c1a380e38..0c28547185721 100644 --- a/packages/web/src/executors/file-server/file-server.impl.ts +++ b/packages/web/src/executors/file-server/file-server.impl.ts @@ -111,7 +111,6 @@ function createFileWatcher( export function normalizeOptions(options: Schema, context: ExecutorContext) { const result = { ...options }; - // Normalizes build target to be project:target:configuration, // while keeping support for just `target` or `target:configuration` if (result.buildTarget) {