diff --git a/docs/generated/packages/webpack/executors/webpack.json b/docs/generated/packages/webpack/executors/webpack.json index 2f5a8b17a5bdc..0e0bb8e6b24f4 100644 --- a/docs/generated/packages/webpack/executors/webpack.json +++ b/docs/generated/packages/webpack/executors/webpack.json @@ -331,6 +331,11 @@ "description": "Generates a 'stats.json' file which can be analyzed using tools such as: 'webpack-bundle-analyzer' or ``.", "default": false }, + "isolatedConfig": { + "type": "boolean", + "description": "Do not apply Nx webpack plugins automatically. Plugins need to be applied in the project's webpack.config.js file (e.g. withNx, withReact, etc.).", + "default": false + }, "extractLicenses": { "type": "boolean", "description": "Extract all licenses in a separate file, in the case of production builds only.", diff --git a/e2e/web/src/web.test.ts b/e2e/web/src/web.test.ts index 373864d3ae5e5..e9bc5aaf15800 100644 --- a/e2e/web/src/web.test.ts +++ b/e2e/web/src/web.test.ts @@ -170,9 +170,10 @@ describe('Web Components Applications', () => { updateFile( `apps/${appName}/webpack.config.js`, ` - module.exports = (config, context) => { + const { composePlugins, withNx, withWeb } = require('@nrwl/webpack'); + module.exports = composePlugins(withNx(), withWeb(), (config, context) => { return config; - }; + }); ` ); runCLI(`build ${appName} --outputHashing none`); @@ -184,9 +185,10 @@ describe('Web Components Applications', () => { updateFile( `apps/${appName}/webpack.config.js`, ` - module.exports = async (config, context) => { + const { composePlugins, withNx, withWeb } = require('@nrwl/webpack'); + module.exports = composePlugins(withNx(), withWeb(), async (config, context) => { return config; - }; + }); ` ); runCLI(`build ${appName} --outputHashing none`); @@ -198,9 +200,10 @@ describe('Web Components Applications', () => { updateFile( `apps/${appName}/webpack.config.js`, ` - module.exports = Promise.resolve((config, context) => { + const { composePlugins, withNx, withWeb } = require('@nrwl/webpack'); + module.exports = composePlugins(withNx(), withWeb(), Promise.resolve((config, context) => { return config; - }); + })); ` ); runCLI(`build ${appName} --outputHashing none`); diff --git a/packages/node/src/generators/application/application.spec.ts b/packages/node/src/generators/application/application.spec.ts index 9d6b72865c02b..29d3c63be7775 100644 --- a/packages/node/src/generators/application/application.spec.ts +++ b/packages/node/src/generators/application/application.spec.ts @@ -55,6 +55,7 @@ describe('app', () => { outputPath: 'dist/my-node-app', main: 'my-node-app/src/main.ts', tsConfig: 'my-node-app/tsconfig.app.json', + isolatedConfig: true, webpackConfig: 'my-node-app/webpack.config.js', assets: ['my-node-app/src/assets'], }, diff --git a/packages/node/src/generators/application/application.ts b/packages/node/src/generators/application/application.ts index a4a9c32ef5c63..2dee80504c269 100644 --- a/packages/node/src/generators/application/application.ts +++ b/packages/node/src/generators/application/application.ts @@ -66,6 +66,7 @@ function getWebpackBuildConfig( ), tsConfig: joinPathFragments(options.appProjectRoot, 'tsconfig.app.json'), assets: [joinPathFragments(project.sourceRoot, 'assets')], + isolatedConfig: true, webpackConfig: joinPathFragments( options.appProjectRoot, 'webpack.config.js' diff --git a/packages/react/plugins/with-react.ts b/packages/react/plugins/with-react.ts index ae562fb33aa87..61c99b7bea487 100644 --- a/packages/react/plugins/with-react.ts +++ b/packages/react/plugins/with-react.ts @@ -1,18 +1,13 @@ import type { Configuration } from 'webpack'; -import { NormalizedWebpackExecutorOptions } from '@nrwl/webpack'; -import { ExecutorContext } from 'nx/src/config/misc-interfaces'; const processed = new Set(); export function withReact() { - return function configure( - config: Configuration, - _ctx?: { - options: NormalizedWebpackExecutorOptions; - context: ExecutorContext; - } - ): Configuration { + return function configure(config: Configuration, _ctx?: any): Configuration { + const { withWeb } = require('@nrwl/webpack'); + if (processed.has(config)) return config; + config = withWeb()(config, _ctx); config.module.rules.push({ test: /\.svg$/, diff --git a/packages/react/src/generators/application/application.spec.ts b/packages/react/src/generators/application/application.spec.ts index b09e32963187a..10c596f2934c6 100644 --- a/packages/react/src/generators/application/application.spec.ts +++ b/packages/react/src/generators/application/application.spec.ts @@ -315,6 +315,7 @@ describe('app', () => { scripts: [], styles: ['apps/my-app/src/styles.css'], tsConfig: 'apps/my-app/tsconfig.app.json', + isolatedConfig: true, webpackConfig: 'apps/my-app/webpack.config.js', }); expect(targetConfig.build.configurations.production).toEqual({ diff --git a/packages/react/src/generators/application/lib/add-project.ts b/packages/react/src/generators/application/lib/add-project.ts index 9ea3b9d51a5e3..d9744ce2e5461 100644 --- a/packages/react/src/generators/application/lib/add-project.ts +++ b/packages/react/src/generators/application/lib/add-project.ts @@ -67,6 +67,7 @@ function createBuildTarget(options: NormalizedSchema): TargetConfiguration { ), ], scripts: [], + isolatedConfig: true, webpackConfig: joinPathFragments( options.appProjectRoot, 'webpack.config.js' diff --git a/packages/react/src/generators/setup-ssr/setup-ssr.ts b/packages/react/src/generators/setup-ssr/setup-ssr.ts index fefa3d3a2b037..563b438e01e60 100644 --- a/packages/react/src/generators/setup-ssr/setup-ssr.ts +++ b/packages/react/src/generators/setup-ssr/setup-ssr.ts @@ -107,6 +107,7 @@ export async function setupSsrGenerator(tree: Tree, options: Schema) { compiler: 'babel', externalDependencies: 'all', outputHashing: 'none', + isolatedConfig: true, webpackConfig: joinPathFragments(projectRoot, 'webpack.config.js'), }, configurations: { diff --git a/packages/web/src/generators/application/application.ts b/packages/web/src/generators/application/application.ts index b50b4ee1ba40e..d31ae15096fc3 100644 --- a/packages/web/src/generators/application/application.ts +++ b/packages/web/src/generators/application/application.ts @@ -82,6 +82,7 @@ async function setupBundler(tree: Tree, options: NormalizedSchema) { tsConfig, compiler: options.compiler ?? 'babel', devServer: true, + isolatedConfig: true, webpackConfig: joinPathFragments( options.appProjectRoot, 'webpack.config.js' diff --git a/packages/webpack/src/executors/webpack/schema.d.ts b/packages/webpack/src/executors/webpack/schema.d.ts index dd9432f03aa99..49fba9ccaa7dc 100644 --- a/packages/webpack/src/executors/webpack/schema.d.ts +++ b/packages/webpack/src/executors/webpack/schema.d.ts @@ -54,6 +54,7 @@ export interface WebpackExecutorOptions { generateIndexHtml?: boolean; generatePackageJson?: boolean; index?: string; + isolatedConfig?: boolean; main: string; memoryLimit?: number; namedChunks?: boolean; diff --git a/packages/webpack/src/executors/webpack/schema.json b/packages/webpack/src/executors/webpack/schema.json index ffa942bdd76fc..cc97b752df211 100644 --- a/packages/webpack/src/executors/webpack/schema.json +++ b/packages/webpack/src/executors/webpack/schema.json @@ -252,6 +252,11 @@ "description": "Generates a 'stats.json' file which can be analyzed using tools such as: 'webpack-bundle-analyzer' or ``.", "default": false }, + "isolatedConfig": { + "type": "boolean", + "description": "Do not apply Nx webpack plugins automatically. Plugins need to be applied in the project's webpack.config.js file (e.g. withNx, withReact, etc.).", + "default": false + }, "extractLicenses": { "type": "boolean", "description": "Extract all licenses in a separate file, in the case of production builds only.", diff --git a/packages/webpack/src/executors/webpack/webpack.impl.ts b/packages/webpack/src/executors/webpack/webpack.impl.ts index 3a0b8f9902c3f..37f9351bce316 100644 --- a/packages/webpack/src/executors/webpack/webpack.impl.ts +++ b/packages/webpack/src/executors/webpack/webpack.impl.ts @@ -27,15 +27,11 @@ async function getWebpackConfigs( options: NormalizedWebpackExecutorOptions, context: ExecutorContext ): Promise { - const metadata = context.projectsConfigurations.projects[context.projectName]; - const projectRoot = metadata.root; - const isScriptOptimizeOn = - typeof options.optimization === 'boolean' - ? options.optimization - : options.optimization && options.optimization.scripts - ? options.optimization.scripts - : false; - + if (options.isolatedConfig && !options.webpackConfig) { + throw new Error( + `Using "isolatedConfig" without a "webpackConfig" is not supported.` + ); + } let customWebpack = null; if (options.webpackConfig) { @@ -49,15 +45,21 @@ async function getWebpackConfigs( } } - const config = getWebpackConfig(context, options); + const config = options.isolatedConfig + ? {} + : getWebpackConfig(context, options); if (customWebpack) { - return await customWebpack(config, { - options, - context, - configuration: context.configurationName, // backwards compat - }); + return await customWebpack( + {}, + { + options, + context, + configuration: context.configurationName, // backwards compat + } + ); } else { + // If the user has no webpackConfig specified then we always have to apply return config; } }