@nx/webpack 24.0.0-pr.37405.acdaf31 → 24.0.0-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/dist/index.d.ts +0 -1
  2. package/dist/index.js +0 -1
  3. package/dist/internal.d.ts +3 -0
  4. package/dist/internal.js +7 -1
  5. package/dist/ready-check.d.ts +1 -0
  6. package/dist/ready-check.js +9 -0
  7. package/dist/ready-signal.d.ts +1 -0
  8. package/dist/ready-signal.js +5 -0
  9. package/dist/src/executors/dev-server/dev-server.impl.js +38 -30
  10. package/dist/src/executors/ssr-dev-server/schema.json +2 -1
  11. package/dist/src/executors/ssr-dev-server/ssr-dev-server.impl.js +2 -0
  12. package/dist/src/generators/configuration/configuration.js +14 -132
  13. package/dist/src/generators/configuration/schema.d.ts +0 -1
  14. package/dist/src/generators/convert-config-to-webpack-plugin/convert-config-to-webpack-plugin.js +97 -57
  15. package/dist/src/generators/convert-config-to-webpack-plugin/lib/extract-webpack-options.d.ts +2 -0
  16. package/dist/src/generators/convert-config-to-webpack-plugin/lib/extract-webpack-options.js +46 -2
  17. package/dist/src/generators/convert-config-to-webpack-plugin/schema.json +2 -2
  18. package/dist/src/generators/convert-to-inferred/convert-to-inferred.js +5 -4
  19. package/dist/src/generators/convert-to-inferred/utils/ast.d.ts +2 -0
  20. package/dist/src/generators/convert-to-inferred/utils/ast.js +13 -0
  21. package/dist/src/generators/convert-to-inferred/utils/build-post-target-transformer.js +25 -5
  22. package/dist/src/generators/convert-to-inferred/utils/serve-post-target-transformer.js +13 -14
  23. package/dist/src/generators/init/init.js +45 -54
  24. package/dist/src/generators/init/schema.d.ts +0 -1
  25. package/dist/src/migrations/update-24-0-0/finish-inferred-conversion.md +11 -0
  26. package/dist/src/migrations/update-24-0-0/inventory.d.ts +10 -0
  27. package/dist/src/migrations/update-24-0-0/inventory.js +55 -0
  28. package/dist/src/migrations/update-24-0-0/migrate-compose-plugins.d.ts +10 -0
  29. package/dist/src/migrations/update-24-0-0/migrate-compose-plugins.js +68 -0
  30. package/dist/src/migrations/update-24-0-0/migrate-compose-plugins.md +98 -0
  31. package/dist/src/migrations/update-24-0-0/remove-deprecated-executors.d.ts +6 -0
  32. package/dist/src/migrations/update-24-0-0/remove-deprecated-executors.js +39 -0
  33. package/dist/src/migrations/update-24-0-0/remove-deprecated-executors.md +92 -0
  34. package/dist/src/plugins/nx-webpack-plugin/lib/normalize-options.d.ts +6 -0
  35. package/dist/src/plugins/nx-webpack-plugin/lib/normalize-options.js +29 -24
  36. package/dist/src/plugins/nx-webpack-plugin/nx-app-webpack-plugin.d.ts +2 -0
  37. package/dist/src/plugins/nx-webpack-plugin/nx-app-webpack-plugin.js +18 -1
  38. package/dist/src/plugins/plugin.js +18 -0
  39. package/dist/src/plugins/use-legacy-nx-plugin/use-legacy-nx-plugin.js +3 -0
  40. package/dist/src/utils/config.d.ts +8 -12
  41. package/dist/src/utils/config.js +15 -68
  42. package/dist/src/utils/deprecation.d.ts +3 -6
  43. package/dist/src/utils/deprecation.js +10 -27
  44. package/dist/src/utils/dev-server-ready-check.d.ts +36 -0
  45. package/dist/src/utils/dev-server-ready-check.js +255 -0
  46. package/dist/src/utils/dev-server-ready-signal.d.ts +29 -0
  47. package/dist/src/utils/dev-server-ready-signal.js +51 -0
  48. package/dist/src/utils/e2e-web-server-info-utils.d.ts +1 -1
  49. package/dist/src/utils/e2e-web-server-info-utils.js +2 -2
  50. package/dist/src/utils/webpack/read-webpack-options.d.ts +1 -1
  51. package/dist/src/utils/webpack/read-webpack-options.js +4 -4
  52. package/dist/src/utils/with-nx.d.ts +5 -9
  53. package/dist/src/utils/with-nx.js +5 -32
  54. package/dist/src/utils/with-web.d.ts +5 -9
  55. package/dist/src/utils/with-web.js +5 -24
  56. package/executors.json +0 -10
  57. package/migrations.json +13 -0
  58. package/package.json +20 -4
  59. package/dist/src/executors/webpack/lib/run-webpack.d.ts +0 -3
  60. package/dist/src/executors/webpack/lib/run-webpack.js +0 -36
  61. package/dist/src/executors/webpack/schema.json +0 -459
  62. package/dist/src/executors/webpack/webpack.impl.d.ts +0 -13
  63. package/dist/src/executors/webpack/webpack.impl.js +0 -117
  64. package/dist/src/utils/has-plugin.d.ts +0 -2
  65. package/dist/src/utils/has-plugin.js +0 -10
