diff --git a/docs/generated/packages/angular/executors/dev-server.json b/docs/generated/packages/angular/executors/dev-server.json index a91014df74..dd339c4915 100644 --- a/docs/generated/packages/angular/executors/dev-server.json +++ b/docs/generated/packages/angular/executors/dev-server.json @@ -150,6 +150,11 @@ "type": "string", "description": "The path to the middleware function. Relative to the workspace root." } + }, + "watchDependencies": { + "type": "boolean", + "description": "Watch buildable dependencies and rebuild when they change.", + "default": true } }, "additionalProperties": false, diff --git a/docs/generated/packages/angular/executors/webpack-browser.json b/docs/generated/packages/angular/executors/webpack-browser.json index 7e43109269..e210725ee5 100644 --- a/docs/generated/packages/angular/executors/webpack-browser.json +++ b/docs/generated/packages/angular/executors/webpack-browser.json @@ -561,6 +561,11 @@ "type": "boolean", "description": "Read buildable libraries from source instead of building them separately.", "default": true + }, + "watchDependencies": { + "type": "boolean", + "description": "Watch buildable dependencies and rebuild when they change.", + "default": true } }, "additionalProperties": false, diff --git a/docs/shared/packages/webpack/webpack-plugins.md b/docs/shared/packages/webpack/webpack-plugins.md index f9045c4ebf..40fb33bc59 100644 --- a/docs/shared/packages/webpack/webpack-plugins.md +++ b/docs/shared/packages/webpack/webpack-plugins.md @@ -301,6 +301,12 @@ Type: `boolean` Watch for file changes. +##### watchDependencies + +Type: `boolean` + +Watch for buildable dependencies and rebuild when they change. Default is `true`. + #### Example ```js diff --git a/packages/angular/src/builders/dev-server/dev-server.impl.ts b/packages/angular/src/builders/dev-server/dev-server.impl.ts index c897ff47ad..5d8f674fae 100644 --- a/packages/angular/src/builders/dev-server/dev-server.impl.ts +++ b/packages/angular/src/builders/dev-server/dev-server.impl.ts @@ -214,7 +214,8 @@ export function executeDevServerBuilder( new WebpackNxBuildCoordinationPlugin( `nx run-many --target=${ parsedBuildTarget.target - } --projects=${workspaceDependencies.join(',')}` + } --projects=${workspaceDependencies.join(',')}`, + { skipWatchingDeps: !options.watchDependencies } ) ); } @@ -269,6 +270,7 @@ function getDelegateBuilderOptions( // delete extra option not supported by the delegate builder delete delegateBuilderOptions.buildLibsFromSource; + delete delegateBuilderOptions.watchDependencies; return delegateBuilderOptions; } diff --git a/packages/angular/src/builders/dev-server/lib/normalize-options.ts b/packages/angular/src/builders/dev-server/lib/normalize-options.ts index ca28d53f8f..4559be275c 100644 --- a/packages/angular/src/builders/dev-server/lib/normalize-options.ts +++ b/packages/angular/src/builders/dev-server/lib/normalize-options.ts @@ -24,5 +24,6 @@ export function normalizeOptions(schema: Schema): NormalizedSchema { hmr: schema.hmr ?? (angularMajorVersion < 19 ? false : undefined), open: schema.open ?? false, ssl: schema.ssl ?? false, + watchDependencies: schema.watchDependencies ?? true, }; } diff --git a/packages/angular/src/builders/dev-server/schema.d.ts b/packages/angular/src/builders/dev-server/schema.d.ts index a4eaef7432..e4240fe59f 100644 --- a/packages/angular/src/builders/dev-server/schema.d.ts +++ b/packages/angular/src/builders/dev-server/schema.d.ts @@ -21,6 +21,7 @@ interface BaseSchema { prebundle?: boolean | { exclude: string[] }; buildLibsFromSource?: boolean; esbuildMiddleware?: string[]; + watchDependencies?: boolean; } export type SchemaWithBrowserTarget = BaseSchema & { diff --git a/packages/angular/src/builders/dev-server/schema.json b/packages/angular/src/builders/dev-server/schema.json index f6e0060596..04d8901edf 100644 --- a/packages/angular/src/builders/dev-server/schema.json +++ b/packages/angular/src/builders/dev-server/schema.json @@ -156,6 +156,11 @@ "type": "string", "description": "The path to the middleware function. Relative to the workspace root." } + }, + "watchDependencies": { + "type": "boolean", + "description": "Watch buildable dependencies and rebuild when they change.", + "default": true } }, "additionalProperties": false, diff --git a/packages/angular/src/builders/webpack-browser/schema.d.ts b/packages/angular/src/builders/webpack-browser/schema.d.ts index ba23348130..b6f1ff4627 100644 --- a/packages/angular/src/builders/webpack-browser/schema.d.ts +++ b/packages/angular/src/builders/webpack-browser/schema.d.ts @@ -6,8 +6,10 @@ export type BrowserBuilderSchema = Schema & { }; indexHtmlTransformer?: string; buildLibsFromSource?: boolean; + watchDependencies?: boolean; + /** - * @deprecated Use `indexHtmlTransformer` instead. It will be removed in Nx 20. + * @deprecated Use `indexHtmlTransformer` instead. It will be removed in Nx 21. */ indexFileTransformer?: string; }; diff --git a/packages/angular/src/builders/webpack-browser/schema.json b/packages/angular/src/builders/webpack-browser/schema.json index 47bdcec72d..dd6a12cb60 100644 --- a/packages/angular/src/builders/webpack-browser/schema.json +++ b/packages/angular/src/builders/webpack-browser/schema.json @@ -464,6 +464,11 @@ "type": "boolean", "description": "Read buildable libraries from source instead of building them separately.", "default": true + }, + "watchDependencies": { + "type": "boolean", + "description": "Watch buildable dependencies and rebuild when they change.", + "default": true } }, "additionalProperties": false, diff --git a/packages/angular/src/builders/webpack-browser/webpack-browser.impl.ts b/packages/angular/src/builders/webpack-browser/webpack-browser.impl.ts index 2593475c2e..db26a3723a 100644 --- a/packages/angular/src/builders/webpack-browser/webpack-browser.impl.ts +++ b/packages/angular/src/builders/webpack-browser/webpack-browser.impl.ts @@ -51,12 +51,14 @@ export function executeWebpackBrowserBuilder( context: import('@angular-devkit/architect').BuilderContext ): Observable { options.buildLibsFromSource ??= true; + options.watchDependencies ??= true; const { buildLibsFromSource, customWebpackConfig, indexHtmlTransformer, indexFileTransformer, + watchDependencies, ...delegateBuilderOptions } = options; @@ -124,7 +126,7 @@ export function executeWebpackBrowserBuilder( `nx run-many --target=${ context.target.target } --projects=${workspaceDependencies.join(',')}`, - skipInitialRun + { skipInitialRun, skipWatchingDeps: !watchDependencies } ) ); } diff --git a/packages/webpack/src/plugins/nx-typescript-webpack-plugin/nx-tsconfig-paths-webpack-plugin.ts b/packages/webpack/src/plugins/nx-typescript-webpack-plugin/nx-tsconfig-paths-webpack-plugin.ts index 64d118c69f..aed8fbdd17 100644 --- a/packages/webpack/src/plugins/nx-typescript-webpack-plugin/nx-tsconfig-paths-webpack-plugin.ts +++ b/packages/webpack/src/plugins/nx-typescript-webpack-plugin/nx-tsconfig-paths-webpack-plugin.ts @@ -46,7 +46,7 @@ export class NxTsconfigPathsWebpackPlugin { handleBuildLibsFromSource( config: Partial, - options + options: NormalizedNxAppWebpackPluginOptions ): void { if (!options.buildLibsFromSource && options.targetName) { const remappedTarget = @@ -75,7 +75,11 @@ export class NxTsconfigPathsWebpackPlugin { const buildCommand = `nx run-many --target=build --projects=${buildableDependencies}`; - config.plugins.push(new WebpackNxBuildCoordinationPlugin(buildCommand)); + config.plugins.push( + new WebpackNxBuildCoordinationPlugin(buildCommand, { + skipWatchingDeps: options.watchDependencies === false, + }) + ); } } } diff --git a/packages/webpack/src/plugins/nx-webpack-plugin/nx-app-webpack-plugin-options.ts b/packages/webpack/src/plugins/nx-webpack-plugin/nx-app-webpack-plugin-options.ts index cc6cac16aa..d4b18bbab1 100644 --- a/packages/webpack/src/plugins/nx-webpack-plugin/nx-app-webpack-plugin-options.ts +++ b/packages/webpack/src/plugins/nx-webpack-plugin/nx-app-webpack-plugin-options.ts @@ -235,6 +235,10 @@ export interface NxAppWebpackPluginOptions { * Whether to rebase absolute path for assets in postcss cli resources. */ rebaseRootRelative?: boolean; + /** + * Watch buildable dependencies and rebuild when they change. + */ + watchDependencies?: boolean; } export interface NormalizedNxAppWebpackPluginOptions diff --git a/packages/webpack/src/plugins/webpack-nx-build-coordination-plugin.ts b/packages/webpack/src/plugins/webpack-nx-build-coordination-plugin.ts index 8ee46959c1..1fe05acfe2 100644 --- a/packages/webpack/src/plugins/webpack-nx-build-coordination-plugin.ts +++ b/packages/webpack/src/plugins/webpack-nx-build-coordination-plugin.ts @@ -4,21 +4,42 @@ import { daemonClient, isDaemonEnabled } from 'nx/src/daemon/client/client'; import { BatchFunctionRunner } from 'nx/src/command-line/watch/watch'; import { output } from 'nx/src/utils/output'; +type PluginOptions = { + skipInitialBuild?: boolean; + skipWatchingDeps?: boolean; +}; + export class WebpackNxBuildCoordinationPlugin { private currentlyRunning: 'none' | 'nx-build' | 'webpack-build' = 'none'; private buildCmdProcess: ReturnType | null = null; - constructor(private readonly buildCmd: string, skipInitialBuild?: boolean) { - if (!skipInitialBuild) { + constructor(buildCmd: string); + /** + * @deprecated Use the constructor with the `options` parameter instead. + */ + constructor(buildCmd: string, skipInitialBuild?: boolean); + constructor(buildCmd: string, options?: PluginOptions); + constructor( + private readonly buildCmd: string, + skipInitialBuildOrOptions?: boolean | PluginOptions + ) { + const options = + typeof skipInitialBuildOrOptions === 'boolean' + ? { skipInitialBuild: skipInitialBuildOrOptions } + : skipInitialBuildOrOptions; + + if (!options?.skipInitialBuild) { this.buildChangedProjects(); } - if (isDaemonEnabled()) { - this.startWatchingBuildableLibs(); - } else { - output.warn({ - title: - 'Nx Daemon is not enabled. Buildable libs will not be rebuilt on file changes.', - }); + if (!options?.skipWatchingDeps) { + if (isDaemonEnabled()) { + this.startWatchingBuildableLibs(); + } else { + output.warn({ + title: + 'Nx Daemon is not enabled. Buildable libs will not be rebuilt on file changes.', + }); + } } }