diff --git a/docs/generated/api-angular/executors/webpack-browser.md b/docs/generated/api-angular/executors/webpack-browser.md index 2bfb92651d58c..e6d4e735cc438 100644 --- a/docs/generated/api-angular/executors/webpack-browser.md +++ b/docs/generated/api-angular/executors/webpack-browser.md @@ -69,6 +69,14 @@ Type: `array` Budget thresholds to ensure parts of your application stay within boundaries which you set. +### buildLibsFromSource + +Default: `true` + +Type: `boolean` + +Read buildable libraries from source instead of building them separately. + ### buildOptimizer Default: `true` diff --git a/docs/shared/guides/setup-incremental-builds-angular.md b/docs/shared/guides/setup-incremental-builds-angular.md index a9e5a77a065a7..dcc8c57d0f6ce 100644 --- a/docs/shared/guides/setup-incremental-builds-angular.md +++ b/docs/shared/guides/setup-incremental-builds-angular.md @@ -67,7 +67,10 @@ Change your Angular app’s “build” target executor to `@nrwl/angular:webpac "build": { "executor": "@nrwl/angular:webpack-browser", "outputs": ["{options.outputPath}"], - "options": { ... }, + "options": { + "buildLibsFromSource": false + ... + }, "configurations": { ... }, "defaultConfiguration": "production" }, @@ -111,7 +114,10 @@ Note: you can specify the `--parallel` flags as part of the options property on "build": { "executor": "@nrwl/angular:webpack-browser", "outputs": ["{options.outputPath}"], - "options": { ... }, + "options": { + "buildLibsFromSource": false + ... + }, "configurations": { ... } }, "serve": { diff --git a/e2e/angular-core/src/projects.test.ts b/e2e/angular-core/src/projects.test.ts index 7205c238ecd7e..f668c04819b4e 100644 --- a/e2e/angular-core/src/projects.test.ts +++ b/e2e/angular-core/src/projects.test.ts @@ -155,6 +155,10 @@ describe('Angular Projects', () => { // update the angular.json updateProjectConfig(app, (config) => { config.targets.build.executor = '@nrwl/angular:webpack-browser'; + config.targets.build.options = { + ...config.targets.build.options, + buildLibsFromSource: false, + }; return config; }); diff --git a/e2e/angular-extensions/src/tailwind.test.ts b/e2e/angular-extensions/src/tailwind.test.ts index 1bfc4ce260dbc..ceb6d4780e21d 100644 --- a/e2e/angular-extensions/src/tailwind.test.ts +++ b/e2e/angular-extensions/src/tailwind.test.ts @@ -9,6 +9,7 @@ import { runCLI, uniq, updateFile, + updateProjectConfig, } from '@nrwl/e2e/utils'; describe('Tailwind support', () => { @@ -357,6 +358,14 @@ describe('Tailwind support', () => { runCLI( `generate @nrwl/angular:app ${appWithTailwind} --add-tailwind --no-interactive` ); + updateProjectConfig(appWithTailwind, (config) => { + config.targets.build.executor = '@nrwl/angular:webpack-browser'; + config.targets.build.options = { + ...config.targets.build.options, + buildLibsFromSource: false, + }; + return config; + }); updateTailwindConfig( `apps/${appWithTailwind}/tailwind.config.js`, spacing.projectVariant1 diff --git a/packages/angular/migrations.json b/packages/angular/migrations.json index d573a291a33be..aac9dd1bb7c3a 100644 --- a/packages/angular/migrations.json +++ b/packages/angular/migrations.json @@ -156,6 +156,12 @@ "version": "13.8.4", "description": "Karma coverage is broken since Angular 13 upgarde and the karma config is severely out of date. Bring it up to date fixing the coverage issue.", "factory": "./src/migrations/update-13-8-4/migrate-karma-conf" + }, + "set-build-libs-from-source": { + "cli": "nx", + "version": "13.9.0-beta.4", + "description": "Set buildLibsFromSource property to false to not break existing usage.", + "factory": "./src/migrations/update-13-9-0/set-build-libs-from-source" } }, "packageJsonUpdates": { diff --git a/packages/angular/src/builders/webpack-browser/schema.json b/packages/angular/src/builders/webpack-browser/schema.json index ee2e5ea16da91..1e5049445b2b4 100644 --- a/packages/angular/src/builders/webpack-browser/schema.json +++ b/packages/angular/src/builders/webpack-browser/schema.json @@ -371,6 +371,11 @@ } }, "additionalProperties": false + }, + "buildLibsFromSource": { + "type": "boolean", + "description": "Read buildable libraries from source instead of building them separately.", + "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 4a822aff59175..e2a41906e9340 100644 --- a/packages/angular/src/builders/webpack-browser/webpack-browser.impl.ts +++ b/packages/angular/src/builders/webpack-browser/webpack-browser.impl.ts @@ -12,10 +12,11 @@ import { calculateProjectDependencies, checkDependentProjectsHaveBeenBuilt, createTmpTsConfig, + DependentBuildableProjectNode, } from '@nrwl/workspace/src/utilities/buildable-libs-utils'; import { existsSync } from 'fs'; import { join } from 'path'; -import { from, Observable, of } from 'rxjs'; +import { Observable, of } from 'rxjs'; import { switchMap } from 'rxjs/operators'; import { merge } from 'webpack-merge'; import { resolveCustomWebpackConfig } from '../utilities/webpack'; @@ -24,13 +25,15 @@ export type BrowserBuilderSchema = Schema & { customWebpackConfig?: { path: string; }; + buildLibsFromSource?: boolean; }; function buildApp( options: BrowserBuilderSchema, context: BuilderContext ): Observable { - const { customWebpackConfig, ...delegateOptions } = options; + const { buildLibsFromSource, customWebpackConfig, ...delegateOptions } = + options; // If there is a path to custom webpack config // Invoke our own support for custom webpack config if (customWebpackConfig && customWebpackConfig.path) { @@ -91,29 +94,37 @@ function run( options: BrowserBuilderSchema, context: BuilderContext ): Observable { - const { target, dependencies } = calculateProjectDependencies( - readCachedProjectGraph(), - context.workspaceRoot, - context.target.project, - context.target.target, - context.target.configuration - ); - - options.tsConfig = createTmpTsConfig( - join(context.workspaceRoot, options.tsConfig), - context.workspaceRoot, - target.data.root, - dependencies - ); - process.env.NX_TSCONFIG_PATH = options.tsConfig; + options.buildLibsFromSource ??= true; + let dependencies: DependentBuildableProjectNode[]; - return of( - checkDependentProjectsHaveBeenBuilt( + if (!options.buildLibsFromSource) { + const result = calculateProjectDependencies( + readCachedProjectGraph(), context.workspaceRoot, context.target.project, context.target.target, + context.target.configuration + ); + dependencies = result.dependencies; + + options.tsConfig = createTmpTsConfig( + join(context.workspaceRoot, options.tsConfig), + context.workspaceRoot, + result.target.data.root, dependencies - ) + ); + } + process.env.NX_TSCONFIG_PATH = options.tsConfig; + + return of( + !options.buildLibsFromSource + ? checkDependentProjectsHaveBeenBuilt( + context.workspaceRoot, + context.target.project, + context.target.target, + dependencies + ) + : true ).pipe( switchMap((result) => { if (result) { diff --git a/packages/angular/src/migrations/update-13-9-0/set-build-libs-from-source.spec.ts b/packages/angular/src/migrations/update-13-9-0/set-build-libs-from-source.spec.ts new file mode 100644 index 0000000000000..74f345e1b4dfa --- /dev/null +++ b/packages/angular/src/migrations/update-13-9-0/set-build-libs-from-source.spec.ts @@ -0,0 +1,63 @@ +import { + addProjectConfiguration, + ProjectConfiguration, + readProjectConfiguration, + Tree, +} from '@nrwl/devkit'; +import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing'; +import migration from './set-build-libs-from-source'; + +describe('set-build-libs-from-source migration', () => { + let tree: Tree; + + beforeEach(() => { + tree = createTreeWithEmptyWorkspace(2); + }); + + it('should not error when project does not have targets', async () => { + addProjectConfiguration(tree, 'app1', { root: 'apps/app1' }); + + await expect(migration(tree)).resolves.not.toThrow(); + }); + + it('should not update when not using the @nrwl/angular:webpack-browser executor', async () => { + const project: ProjectConfiguration = { + root: 'apps/app1', + targets: { build: { executor: '@nrwl/angular:package' } }, + }; + addProjectConfiguration(tree, 'app1', project); + + await migration(tree); + + const resultingProject = readProjectConfiguration(tree, 'app1'); + expect(project).toStrictEqual(resultingProject); + }); + + it('should set buildLibsFromSource to false', async () => { + addProjectConfiguration(tree, 'app1', { + root: 'apps/app1', + targets: { build: { executor: '@nrwl/angular:webpack-browser' } }, + }); + + await migration(tree); + + const project = readProjectConfiguration(tree, 'app1'); + expect(project.targets.build.options).toStrictEqual({ + buildLibsFromSource: false, + }); + }); + + it('should support any target name using @nrwl/angular:webpack-browser', async () => { + addProjectConfiguration(tree, 'app1', { + root: 'apps/app1', + targets: { 'build-base': { executor: '@nrwl/angular:webpack-browser' } }, + }); + + await migration(tree); + + const project = readProjectConfiguration(tree, 'app1'); + expect(project.targets['build-base'].options).toStrictEqual({ + buildLibsFromSource: false, + }); + }); +}); diff --git a/packages/angular/src/migrations/update-13-9-0/set-build-libs-from-source.ts b/packages/angular/src/migrations/update-13-9-0/set-build-libs-from-source.ts new file mode 100644 index 0000000000000..debff18cc6cfe --- /dev/null +++ b/packages/angular/src/migrations/update-13-9-0/set-build-libs-from-source.ts @@ -0,0 +1,30 @@ +import { + formatFiles, + getProjects, + Tree, + updateProjectConfiguration, +} from '@nrwl/devkit'; + +export default async function (tree: Tree) { + const projects = getProjects(tree); + + for (const [projectName, project] of projects) { + if (!project.targets) { + continue; + } + + let shouldUpdate = false; + Object.values(project.targets).forEach((target) => { + if (target.executor === '@nrwl/angular:webpack-browser') { + shouldUpdate = true; + target.options = { ...target.options, buildLibsFromSource: false }; + } + }); + + if (shouldUpdate) { + updateProjectConfiguration(tree, projectName, project); + } + } + + await formatFiles(tree); +}