package/dist/index.d.ts CHANGED
@@ -14,7 +14,6 @@ export type { WebDevServerOptions } from './src/executors/dev-server/schema';
14
14
  export * from './src/executors/dev-server/dev-server.impl';
15
15
  export * from './src/executors/webpack/lib/normalize-options';
16
16
  export type { WebpackExecutorOptions, NormalizedWebpackExecutorOptions, AssetGlobPattern, FileReplacement, } from './src/executors/webpack/schema';
17
- export * from './src/executors/webpack/webpack.impl';
18
17
  export * from './src/utils/get-css-module-local-ident';
19
18
  export * from './src/utils/with-nx';
20
19
  export * from './src/utils/with-web';
package/dist/index.js CHANGED
@@ -26,7 +26,6 @@ var init_1 = require("./src/generators/init/init");
26
26
  Object.defineProperty(exports, "webpackInitGenerator", { enumerable: true, get: function () { return init_1.webpackInitGenerator; } });
27
27
  tslib_1.__exportStar(require("./src/executors/dev-server/dev-server.impl"), exports);
28
28
  tslib_1.__exportStar(require("./src/executors/webpack/lib/normalize-options"), exports);
29
- tslib_1.__exportStar(require("./src/executors/webpack/webpack.impl"), exports);
30
29
  tslib_1.__exportStar(require("./src/utils/get-css-module-local-ident"), exports);
31
30
  tslib_1.__exportStar(require("./src/utils/with-nx"), exports);
32
31
  tslib_1.__exportStar(require("./src/utils/with-web"), exports);
@@ -6,3 +6,6 @@ export { suppressWebpackComposeHelperWarnings } from './src/utils/deprecation';
6
6
  export { WebpackNxBuildCoordinationPlugin } from './src/plugins/webpack-nx-build-coordination-plugin';
7
7
  export type { WebSsrDevServerOptions } from './src/executors/ssr-dev-server/schema';
8
8
  export { default as ssrDevServerExecutor } from './src/executors/ssr-dev-server/ssr-dev-server.impl';
9
+ export { applyBaseConfig } from './src/plugins/nx-webpack-plugin/lib/apply-base-config';
10
+ export { applyWebConfig } from './src/plugins/nx-webpack-plugin/lib/apply-web-config';
11
+ export { webpackExecutorContext } from './src/plugins/nx-webpack-plugin/lib/normalize-options';
package/dist/internal.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ssrDevServerExecutor = exports.WebpackNxBuildCoordinationPlugin = exports.suppressWebpackComposeHelperWarnings = exports.resolveUserDefinedWebpackConfig = exports.ensureDependencies = exports.deleteOutputDir = exports.findAllNodeModules = exports.findUp = void 0;
3
+ exports.webpackExecutorContext = exports.applyWebConfig = exports.applyBaseConfig = exports.ssrDevServerExecutor = exports.WebpackNxBuildCoordinationPlugin = exports.suppressWebpackComposeHelperWarnings = exports.resolveUserDefinedWebpackConfig = exports.ensureDependencies = exports.deleteOutputDir = exports.findAllNodeModules = exports.findUp = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  // Curated internal API surface for other first-party Nx plugins (e.g. @nx/react,
6
6
  // @nx/angular, @nx/web, @nx/node, @nx/next, @nx/react-native). Prefer this over
@@ -24,3 +24,9 @@ var webpack_nx_build_coordination_plugin_1 = require("./src/plugins/webpack-nx-b
24
24
  Object.defineProperty(exports, "WebpackNxBuildCoordinationPlugin", { enumerable: true, get: function () { return webpack_nx_build_coordination_plugin_1.WebpackNxBuildCoordinationPlugin; } });
25
25
  var ssr_dev_server_impl_1 = require("./src/executors/ssr-dev-server/ssr-dev-server.impl");
26
26
  Object.defineProperty(exports, "ssrDevServerExecutor", { enumerable: true, get: function () { return tslib_1.__importDefault(ssr_dev_server_impl_1).default; } });
27
+ var apply_base_config_1 = require("./src/plugins/nx-webpack-plugin/lib/apply-base-config");
28
+ Object.defineProperty(exports, "applyBaseConfig", { enumerable: true, get: function () { return apply_base_config_1.applyBaseConfig; } });
29
+ var apply_web_config_1 = require("./src/plugins/nx-webpack-plugin/lib/apply-web-config");
30
+ Object.defineProperty(exports, "applyWebConfig", { enumerable: true, get: function () { return apply_web_config_1.applyWebConfig; } });
31
+ var normalize_options_1 = require("./src/plugins/nx-webpack-plugin/lib/normalize-options");
32
+ Object.defineProperty(exports, "webpackExecutorContext", { enumerable: true, get: function () { return normalize_options_1.webpackExecutorContext; } });
@@ -0,0 +1 @@
1
+ export declare function waitForDevServer(configPath: string): Promise<void>;
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.waitForDevServer = waitForDevServer;
4
+ const dev_server_ready_check_1 = require("./src/utils/dev-server-ready-check");
5
+ // The config can leave handles open, such as a type checker's workers
6
+ async function waitForDevServer(configPath) {
7
+ await (0, dev_server_ready_check_1.waitForWebpackDevServer)(configPath);
8
+ process.exit(0);
9
+ }
@@ -0,0 +1 @@
1
+ export { NxReadySignalPlugin } from './src/utils/dev-server-ready-signal';
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NxReadySignalPlugin = void 0;
4
+ var dev_server_ready_signal_1 = require("./src/utils/dev-server-ready-signal");
5
+ Object.defineProperty(exports, "NxReadySignalPlugin", { enumerable: true, get: function () { return dev_server_ready_signal_1.NxReadySignalPlugin; } });
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.devServerExecutor = devServerExecutor;
4
+ const normalize_options_1 = require("../../plugins/nx-webpack-plugin/lib/normalize-options");
4
5
  const internal_1 = require("@nx/devkit/internal");
5
6
  const devkit_1 = require("@nx/devkit");
6
7
  const operators_1 = require("rxjs/operators");
@@ -8,16 +9,15 @@ const get_dev_server_config_1 = require("./lib/get-dev-server-config");
8
9
  const internal_2 = require("@nx/js/internal");
9
10
  const run_webpack_1 = require("../../utils/run-webpack");
10
11
  const resolve_user_defined_webpack_config_1 = require("../../utils/webpack/resolve-user-defined-webpack-config");
11
- const deprecation_1 = require("../../utils/deprecation");
12
- const normalize_options_1 = require("../webpack/lib/normalize-options");
12
+ const normalize_options_2 = require("../webpack/lib/normalize-options");
13
13
  const config_1 = require("../../utils/config");
14
14
  const js_1 = require("@nx/js");
15
15
  async function* devServerExecutor(serveOptions, context) {
16
- (0, deprecation_1.warnWebpackDevServerExecutorDeprecation)();
17
16
  // Default to dev mode so builds are faster and HMR mode works better.
18
17
  process.env.NODE_ENV ??= 'development';
19
18
  const { root: projectRoot, sourceRoot } = context.projectsConfigurations.projects[context.projectName];
20
- const buildOptions = (0, normalize_options_1.normalizeOptions)(getBuildOptions(serveOptions, context), context.root, projectRoot, sourceRoot);
19
+ const executorOptions = getBuildOptions(serveOptions, context);
20
+ const buildOptions = (0, normalize_options_2.normalizeOptions)(executorOptions, context.root, projectRoot, sourceRoot);
21
21
  process.env.NX_BUILD_LIBS_FROM_SOURCE = `${buildOptions.buildLibsFromSource}`;
22
22
  process.env.NX_BUILD_TARGET = serveOptions.buildTarget;
23
23
  // TODO(jack): Figure out a way to port this into NxWebpackPlugin
@@ -29,37 +29,45 @@ async function* devServerExecutor(serveOptions, context) {
29
29
  context.configurationName);
30
30
  buildOptions.tsConfig = (0, internal_2.createTmpTsConfig)(buildOptions.tsConfig, context.root, target.data.root, dependencies);
31
31
  process.env.NX_TSCONFIG_PATH = buildOptions.tsConfig;
32
+ executorOptions.tsConfig = buildOptions.tsConfig;
32
33
  }
33
- let config;
34
34
  const devServer = (0, get_dev_server_config_1.getDevServerOptions)(context.root, serveOptions, buildOptions);
35
- if (buildOptions.webpackConfig) {
36
- let userDefinedWebpackConfig = (0, resolve_user_defined_webpack_config_1.resolveUserDefinedWebpackConfig)(buildOptions.webpackConfig, (0, js_1.getRootTsConfigPath)());
37
- if (typeof userDefinedWebpackConfig.then === 'function') {
38
- userDefinedWebpackConfig = await userDefinedWebpackConfig;
39
- }
40
- // Only add the dev server option if user is composable plugin.
41
- // Otherwise, user should define `devServer` option directly in their webpack config.
42
- if (typeof userDefinedWebpackConfig === 'function' &&
43
- ((0, config_1.isNxWebpackComposablePlugin)(userDefinedWebpackConfig) ||
44
- !buildOptions.standardWebpackConfigFunction)) {
45
- config = await userDefinedWebpackConfig({ devServer }, {
46
- options: buildOptions,
47
- context,
48
- configuration: serveOptions.buildTarget.split(':')[2],
49
- });
50
- }
51
- else if (userDefinedWebpackConfig) {
52
- // New behavior, we want the webpack config to export object
53
- // If the config is a function, we assume it's a standard webpack config function and it's async
54
- if (typeof userDefinedWebpackConfig === 'function') {
55
- config = await userDefinedWebpackConfig(process.env.NODE_ENV, {});
35
+ const config = await normalize_options_1.webpackExecutorContext.run({
36
+ options: executorOptions,
37
+ target: (0, devkit_1.parseTargetString)(serveOptions.buildTarget, context.projectGraph),
38
+ }, async () => {
39
+ let config;
40
+ if (buildOptions.webpackConfig) {
41
+ let userDefinedWebpackConfig = (0, resolve_user_defined_webpack_config_1.resolveUserDefinedWebpackConfig)(buildOptions.webpackConfig, (0, js_1.getRootTsConfigPath)());
42
+ if (typeof userDefinedWebpackConfig.then === 'function') {
43
+ userDefinedWebpackConfig = await userDefinedWebpackConfig;
56
44
  }
57
- else {
58
- config = userDefinedWebpackConfig;
45
+ // Legacy config functions receive the dev server options as their input config.
46
+ if (typeof userDefinedWebpackConfig === 'function' &&
47
+ ((0, config_1.isNxWebpackComposablePlugin)(userDefinedWebpackConfig) ||
48
+ !buildOptions.standardWebpackConfigFunction)) {
49
+ config = await userDefinedWebpackConfig({ devServer }, {
50
+ options: buildOptions,
51
+ context,
52
+ configuration: serveOptions.buildTarget.split(':')[2],
53
+ });
59
54
  }
60
- config.devServer ??= devServer;
55
+ else if (userDefinedWebpackConfig) {
56
+ // New behavior, we want the webpack config to export object
57
+ // If the config is a function, we assume it's a standard webpack config function and it's async
58
+ if (typeof userDefinedWebpackConfig === 'function') {
59
+ config = await userDefinedWebpackConfig(process.env.NODE_ENV, {});
60
+ }
61
+ else {
62
+ config = userDefinedWebpackConfig;
63
+ }
64
+ }
65
+ // Configs that ignore their arguments still get the target's dev server options.
66
+ if (config)
67
+ config.devServer ??= devServer;
61
68
  }
62
- }
69
+ return config;
70
+ });
63
71
  // Lazy-loaded: optional peers absent during project-graph discovery.
64
72
  const webpack = require('webpack');
65
73
  const WebpackDevServer = require('webpack-dev-server');
@@ -6,6 +6,7 @@
6
6
  "description": "Serve a SSR application using webpack.",
7
7
  "cli": "nx",
8
8
  "type": "object",
9
+ "x-deprecated": "The `@nx/webpack:ssr-dev-server` executor is deprecated and will be removed in Nx v25. Run the server from source with the `@nx/js/tsx` plugin, with the browser build in watch mode as a continuous dependency. See https://nx.dev/docs/kb/replace-ssr-dev-server.",
9
10
  "properties": {
10
11
  "browserTarget": {
11
12
  "type": "string",
@@ -19,7 +20,7 @@
19
20
  },
20
21
  "port": {
21
22
  "type": "number",
22
- "description": "The port to be set on `process.env.PORT` for use in the server.",
23
+ "description": "The port the server application listens on. The executor waits for it to accept connections before reporting the server as ready.",
23
24
  "default": 4200,
24
25
  "x-priority": "important"
25
26
  },
@@ -5,8 +5,10 @@ const tslib_1 = require("tslib");
5
5
  const internal_1 = require("@nx/devkit/internal");
6
6
  const devkit_1 = require("@nx/devkit");
7
7
  const pc = tslib_1.__importStar(require("picocolors"));
8
+ const deprecation_1 = require("../../utils/deprecation");
8
9
  const wait_until_server_is_listening_1 = require("./lib/wait-until-server-is-listening");
9
10
  async function* ssrDevServerExecutor(options, context) {
11
+ (0, deprecation_1.warnWebpackSsrDevServerExecutorDeprecation)();
10
12
  const browserTarget = (0, devkit_1.parseTargetString)(options.browserTarget, context.projectGraph);
11
13
  const serverTarget = (0, devkit_1.parseTargetString)(options.serverTarget, context);
12
14
  const browserOptions = (0, devkit_1.readTargetOptions)(browserTarget, context);
@@ -2,24 +2,16 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.configurationGenerator = configurationGenerator;
4
4
  exports.configurationGeneratorInternal = configurationGeneratorInternal;
5
- const internal_1 = require("@nx/devkit/internal");
6
5
  const devkit_1 = require("@nx/devkit");
7
6
  const init_1 = require("../init/init");
8
- const has_plugin_1 = require("../../utils/has-plugin");
9
- const deprecation_1 = require("../../utils/deprecation");
10
- const internal_2 = require("@nx/js/internal");
11
7
  const ensure_dependencies_1 = require("../../utils/ensure-dependencies");
12
8
  const versions_1 = require("../../utils/versions");
13
9
  function configurationGenerator(tree, options) {
14
- return configurationGeneratorInternal(tree, { addPlugin: false, ...options });
10
+ return configurationGeneratorInternal(tree, options);
15
11
  }
16
12
  async function configurationGeneratorInternal(tree, options) {
17
13
  (0, versions_1.assertSupportedWebpackVersion)(tree);
18
14
  const tasks = [];
19
- const nxJson = (0, devkit_1.readNxJson)(tree);
20
- const addPluginDefault = process.env.NX_ADD_PLUGINS !== 'false' &&
21
- nxJson.useInferencePlugins !== false;
22
- options.addPlugin ??= addPluginDefault;
23
15
  const initTask = await (0, init_1.webpackInitGenerator)(tree, {
24
16
  ...options,
25
17
  skipFormat: true,
@@ -30,13 +22,6 @@ async function configurationGeneratorInternal(tree, options) {
30
22
  });
31
23
  tasks.push(depsTask);
32
24
  checkForTargetConflicts(tree, options);
33
- if (!(0, has_plugin_1.hasPlugin)(tree)) {
34
- (0, deprecation_1.warnWebpackExecutorGenerating)();
35
- addBuildTarget(tree, options);
36
- if (options.devServer) {
37
- addServeTarget(tree, options);
38
- }
39
- }
40
25
  createWebpackConfig(tree, options);
41
26
  if (!options.skipFormat) {
42
27
  await (0, devkit_1.formatFiles)(tree);
@@ -64,42 +49,16 @@ function createWebpackConfig(tree, options) {
64
49
  tsConfig: options.tsConfig ?? (0, devkit_1.joinPathFragments)(project.root, 'tsconfig.app.json'),
65
50
  webpackConfig: (0, devkit_1.joinPathFragments)(project.root, 'webpack.config.js'),
66
51
  };
67
- if (options.target === 'web') {
68
- tree.write((0, devkit_1.joinPathFragments)(project.root, 'webpack.config.js'), (0, has_plugin_1.hasPlugin)(tree)
69
- ? `
70
- const { NxAppWebpackPlugin } = require('@nx/webpack/app-plugin');
71
- const { join } = require('path');
72
-
73
- module.exports = {
74
- output: {
75
- path: join(__dirname, '${(0, devkit_1.offsetFromRoot)(project.root)}${buildOptions.outputPath}'),
76
- },
77
- plugins: [
78
- new NxAppWebpackPlugin({
79
- target: '${buildOptions.target}',
80
- tsConfig: '${buildOptions.tsConfig}',
81
- compiler: '${buildOptions.compiler}',
82
- main: '${buildOptions.main}',
83
- outputHashing: '${buildOptions.target !== 'web' ? 'none' : 'all'}',
84
- })
85
- ],
86
- }
87
- `
88
- : `
89
- const { composePlugins, withNx, withWeb } = require('@nx/webpack');
90
-
91
- // Nx plugins for webpack.
92
- module.exports = composePlugins(withNx(), withWeb(), (config) => {
93
- // Update the webpack config as needed here.
94
- // e.g. \`config.plugins.push(new MyPlugin())\`
95
- config.output.clean = true;
96
- return config;
97
- });
98
- `);
52
+ if (options.babelConfig) {
53
+ buildOptions.babelConfig = options.babelConfig;
54
+ }
55
+ else if (options.compiler === 'babel') {
56
+ // Without a config file babel-loader looks for <projectRoot>/.babelrc and the build fails.
57
+ (0, devkit_1.writeJson)(tree, (0, devkit_1.joinPathFragments)(project.root, '.babelrc'), {
58
+ presets: ['@nx/js/babel'],
59
+ });
99
60
  }
100
- else {
101
- tree.write((0, devkit_1.joinPathFragments)(project.root, 'webpack.config.js'), (0, has_plugin_1.hasPlugin)(tree)
102
- ? `
61
+ tree.write((0, devkit_1.joinPathFragments)(project.root, 'webpack.config.js'), `
103
62
  const { NxAppWebpackPlugin } = require('@nx/webpack/app-plugin');
104
63
  const { join } = require('path');
105
64
 
@@ -111,92 +70,15 @@ module.exports = {
111
70
  new NxAppWebpackPlugin({
112
71
  target: '${buildOptions.target}',
113
72
  tsConfig: '${buildOptions.tsConfig}',
114
- compiler: '${buildOptions.compiler}',
73
+ compiler: '${buildOptions.compiler}',${buildOptions.babelConfig
74
+ ? `
75
+ babelConfig: '${buildOptions.babelConfig}',`
76
+ : ''}
115
77
  main: '${buildOptions.main}',
116
78
  outputHashing: '${buildOptions.target !== 'web' ? 'none' : 'all'}',
117
79
  })
118
80
  ],
119
81
  }
120
- `
121
- : `
122
- const { composePlugins, withNx } = require('@nx/webpack');
123
-
124
- // Nx plugins for webpack.
125
- module.exports = composePlugins(withNx(), (config) => {
126
- // Update the webpack config as needed here.
127
- // e.g. \`config.plugins.push(new MyPlugin())\`
128
- config.output.clean = true;
129
- return config;
130
- });
131
82
  `);
132
- }
133
- }
134
- function addBuildTarget(tree, options) {
135
- (0, internal_1.addBuildTargetDefaults)(tree, '@nx/webpack:webpack', 'build', [
136
- internal_2.TS_SOLUTION_SETUP_TSCONFIG_INPUT,
137
- ]);
138
- const project = (0, devkit_1.readProjectConfiguration)(tree, options.project);
139
- const buildOptions = {
140
- target: options.target,
141
- outputPath: (0, devkit_1.joinPathFragments)('dist', project.root),
142
- compiler: options.compiler ?? 'swc',
143
- main: options.main ?? (0, devkit_1.joinPathFragments)(project.root, 'src/main.ts'),
144
- tsConfig: options.tsConfig ?? (0, devkit_1.joinPathFragments)(project.root, 'tsconfig.app.json'),
145
- webpackConfig: (0, devkit_1.joinPathFragments)(project.root, 'webpack.config.js'),
146
- };
147
- if (options.webpackConfig) {
148
- buildOptions.webpackConfig = options.webpackConfig;
149
- }
150
- if (options.babelConfig) {
151
- buildOptions.babelConfig = options.babelConfig;
152
- }
153
- else if (options.compiler === 'babel') {
154
- // If no babel config file is provided then write a default one, otherwise build will fail.
155
- (0, devkit_1.writeJson)(tree, (0, devkit_1.joinPathFragments)(project.root, '.babelrc'), {
156
- presets: ['@nx/js/babel'],
157
- });
158
- }
159
- (0, devkit_1.updateProjectConfiguration)(tree, options.project, {
160
- ...project,
161
- targets: {
162
- ...project.targets,
163
- build: {
164
- executor: '@nx/webpack:webpack',
165
- outputs: ['{options.outputPath}'],
166
- defaultConfiguration: 'production',
167
- options: buildOptions,
168
- configurations: {
169
- production: {
170
- optimization: true,
171
- outputHashing: options.target === 'web' ? 'all' : 'none',
172
- sourceMap: false,
173
- namedChunks: false,
174
- extractLicenses: true,
175
- vendorChunk: false,
176
- },
177
- },
178
- },
179
- },
180
- });
181
- }
182
- function addServeTarget(tree, options) {
183
- const project = (0, devkit_1.readProjectConfiguration)(tree, options.project);
184
- (0, devkit_1.updateProjectConfiguration)(tree, options.project, {
185
- ...project,
186
- targets: {
187
- ...project.targets,
188
- serve: {
189
- executor: '@nx/webpack:dev-server',
190
- options: {
191
- buildTarget: `${options.project}:build`,
192
- },
193
- configurations: {
194
- production: {
195
- buildTarget: `${options.project}:build:production`,
196
- },
197
- },
198
- },
199
- },
200
- });
201
83
  }
202
84
  exports.default = configurationGenerator;
@@ -10,5 +10,4 @@ export interface ConfigurationGeneratorSchema {
10
10
  target?: 'node' | 'web' | 'webworker';
11
11
  webpackConfig?: string;
12
12
  babelConfig?: string;
13
- addPlugin?: boolean;
14
13
  }
@@ -8,6 +8,7 @@ const normalize_path_options_1 = require("./lib/normalize-path-options");
8
8
  const path_1 = require("path");
9
9
  const validate_project_1 = require("./lib/validate-project");
10
10
  const versions_1 = require("../../utils/versions");
11
+ const buildExecutors = ['@nx/webpack:webpack', '@nrwl/webpack:webpack'];
11
12
  // Make text JSON compatible
12
13
  const preprocessText = (text) => {
13
14
  return text
@@ -20,70 +21,44 @@ async function convertConfigToWebpackPluginGenerator(tree, options) {
20
21
  (0, versions_1.assertSupportedWebpackVersion)(tree);
21
22
  let migrated = 0;
22
23
  const projects = (0, devkit_1.getProjects)(tree);
23
- (0, internal_1.forEachExecutorOptions)(tree, '@nx/webpack:webpack', (currentTargetOptions, projectName, targetName, configurationName) => {
24
- if (options.project && projectName !== options.project) {
25
- return;
26
- }
27
- if (!configurationName) {
28
- const project = projects.get(projectName);
29
- const target = project.targets[targetName];
30
- const hasError = (0, validate_project_1.validateProject)(tree, project);
31
- if (hasError) {
32
- throw new Error(hasError);
24
+ for (const executor of buildExecutors) {
25
+ (0, internal_1.forEachExecutorOptions)(tree, executor, (currentTargetOptions, projectName, targetName, configurationName) => {
26
+ if (options.project && projectName !== options.project) {
27
+ return;
33
28
  }
34
- const webpackConfigPath = currentTargetOptions?.webpackConfig || '';
35
- if (webpackConfigPath && tree.exists(webpackConfigPath)) {
36
- let { withNxConfig: webpackOptions, withReactConfig } = (0, extract_webpack_options_1.extractWebpackOptions)(tree, webpackConfigPath);
37
- // if webpackOptions === undefined
38
- // withNx was not found in the webpack.config.js file so we should skip this project
39
- if (webpackOptions !== undefined) {
40
- let parsedOptions = {};
41
- if (webpackOptions) {
42
- parsedOptions = JSON.parse(preprocessText(webpackOptions.getText()));
43
- parsedOptions = (0, normalize_path_options_1.normalizePathOptions)(project.root, parsedOptions);
44
- }
29
+ if (!configurationName) {
30
+ const project = projects.get(projectName);
31
+ const target = project.targets[targetName];
32
+ const hasError = (0, validate_project_1.validateProject)(tree, project);
33
+ if (hasError) {
34
+ throw new Error(hasError);
35
+ }
36
+ const webpackConfigPath = currentTargetOptions?.webpackConfig || '';
37
+ if (webpackConfigPath &&
38
+ tree.exists(webpackConfigPath) &&
39
+ convertConfigFile(tree, project.root, webpackConfigPath)) {
45
40
  target.options.standardWebpackConfigFunction = true;
46
41
  (0, devkit_1.updateProjectConfiguration)(tree, projectName, project);
47
- const { dir, name, ext } = (0, path_1.parse)(webpackConfigPath);
48
- tree.rename(webpackConfigPath, `${(0, devkit_1.joinPathFragments)(dir, `${name}.old${ext}`)}`);
49
- tree.write(webpackConfigPath, (0, devkit_1.stripIndents) `
50
- const { NxAppWebpackPlugin } = require('@nx/webpack/app-plugin');
51
- const { NxReactWebpackPlugin } = require('@nx/react/webpack-plugin');
52
- const { useLegacyNxPlugin } = require('@nx/webpack');
53
-
54
- // This file was migrated using @nx/webpack:convert-config-to-webpack-plugin from your './webpack.config.old.js'
55
- // Please check that the options here are correct as they were moved from the old webpack.config.js to this file.
56
- const options = ${webpackOptions ? JSON.stringify(parsedOptions, null, 2) : '{}'};
57
-
58
- /**
59
- * @type{import('webpack').WebpackOptionsNormalized}
60
- */
61
- module.exports = async () => ({
62
- plugins: [
63
- ${webpackOptions
64
- ? 'new NxAppWebpackPlugin(options)'
65
- : 'new NxAppWebpackPlugin()'},
66
- ${withReactConfig
67
- ? `new NxReactWebpackPlugin(${withReactConfig.getText()})`
68
- : `new NxReactWebpackPlugin({
69
- // Uncomment this line if you don't want to use SVGR
70
- // See: https://react-svgr.com/
71
- // svgr: false
72
- })`},
73
- // NOTE: useLegacyNxPlugin ensures that the non-standard Webpack configuration file previously used still works.
74
- // To remove its usage, move options such as "plugins" into this file as standard Webpack configuration options.
75
- // To enhance configurations after Nx plugins have applied, you can add a new plugin with the \`apply\` method.
76
- // e.g. \`{ apply: (compiler) => { /* modify compiler.options */ }\`
77
- // eslint-disable-next-line react-hooks/rules-of-hooks
78
- await useLegacyNxPlugin(require('./webpack.config.old${ext}'), options),
79
- ],
80
- });
81
- `);
82
42
  migrated++;
83
43
  }
84
44
  }
45
+ });
46
+ }
47
+ // Projects already on the inference plugin keep their options in the config,
48
+ // so only the config needs converting.
49
+ for (const [projectName, project] of projects) {
50
+ if (options.project && projectName !== options.project) {
51
+ continue;
52
+ }
53
+ if (Object.values(project.targets ?? {}).some((target) => buildExecutors.includes(target.executor))) {
54
+ continue;
85
55
  }
86
- });
56
+ const webpackConfigPath = (0, devkit_1.joinPathFragments)(project.root, 'webpack.config.js');
57
+ if (tree.exists(webpackConfigPath) &&
58
+ convertConfigFile(tree, project.root, webpackConfigPath)) {
59
+ migrated++;
60
+ }
61
+ }
87
62
  if (migrated === 0) {
88
63
  throw new Error('Could not find any projects to migrate.');
89
64
  }
@@ -91,4 +66,69 @@ async function convertConfigToWebpackPluginGenerator(tree, options) {
91
66
  await (0, devkit_1.formatFiles)(tree);
92
67
  }
93
68
  }
69
+ /** Returns whether the config used `withNx` and was converted. */
70
+ function convertConfigFile(tree, projectRoot, webpackConfigPath) {
71
+ let { withNxConfig: webpackOptions, withReactConfig, strippedSource, leftoverHelpers, } = (0, extract_webpack_options_1.extractWebpackOptions)(tree, webpackConfigPath);
72
+ // if webpackOptions === undefined
73
+ // withNx was not found in the webpack.config.js file so we should skip this project
74
+ if (webpackOptions !== undefined) {
75
+ // The `.old` config would call helpers whose imports were removed, or inert stubs.
76
+ if (leftoverHelpers.length) {
77
+ throw new Error(`Could not convert ${webpackConfigPath}: ${leftoverHelpers.join(', ')} would be left in the old config. Only \`require\`d helpers passed directly to \`composePlugins\` are supported.`);
78
+ }
79
+ let parsedOptions = {};
80
+ if (webpackOptions) {
81
+ // Parse before writing anything: a non-literal option value leaves the
82
+ // project untouched for the migration prompt instead of a config whose
83
+ // helper calls are gone and whose options never made it across.
84
+ try {
85
+ parsedOptions = JSON.parse(preprocessText(webpackOptions.getText()));
86
+ }
87
+ catch {
88
+ throw new Error(`Could not read the \`withNx\` options in ${webpackConfigPath}. They must be a plain object literal; spreads, variables and function calls are not supported.`);
89
+ }
90
+ parsedOptions = (0, normalize_path_options_1.normalizePathOptions)(projectRoot, parsedOptions);
91
+ }
92
+ if (strippedSource !== undefined) {
93
+ tree.write(webpackConfigPath, strippedSource);
94
+ }
95
+ const { dir, name, ext } = (0, path_1.parse)(webpackConfigPath);
96
+ tree.rename(webpackConfigPath, `${(0, devkit_1.joinPathFragments)(dir, `${name}.old${ext}`)}`);
97
+ // `@nx/webpack` does not depend on `@nx/react`, so only React configs may require it.
98
+ const usesReact = withReactConfig !== undefined;
99
+ const reactRequire = usesReact
100
+ ? `\nconst { NxReactWebpackPlugin } = require('@nx/react/webpack-plugin');`
101
+ : '';
102
+ const reactPlugin = usesReact
103
+ ? `\nnew NxReactWebpackPlugin(${withReactConfig ? withReactConfig.getText() : ''}),`
104
+ : '';
105
+ tree.write(webpackConfigPath, (0, devkit_1.stripIndents) `
106
+ const { NxAppWebpackPlugin } = require('@nx/webpack/app-plugin');${reactRequire}
107
+ const { useLegacyNxPlugin } = require('@nx/webpack');
108
+
109
+ // This file was migrated using @nx/webpack:convert-config-to-webpack-plugin from your './webpack.config.old.js'
110
+ // Please check that the options here are correct as they were moved from the old webpack.config.js to this file.
111
+ const options = ${webpackOptions ? JSON.stringify(parsedOptions, null, 2) : '{}'};
112
+
113
+ /**
114
+ * @type{import('webpack').WebpackOptionsNormalized}
115
+ */
116
+ module.exports = async () => ({
117
+ plugins: [
118
+ ${webpackOptions
119
+ ? 'new NxAppWebpackPlugin(options)'
120
+ : 'new NxAppWebpackPlugin()'},${reactPlugin}
121
+ // NOTE: useLegacyNxPlugin ensures that the non-standard Webpack configuration file previously used still works.
122
+ // To remove its usage, move options such as "plugins" into this file as standard Webpack configuration options.
123
+ // To enhance configurations after Nx plugins have applied, you can add a new plugin with the \`apply\` method.
124
+ // e.g. \`{ apply: (compiler) => { /* modify compiler.options */ }\`
125
+ // eslint-disable-next-line react-hooks/rules-of-hooks
126
+ await useLegacyNxPlugin(require('./webpack.config.old${ext}'), options),
127
+ ],
128
+ });
129
+ `);
130
+ return true;
131
+ }
132
+ return false;
133
+ }
94
134
  exports.default = convertConfigToWebpackPluginGenerator;
@@ -3,4 +3,6 @@ import * as ts from 'typescript';
3
3
  export declare function extractWebpackOptions(tree: Tree, webpackConfigPath: string): {
4
4
  withNxConfig: "" | ts.Node;
5
5
  withReactConfig: "" | ts.Node;
6
+ strippedSource: string;
7
+ leftoverHelpers: string[];
6
8
  };
@@ -15,6 +15,10 @@ function extractWebpackOptions(tree, webpackConfigPath) {
15
15
  const withWebCall = (0, tsquery_1.query)(sourceFile, withWebQuery);
16
16
  // If the config is empty set to empty string to avoid undefined. Undefined is used to check if the withNx exists inside of the config file.
17
17
  let withNxConfig, withReactConfig;
18
+ // Returned rather than written here so the caller can reject configs whose
19
+ // options are not a plain literal before touching the file.
20
+ let strippedSource;
21
+ let leftoverHelpers = [];
18
22
  withWebCall.forEach((node) => {
19
23
  const argument = node.arguments[0] || '';
20
24
  withNxConfig = argument; // Since withWeb and withNx use the same config object and both should not exist in the same file, we can reuse the withNxConfig variable.
@@ -37,9 +41,49 @@ function extractWebpackOptions(tree, webpackConfigPath) {
37
41
  updatedSource = removeImportDeclarations(updatedSource, 'withNx', '@nx/webpack');
38
42
  updatedSource = removeImportDeclarations(updatedSource, 'withWeb', '@nx/webpack');
39
43
  updatedSource = removeImportDeclarations(updatedSource, 'withReact', '@nx/react');
40
- tree.write(webpackConfigPath, updatedSource);
44
+ updatedSource = inlineComposePlugins(updatedSource);
45
+ updatedSource = removeImportDeclarations(updatedSource, 'composePlugins', '@nx/webpack');
46
+ strippedSource = updatedSource;
47
+ leftoverHelpers = findHelperReferences(updatedSource);
41
48
  }
42
- return { withNxConfig, withReactConfig };
49
+ return { withNxConfig, withReactConfig, strippedSource, leftoverHelpers };
50
+ }
51
+ const REMOVED_HELPERS = new Set([
52
+ 'composePlugins',
53
+ 'composePluginsSync',
54
+ 'withNx',
55
+ 'withWeb',
56
+ 'withReact',
57
+ ]);
58
+ function findHelperReferences(source) {
59
+ const names = (0, tsquery_1.query)((0, tsquery_1.ast)(source), 'Identifier')
60
+ .map((node) => node.text)
61
+ .filter((name) => REMOVED_HELPERS.has(name));
62
+ return [...new Set(names)];
63
+ }
64
+ // `composePlugins` is an inert stub since Nx v24, so the old config composes its
65
+ // remaining callbacks with a local copy.
66
+ function inlineComposePlugins(source) {
67
+ let found = false;
68
+ const updatedSource = (0, tsquery_1.replace)(source, 'CallExpression > Identifier[name="composePlugins"]', (node) => {
69
+ if (node.parent.expression !== node) {
70
+ return node.getText();
71
+ }
72
+ found = true;
73
+ return 'composeLegacyPlugins';
74
+ });
75
+ if (!found)
76
+ return source;
77
+ return `${updatedSource}
78
+ function composeLegacyPlugins(...plugins) {
79
+ return async (config, ctx) => {
80
+ for (const plugin of plugins) {
81
+ config = await (await plugin)(config, ctx);
82
+ }
83
+ return config;
84
+ };
85
+ }
86
+ `;
43
87
  }
44
88
  function removeCallExpressions(source, functionNames) {
45
89
  let modifiedSource = source;