@nx/next 17.0.2 → 17.0.4

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 (73) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +9 -4
  3. package/generators.json +2 -2
  4. package/migrations.json +24 -0
  5. package/package.json +12 -10
  6. package/plugin.d.ts +1 -0
  7. package/plugin.js +5 -0
  8. package/plugins/component-testing.d.ts +1 -11
  9. package/plugins/component-testing.js +26 -10
  10. package/plugins/with-nx.d.ts +1 -1
  11. package/plugins/with-nx.js +68 -86
  12. package/plugins/with-stylus.js +1 -1
  13. package/src/executors/build/build.impl.js +20 -9
  14. package/src/executors/build/lib/create-next-config-file.js +5 -2
  15. package/src/executors/build/lib/test-fixtures/ensure-exts/baz.json +1 -0
  16. package/src/executors/build/lib/update-package-json.js +10 -1
  17. package/src/executors/build/schema.json +1 -1
  18. package/src/executors/export/export.impl.js +9 -9
  19. package/src/executors/server/custom-server.impl.js +3 -2
  20. package/src/executors/server/schema.json +4 -0
  21. package/src/executors/server/server.impl.js +13 -11
  22. package/src/generators/application/application.js +24 -0
  23. package/src/generators/application/files/app/page.tsx__tmpl__ +1 -1
  24. package/src/generators/application/files/common/specs/__fileName__.spec.tsx__tmpl__ +10 -3
  25. package/src/generators/application/files/common/tsconfig.json__tmpl__ +5 -5
  26. package/src/generators/application/files/pages/__fileName__.tsx__tmpl__ +1 -1
  27. package/src/generators/application/lib/add-e2e.js +27 -3
  28. package/src/generators/application/lib/add-linting.js +13 -16
  29. package/src/generators/application/lib/add-plugin.d.ts +2 -0
  30. package/src/generators/application/lib/add-plugin.js +25 -0
  31. package/src/generators/application/lib/add-project.js +43 -33
  32. package/src/generators/application/lib/create-application-files.helpers.js +67 -5
  33. package/src/generators/application/lib/create-application-files.js +23 -11
  34. package/src/generators/application/lib/normalize-options.d.ts +3 -0
  35. package/src/generators/application/lib/normalize-options.js +31 -0
  36. package/src/generators/application/schema.d.ts +2 -0
  37. package/src/generators/application/schema.json +9 -3
  38. package/src/generators/component/component.d.ts +4 -4
  39. package/src/generators/component/component.js +3 -2
  40. package/src/generators/component/schema.json +7 -7
  41. package/src/generators/custom-server/custom-server.d.ts +1 -1
  42. package/src/generators/custom-server/custom-server.js +34 -9
  43. package/src/generators/custom-server/files/server/main.ts__tmpl__ +4 -4
  44. package/src/generators/custom-server/files/tsconfig.server.json__tmpl__ +2 -0
  45. package/src/generators/custom-server/schema.json +1 -1
  46. package/src/generators/cypress-component-configuration/cypress-component-configuration.d.ts +1 -0
  47. package/src/generators/cypress-component-configuration/cypress-component-configuration.js +23 -10
  48. package/src/generators/cypress-component-configuration/schema.d.ts +1 -0
  49. package/src/generators/cypress-component-configuration/schema.json +1 -1
  50. package/src/generators/init/init.d.ts +4 -3
  51. package/src/generators/init/init.js +30 -44
  52. package/src/generators/init/lib/add-plugin.d.ts +2 -0
  53. package/src/generators/init/lib/add-plugin.js +26 -0
  54. package/src/generators/init/schema.d.ts +3 -4
  55. package/src/generators/init/schema.json +11 -23
  56. package/src/generators/library/lib/normalize-options.js +5 -0
  57. package/src/generators/library/library.js +19 -1
  58. package/src/generators/library/schema.d.ts +2 -1
  59. package/src/generators/library/schema.json +3 -3
  60. package/src/generators/page/page.js +21 -4
  61. package/src/generators/page/schema.d.ts +3 -3
  62. package/src/generators/page/schema.json +5 -5
  63. package/src/migrations/update-17-2-7/remove-eslint-rules-patch.d.ts +2 -0
  64. package/src/migrations/update-17-2-7/remove-eslint-rules-patch.js +15 -0
  65. package/src/plugins/plugin.d.ts +11 -0
  66. package/src/plugins/plugin.js +184 -0
  67. package/src/utils/add-gitignore-entry.js +1 -1
  68. package/src/utils/add-swc-to-custom-server.d.ts +2 -0
  69. package/src/utils/add-swc-to-custom-server.js +37 -0
  70. package/src/utils/styles.d.ts +4 -4
  71. package/src/utils/types.d.ts +1 -0
  72. package/src/utils/versions.d.ts +6 -2
  73. package/src/utils/versions.js +7 -3
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  (The MIT License)
2
2
 
3
- Copyright (c) 2017-2023 Narwhal Technologies Inc.
3
+ Copyright (c) 2017-2024 Narwhal Technologies Inc.
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining
6
6
  a copy of this software and associated documentation files (the
package/README.md CHANGED
@@ -1,4 +1,9 @@
1
- <p style="text-align: center;"><img src="https://raw.githubusercontent.com/nrwl/nx/master/images/nx.png" width="600" alt="Nx - Smart, Fast and Extensible Build System"></p>
1
+ <p style="text-align: center;">
2
+ <picture>
3
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/nrwl/nx/master/images/nx-dark.svg">
4
+ <img alt="Nx - Smart Monorepos · Fast CI" src="https://raw.githubusercontent.com/nrwl/nx/master/images/nx-light.svg" width="100%">
5
+ </picture>
6
+ </p>
2
7
 
3
8
  <div style="text-align: center;">
4
9
 
@@ -15,9 +20,9 @@
15
20
 
16
21
  <hr>
17
22
 
18
- # Nx: Smart, Fast and Extensible Build System
23
+ # Nx: Smart Monorepos · Fast CI
19
24
 
20
- Nx is a next generation build system with first class monorepo support and powerful integrations.
25
+ Nx is a build system with built-in tooling and advanced CI capabilities. It helps you maintain and scale monorepos, both locally and on CI.
21
26
 
22
27
  This package is a [Next.js plugin for Nx](https://nx.dev/next/overview).
23
28
 
@@ -59,5 +64,5 @@ npx nx@latest init
59
64
  - [Blog Posts About Nx](https://blog.nrwl.io/nx/home)
60
65
 
61
66
  <p style="text-align: center;"><a href="https://nx.dev/#learning-materials" target="_blank" rel="noreferrer"><img src="https://raw.githubusercontent.com/nrwl/nx/master/images/nx-courses-and-videos.svg"
62
- width="100%" alt="Nx - Smart, Fast and Extensible Build System"></a></p>
67
+ width="100%" alt="Nx - Smart Monorepos · Fast CI"></a></p>
63
68
 
package/generators.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "extends": ["@nx/react"],
5
5
  "generators": {
6
6
  "init": {
7
- "factory": "./src/generators/init/init#nextInitGenerator",
7
+ "factory": "./src/generators/init/init#nextInitGeneratorInternal",
8
8
  "schema": "./src/generators/init/schema.json",
9
9
  "description": "Initialize the `@nrwl/next` plugin.",
10
10
  "hidden": true
@@ -39,7 +39,7 @@
39
39
  "description": "Set up a custom server."
40
40
  },
41
41
  "cypress-component-configuration": {
42
- "factory": "./src/generators/cypress-component-configuration/cypress-component-configuration",
42
+ "factory": "./src/generators/cypress-component-configuration/cypress-component-configuration#cypressComponentConfigurationInternal",
43
43
  "schema": "./src/generators/cypress-component-configuration/schema.json",
44
44
  "description": "cypress-component-configuration generator"
45
45
  }
package/migrations.json CHANGED
@@ -23,6 +23,12 @@
23
23
  "version": "16.4.0-beta.3",
24
24
  "description": "Update package.json moving @nx/next from dependency to devDependency",
25
25
  "implementation": "./src/migrations/update-16-4-0/update-nx-next-dependency"
26
+ },
27
+ "update-17-2-7": {
28
+ "cli": "nx",
29
+ "version": "17.2.7",
30
+ "description": "Remove patched eslint rule for @next/next/no-html-link-for-pages",
31
+ "implementation": "./src/migrations/update-17-2-7/remove-eslint-rules-patch"
26
32
  }
27
33
  },
28
34
  "packageJsonUpdates": {
@@ -77,6 +83,24 @@
77
83
  "alwaysAddToPackageJson": false
78
84
  }
79
85
  }
86
+ },
87
+ "17.3.1-beta.0": {
88
+ "version": "17.3.1-beta.0",
89
+ "packages": {
90
+ "next": {
91
+ "version": "14.0.4",
92
+ "alwaysAddToPackageJson": false
93
+ }
94
+ }
95
+ },
96
+ "18.0.4": {
97
+ "version": "18.0.4-beta.0",
98
+ "packages": {
99
+ "@swc-node/register": {
100
+ "version": "~1.8.0",
101
+ "alwaysAddToPackageJson": false
102
+ }
103
+ }
80
104
  }
81
105
  }
82
106
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nx/next",
3
- "version": "17.0.2",
3
+ "version": "17.0.4",
4
4
  "private": false,
5
5
  "description": "The Next.js plugin for Nx contains executors and generators for managing Next.js applications and libraries within an Nx workspace. It provides:\n\n\n- Scaffolding for creating, building, serving, linting, and testing Next.js applications.\n\n- Integration with building, serving, and exporting a Next.js application.\n\n- Integration with React libraries within the workspace. \n\nWhen using Next.js in Nx, you get the out-of-the-box support for TypeScript, Cypress, and Jest. No need to configure anything: watch mode, source maps, and typings just work.",
6
6
  "repository": {
@@ -31,26 +31,28 @@
31
31
  "migrations": "./migrations.json"
32
32
  },
33
33
  "peerDependencies": {
34
- "next": ">=13.0.0"
34
+ "next": ">=14.0.0"
35
35
  },
36
36
  "dependencies": {
37
+ "@nx/devkit": "17.0.4",
37
38
  "@babel/plugin-proposal-decorators": "^7.22.7",
38
39
  "@svgr/webpack": "^8.0.1",
39
40
  "chalk": "^4.1.0",
40
41
  "copy-webpack-plugin": "^10.2.4",
42
+ "file-loader": "^6.2.0",
41
43
  "fs-extra": "^11.1.0",
42
44
  "ignore": "^5.0.4",
43
- "semver": "7.5.3",
45
+ "semver": "^7.5.3",
44
46
  "url-loader": "^4.1.1",
45
47
  "tslib": "^2.3.0",
46
48
  "webpack-merge": "^5.8.0",
47
- "@nx/devkit": "17.0.2",
48
- "@nx/js": "17.0.2",
49
- "@nx/eslint": "17.0.2",
50
- "@nx/react": "17.0.2",
51
- "@nx/web": "17.0.2",
52
- "@nx/workspace": "17.0.2",
53
- "@nrwl/next": "17.0.2"
49
+ "@nx/js": "17.0.4",
50
+ "@nx/eslint": "17.0.4",
51
+ "@nx/react": "17.0.4",
52
+ "@nx/web": "17.0.4",
53
+ "@nx/webpack": "17.0.4",
54
+ "@nx/workspace": "17.0.4",
55
+ "@nrwl/next": "17.0.4"
54
56
  },
55
57
  "publishConfig": {
56
58
  "access": "public"
package/plugin.d.ts ADDED
@@ -0,0 +1 @@
1
+ export { createNodes, NextPluginOptions } from './src/plugins/plugin';
package/plugin.js ADDED
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createNodes = void 0;
4
+ var plugin_1 = require("./src/plugins/plugin");
5
+ Object.defineProperty(exports, "createNodes", { enumerable: true, get: function () { return plugin_1.createNodes; } });
@@ -1,12 +1,2 @@
1
1
  import { NxComponentTestingOptions } from '@nx/cypress/plugins/cypress-preset';
2
- export declare function nxComponentTestingPreset(pathToConfig: string, options?: NxComponentTestingOptions): {
3
- specPattern: string;
4
- devServer: {
5
- webpackConfig: import("webpack").Configuration;
6
- framework: "react";
7
- bundler: "webpack";
8
- };
9
- videosFolder: string;
10
- screenshotsFolder: string;
11
- chromeWebSecurity: boolean;
12
- };
2
+ export declare function nxComponentTestingPreset(pathToConfig: string, options?: NxComponentTestingOptions): any;
@@ -8,17 +8,25 @@ const react_1 = require("@nx/react");
8
8
  const webpack_1 = require("@nx/webpack");
9
9
  const path_1 = require("path");
10
10
  function nxComponentTestingPreset(pathToConfig, options) {
11
+ if (global.NX_GRAPH_CREATION || global.NX_CYPRESS_INIT_GENERATOR_RUNNING) {
12
+ // this is only used by plugins, so we don't need the component testing
13
+ // options, cast to any to avoid type errors
14
+ return (0, cypress_preset_1.nxBaseCypressPreset)(pathToConfig);
15
+ }
11
16
  const graph = (0, devkit_1.readCachedProjectGraph)();
12
17
  const { targets: ctTargets, name: ctProjectName } = (0, ct_helpers_1.getProjectConfigByPath)(graph, pathToConfig);
13
18
  const ctTargetName = options?.ctTargetName || 'component-test';
14
19
  const ctConfigurationName = process.env.NX_CYPRESS_TARGET_CONFIGURATION;
15
20
  const ctExecutorContext = (0, ct_helpers_1.createExecutorContext)(graph, ctTargets, ctProjectName, ctTargetName, ctConfigurationName);
16
- const ctExecutorOptions = (0, devkit_1.readTargetOptions)({
17
- project: ctProjectName,
18
- target: ctTargetName,
19
- configuration: ctConfigurationName,
20
- }, ctExecutorContext);
21
- const buildTarget = ctExecutorOptions.devServerTarget;
21
+ let buildTarget = options?.buildTarget;
22
+ if (!buildTarget) {
23
+ const ctExecutorOptions = (0, devkit_1.readTargetOptions)({
24
+ project: ctProjectName,
25
+ target: ctTargetName,
26
+ configuration: ctConfigurationName,
27
+ }, ctExecutorContext);
28
+ buildTarget = ctExecutorOptions.devServerTarget;
29
+ }
22
30
  let buildAssets = [];
23
31
  let buildFileReplacements = [];
24
32
  let buildOuputPath = `dist/${ctProjectName}/.next`;
@@ -31,6 +39,13 @@ function nxComponentTestingPreset(pathToConfig, options) {
31
39
  projectGraph: graph,
32
40
  });
33
41
  const buildProjectConfig = graph.nodes[parsedBuildTarget.project]?.data;
42
+ if (buildProjectConfig?.targets?.[parsedBuildTarget.target]?.executor !==
43
+ '@nx/next:build') {
44
+ throw new Error(`The '${parsedBuildTarget.target}' target of the '${[
45
+ parsedBuildTarget.project,
46
+ ]}' project is not using the '@nx/next:build' executor. ` +
47
+ `Please make sure to use '@nx/next:build' executor in that target to use Cypress Component Testing.`);
48
+ }
34
49
  const buildExecutorContext = (0, ct_helpers_1.createExecutorContext)(graph, buildProjectConfig.targets, parsedBuildTarget.project, parsedBuildTarget.target, parsedBuildTarget.configuration);
35
50
  const buildExecutorOptions = (0, devkit_1.readTargetOptions)({
36
51
  project: parsedBuildTarget.project,
@@ -56,20 +71,21 @@ Able to find CT project, ${!!ctProjectConfig}.`);
56
71
  assets: buildAssets,
57
72
  outputPath: buildOuputPath,
58
73
  outputFileName: 'main.js',
59
- compiler: 'swc',
74
+ compiler: options?.compiler || 'swc',
60
75
  tsConfig: (0, path_1.join)(ctExecutorContext.root, ctProjectConfig.root, 'tsconfig.json'),
61
76
  };
62
- const configure = (0, webpack_1.composePluginsSync)((0, webpack_1.withNx)(), (0, react_1.withReact)({
77
+ const configure = (0, webpack_1.composePluginsSync)((0, webpack_1.withNx)({
78
+ target: 'web',
63
79
  styles: [],
64
80
  scripts: [],
65
81
  postcssConfig: ctProjectConfig.root,
66
- }));
82
+ }), (0, react_1.withReact)({}));
67
83
  const webpackConfig = configure({}, {
68
84
  options: webpackOptions,
69
85
  context: ctExecutorContext,
70
86
  });
71
87
  return {
72
- ...(0, cypress_preset_1.nxBaseCypressPreset)(__filename),
88
+ ...(0, cypress_preset_1.nxBaseCypressPreset)(pathToConfig),
73
89
  specPattern: '**/*.cy.{js,jsx,ts,tsx}',
74
90
  devServer: {
75
91
  ...{ framework: 'react', bundler: 'webpack' },
@@ -4,7 +4,7 @@
4
4
  */
5
5
  import type { NextConfig } from 'next';
6
6
  import type { NextConfigFn } from '../src/utils/config';
7
- import type { ProjectGraphProjectNode } from '@nx/devkit';
7
+ import { type ProjectGraphProjectNode } from '@nx/devkit';
8
8
  export interface WithNxOptions extends NextConfig {
9
9
  nx?: {
10
10
  svgr?: boolean;
@@ -1,42 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.withNx = exports.forNextVersion = exports.getAliasForProject = exports.getNextConfig = void 0;
4
- const baseNXEnvironmentVariables = [
5
- 'NX_BASE',
6
- 'NX_CACHE_DIRECTORY',
7
- 'NX_CACHE_PROJECT_GRAPH',
8
- 'NX_DAEMON',
9
- 'NX_DEFAULT_PROJECT',
10
- 'NX_HEAD',
11
- 'NX_PERF_LOGGING',
12
- 'NX_PROFILE',
13
- 'NX_PROJECT_GRAPH_CACHE_DIRECTORY',
14
- 'NX_INVOKED_BY_RUNNER',
15
- 'NX_PROJECT_GRAPH_MAX_WORKERS',
16
- 'NX_RUNNER',
17
- 'NX_SKIP_NX_CACHE',
18
- 'NX_TASKS_RUNNER',
19
- 'NX_TASKS_RUNNER_DYNAMIC_OUTPUT',
20
- 'NX_VERBOSE_LOGGING',
21
- 'NX_DRY_RUN',
22
- 'NX_INTERACTIVE',
23
- 'NX_GENERATE_QUIET',
24
- 'NX_PREFER_TS_NODE',
25
- 'NX_TASK_TARGET_PROJECT',
26
- 'NX_TASK_TARGET_TARGET',
27
- 'NX_TASK_TARGET_CONFIGURATION',
28
- 'NX_CLI_SET',
29
- 'NX_LOAD_DOT_ENV_FILES',
30
- 'NX_WORKSPACE_ROOT',
31
- 'NX_TASK_HASH',
32
- 'NX_NEXT_DIR',
33
- 'NX_NEXT_OUTPUT_PATH',
34
- 'NX_E2E_RUN_E2E',
35
- 'NX_E2E_CI_CACHE_KEY',
36
- 'NX_MAPPINGS',
37
- 'NX_FILE_TO_RUN',
38
- 'NX_NEXT_PUBLIC_DIR',
39
- ];
40
4
  function regexEqual(x, y) {
41
5
  return (x instanceof RegExp &&
42
6
  y instanceof RegExp &&
@@ -94,10 +58,13 @@ function getNxContext(graph, target) {
94
58
  */
95
59
  function withNx(_nextConfig = {}, context = getWithNxContext()) {
96
60
  return async (phase) => {
97
- const { PHASE_PRODUCTION_SERVER } = await Promise.resolve().then(() => require('next/constants'));
98
- if (phase === PHASE_PRODUCTION_SERVER) {
99
- // If we are running an already built production server, just return the configuration.
100
- // NOTE: Avoid any `require(...)` or `import(...)` statements here. Development dependencies are not available at production runtime.
61
+ const { PHASE_PRODUCTION_SERVER, PHASE_DEVELOPMENT_SERVER } = await Promise.resolve().then(() => require('next/constants'));
62
+ // Two scenarios where we want to skip graph creation:
63
+ // 1. Running production server means the build is already done so we just need to start the Next.js server.
64
+ // 2. During graph creation (i.e. create nodes), we won't have a graph to read, and it is not needed anyway since it's a build-time concern.
65
+ //
66
+ // NOTE: Avoid any `require(...)` or `import(...)` statements here. Development dependencies are not available at production runtime.
67
+ if (PHASE_PRODUCTION_SERVER === phase || global.NX_GRAPH_CREATION) {
101
68
  const { nx, ...validNextConfig } = _nextConfig;
102
69
  return {
103
70
  distDir: '.next',
@@ -106,21 +73,20 @@ function withNx(_nextConfig = {}, context = getWithNxContext()) {
106
73
  }
107
74
  else {
108
75
  const { createProjectGraphAsync, joinPathFragments, offsetFromRoot, workspaceRoot, } = require('@nx/devkit');
109
- // Otherwise, add in webpack and eslint configuration for build or test.
110
- let dependencies = [];
111
- const graph = await createProjectGraphAsync();
76
+ let graph;
77
+ try {
78
+ graph = await createProjectGraphAsync();
79
+ }
80
+ catch (e) {
81
+ throw new Error('Could not create project graph. Please ensure that your workspace is valid.', { cause: e });
82
+ }
112
83
  const originalTarget = {
113
84
  project: process.env.NX_TASK_TARGET_PROJECT,
114
85
  target: process.env.NX_TASK_TARGET_TARGET,
115
86
  configuration: process.env.NX_TASK_TARGET_CONFIGURATION,
116
87
  };
117
- const { node: projectNode, options, projectName: project, targetName, configurationName, } = getNxContext(graph, originalTarget);
88
+ const { node: projectNode, options, projectName: project, } = getNxContext(graph, originalTarget);
118
89
  const projectDirectory = projectNode.data.root;
119
- if (options.buildLibsFromSource === false && targetName) {
120
- const { calculateProjectDependencies, } = require('@nx/js/src/utils/buildable-libs-utils');
121
- const result = calculateProjectDependencies(graph, workspaceRoot, project, targetName, configurationName);
122
- dependencies = result.dependencies;
123
- }
124
90
  // Get next config
125
91
  const nextConfig = getNextConfig(_nextConfig, context);
126
92
  // For Next.js 13.1 and greater, make sure workspace libs are transpiled.
@@ -144,13 +110,20 @@ function withNx(_nextConfig = {}, context = getWithNxContext()) {
144
110
  process.env.NX_NEXT_OUTPUT_PATH || options.outputPath;
145
111
  // outputPath may be undefined if using run-commands or other executors other than @nx/next:build.
146
112
  // In this case, the user should set distDir in their next.config.js.
147
- if (options.outputPath) {
113
+ if (options.outputPath && phase !== PHASE_DEVELOPMENT_SERVER) {
148
114
  const outputDir = `${offsetFromRoot(projectDirectory)}${options.outputPath}`;
115
+ // If running dev-server, we should keep `.next` inside project directory since Turbopack expects this.
116
+ // See: https://github.com/nrwl/nx/issues/19365
149
117
  nextConfig.distDir =
150
118
  nextConfig.distDir && nextConfig.distDir !== '.next'
151
119
  ? joinPathFragments(outputDir, nextConfig.distDir)
152
120
  : joinPathFragments(outputDir, '.next');
153
121
  }
122
+ // If we are running a static serve of the Next.js app, we need to change the output to 'export' and the distDir to 'out'.
123
+ if (process.env.NX_SERVE_STATIC_BUILD_RUNNING === 'true') {
124
+ nextConfig.output = 'export';
125
+ nextConfig.distDir = 'out';
126
+ }
154
127
  const userWebpackConfig = nextConfig.webpack;
155
128
  const { createWebpackConfig } = require('@nx/next/src/utils/config');
156
129
  nextConfig.webpack = (a, b) => createWebpackConfig(workspaceRoot, projectDirectory, options.fileReplacements, options.assets)(userWebpackConfig ? userWebpackConfig(a, b) : a, b);
@@ -251,36 +224,51 @@ function getNextConfig(nextConfig = {}, context = getWithNxContext()) {
251
224
  */
252
225
  // Default SVGR support to be on for projects.
253
226
  if (nx?.svgr !== false) {
227
+ // TODO(v20): Remove file-loader and use `?react` querystring to differentiate between asset and SVGR.
228
+ // It should be:
229
+ // use: [{
230
+ // test: /\.svg$/i,
231
+ // type: 'asset',
232
+ // resourceQuery: /react/, // *.svg?react
233
+ // },
234
+ // {
235
+ // test: /\.svg$/i,
236
+ // issuer: /\.[jt]sx?$/,
237
+ // resourceQuery: { not: [/react/] }, // exclude react component if *.svg?react
238
+ // use: ['@svgr/webpack'],
239
+ // }],
240
+ // See:
241
+ // - SVGR: https://react-svgr.com/docs/webpack/#use-svgr-and-asset-svg-in-the-same-project
242
+ // - Vite: https://www.npmjs.com/package/vite-plugin-svgr
243
+ // - Rsbuild: https://github.com/web-infra-dev/rsbuild/pull/1783
244
+ // Note: We also need a migration for any projects that are using SVGR to convert
245
+ // `import { ReactComponent as X } from './x.svg` to
246
+ // `import X from './x.svg?react';
254
247
  config.module.rules.push({
255
248
  test: /\.svg$/,
256
- oneOf: [
257
- // If coming from JS/TS file, then transform into React component using SVGR.
249
+ issuer: { not: /\.(css|scss|sass)$/ },
250
+ resourceQuery: {
251
+ not: [
252
+ /__next_metadata__/,
253
+ /__next_metadata_route__/,
254
+ /__next_metadata_image_meta__/,
255
+ ],
256
+ },
257
+ use: [
258
258
  {
259
- issuer: /\.[jt]sx?$/,
260
- use: [
261
- {
262
- loader: require.resolve('@svgr/webpack'),
263
- options: {
264
- svgo: false,
265
- titleProp: true,
266
- ref: true,
267
- },
268
- },
269
- {
270
- loader: require.resolve('url-loader'),
271
- options: {
272
- limit: 10000,
273
- name: '[name].[hash:7].[ext]',
274
- },
275
- },
276
- ],
259
+ loader: require.resolve('@svgr/webpack'),
260
+ options: {
261
+ svgo: false,
262
+ titleProp: true,
263
+ ref: true,
264
+ },
277
265
  },
278
- // Fallback to plain URL loader if someone just imports the SVG and references it on the <img src> tag
279
266
  {
280
- loader: require.resolve('url-loader'),
267
+ loader: require.resolve('file-loader'),
281
268
  options: {
282
- limit: 10000,
283
- name: '[name].[hash:7].[ext]',
269
+ // Next.js hard-codes assets to load from "static/media".
270
+ // See: https://github.com/vercel/next.js/blob/53d017d/packages/next/src/build/webpack-config.ts#L1993
271
+ name: 'static/media/[name].[hash].[ext]',
284
272
  },
285
273
  },
286
274
  ],
@@ -291,20 +279,19 @@ function getNextConfig(nextConfig = {}, context = getWithNxContext()) {
291
279
  };
292
280
  }
293
281
  exports.getNextConfig = getNextConfig;
294
- function getNonBaseVariables(oldEnv) {
295
- return Object.keys(oldEnv).filter((env) => !baseNXEnvironmentVariables.includes(env));
296
- }
282
+ // Prevent sensitive keys from being bundled when source code uses entire `process.env` object rather than individual keys (e.g. `process.env.NX_FOO`).
283
+ // TODO(v19): BREAKING: Only support NEXT_PUBLIC_ env vars and ignore NX_ vars since this is a standard Next.js feature.
284
+ const excludedKeys = ['NX_CLOUD_ACCESS_TOKEN', 'NX_CLOUD_ENCRYPTION_KEY'];
297
285
  function getNxEnvironmentVariables() {
298
286
  return Object.keys(process.env)
299
- .filter((env) => /^NX_/i.test(env))
287
+ .filter((env) => !excludedKeys.includes(env) && /^NX_/i.test(env))
300
288
  .reduce((env, key) => {
301
289
  env[key] = process.env[key];
302
290
  return env;
303
291
  }, {});
304
292
  }
305
- let hasWarnedAboutDeprecatedEnvVariables = false;
306
293
  /**
307
- * TODO(v18)
294
+ * TODO(v19)
308
295
  * @deprecated Use Next.js 9.4+ built-in support for environment variables. Reference https://nextjs.org/docs/pages/api-reference/next-config-js/env
309
296
  */
310
297
  function addNxEnvVariables(config) {
@@ -317,16 +304,11 @@ function addNxEnvVariables(config) {
317
304
  .map(([name, value]) => [`process.env.${name}`, `"${value}"`])
318
305
  .filter(([name]) => !maybeDefinePlugin.definitions[name])
319
306
  .forEach(([name, value]) => (maybeDefinePlugin.definitions[name] = value));
320
- const vars = getNonBaseVariables(env);
321
- if (vars.length > 0 && !hasWarnedAboutDeprecatedEnvVariables) {
322
- hasWarnedAboutDeprecatedEnvVariables = true;
323
- console.warn(`Warning, in Nx 18 environment variables starting with NX_ will not be available in the browser, and currently will not work with @nx/next:server executor.\nPlease rename the following environment variables: ${vars.join(', ')} using Next.js' built-in support for environment variables. Reference https://nextjs.org/docs/pages/api-reference/next-config-js/env`);
324
- }
325
307
  }
326
308
  }
327
309
  function getAliasForProject(node, paths) {
328
310
  // Match workspace libs to their alias in tsconfig paths.
329
- for (const [alias, lookup] of Object.entries(paths)) {
311
+ for (const [alias, lookup] of Object.entries(paths ?? {})) {
330
312
  const lookupContainsDepNode = lookup.some((lookupPath) => lookupPath.startsWith(node?.data?.root) ||
331
313
  lookupPath.startsWith('./' + node?.data?.root));
332
314
  if (lookupContainsDepNode) {
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.withStylus = void 0;
4
- // TODO(v18): Remove file, it is here until users migrate over to SASS manually.
4
+ // TODO(v19): Remove file, it is here until users migrate over to SASS manually.
5
5
  function withStylus(configOrFn) {
6
6
  return async (phase) => {
7
7
  throw new Error(`Stylus support has been removed and you should use the built-in SASS support. Remove the "withStylus" plugin from your Next.js config, and rename your files from .styl to .scss.`);
@@ -12,6 +12,7 @@ const create_next_config_file_1 = require("./lib/create-next-config-file");
12
12
  const check_project_1 = require("./lib/check-project");
13
13
  const child_process_1 = require("child_process");
14
14
  const create_cli_options_1 = require("../../utils/create-cli-options");
15
+ const exit_codes_1 = require("nx/src/utils/exit-codes");
15
16
  let childProcess;
16
17
  async function buildExecutor(options, context) {
17
18
  // Cast to any to overwrite NODE_ENV
@@ -34,9 +35,14 @@ async function buildExecutor(options, context) {
34
35
  try {
35
36
  await runCliBuild(devkit_1.workspaceRoot, projectRoot, options);
36
37
  }
37
- catch (error) {
38
- devkit_1.logger.error(`Error occurred while trying to run the build command`);
39
- devkit_1.logger.error(error);
38
+ catch ({ error, code, signal }) {
39
+ if (code || signal) {
40
+ devkit_1.logger.error(`Build process exited due to ${code ? 'code ' + code : ''} ${code && signal ? 'and' : ''} ${signal ? 'signal ' + signal : ''}`);
41
+ }
42
+ else {
43
+ devkit_1.logger.error(`Error occurred while trying to run the build command`);
44
+ devkit_1.logger.error(error);
45
+ }
40
46
  return { success: false };
41
47
  }
42
48
  finally {
@@ -85,21 +91,26 @@ function runCliBuild(workspaceRoot, projectRoot, options) {
85
91
  return new Promise((resolve, reject) => {
86
92
  childProcess = (0, child_process_1.fork)(require.resolve('next/dist/bin/next'), ['build', ...args], {
87
93
  cwd: (0, path_1.resolve)(workspaceRoot, projectRoot),
88
- stdio: 'inherit',
94
+ stdio: ['ignore', 'inherit', 'inherit', 'ipc'],
89
95
  env: process.env,
90
96
  });
91
97
  // Ensure the child process is killed when the parent exits
92
98
  process.on('exit', () => childProcess.kill());
93
- process.on('SIGTERM', () => childProcess.kill());
99
+ process.on('SIGTERM', (signal) => {
100
+ reject({ code: (0, exit_codes_1.signalToCode)(signal), signal });
101
+ });
102
+ process.on('SIGINT', (signal) => {
103
+ reject({ code: (0, exit_codes_1.signalToCode)(signal), signal });
104
+ });
94
105
  childProcess.on('error', (err) => {
95
- reject(err);
106
+ reject({ error: err });
96
107
  });
97
- childProcess.on('exit', (code) => {
108
+ childProcess.on('exit', (code, signal) => {
98
109
  if (code === 0) {
99
- resolve(code);
110
+ resolve({ code, signal });
100
111
  }
101
112
  else {
102
- reject(code);
113
+ reject({ code, signal });
103
114
  }
104
115
  });
105
116
  });
@@ -41,7 +41,10 @@ function createNextConfigFile(options, context) {
41
41
  const moduleFilesToCopy = getRelativeFilesToCopy(configRelativeToProjectRoot, projectRoot);
42
42
  for (const moduleFile of moduleFilesToCopy) {
43
43
  (0, fs_extra_1.ensureDirSync)((0, path_1.dirname)((0, path_1.join)(context.root, options.outputPath, moduleFile)));
44
- (0, fs_extra_1.copyFileSync)((0, path_1.join)(context.root, projectRoot, moduleFile), (0, path_1.join)(context.root, options.outputPath, moduleFile));
44
+ // We already generate a build version of package.json in the dist folder.
45
+ if (moduleFile !== 'package.json') {
46
+ (0, fs_extra_1.copyFileSync)((0, path_1.join)(context.root, projectRoot, moduleFile), (0, path_1.join)(context.root, options.outputPath, moduleFile));
47
+ }
45
48
  }
46
49
  }
47
50
  exports.createNextConfigFile = createNextConfigFile;
@@ -80,7 +83,7 @@ exports.getWithNxContent = getWithNxContent;
80
83
  function findNextConfigPath(dirname, userDefinedConfigPath) {
81
84
  if (userDefinedConfigPath) {
82
85
  const file = userDefinedConfigPath;
83
- if ((0, fs_extra_1.existsSync)(file))
86
+ if ((0, fs_extra_1.existsSync)((0, path_1.join)(dirname, file)))
84
87
  return file;
85
88
  throw new Error(`Cannot find the Next.js config file: ${userDefinedConfigPath}. Is the path correct in project.json?`);
86
89
  }
@@ -10,7 +10,16 @@ function updatePackageJson(packageJson, context) {
10
10
  }
11
11
  packageJson.dependencies ??= {};
12
12
  // These are always required for a production Next.js app to run.
13
- const requiredPackages = ['react', 'react-dom', 'next', 'typescript'];
13
+ // sharp is for next/image https://nextjs.org/docs/messages/sharp-missing-in-production
14
+ // critters is required for experimental optimizing CSS
15
+ const requiredPackages = [
16
+ 'react',
17
+ 'react-dom',
18
+ 'next',
19
+ 'typescript',
20
+ 'sharp',
21
+ 'critters',
22
+ ];
14
23
  for (const pkg of requiredPackages) {
15
24
  const externalNode = context.projectGraph.externalNodes[`npm:${pkg}`];
16
25
  if (externalNode) {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 2,
3
3
  "outputCapture": "pipe",
4
- "$schema": "http://json-schema.org/schema",
4
+ "$schema": "https://json-schema.org/schema",
5
5
  "cli": "nx",
6
6
  "title": "Next Build",
7
7
  "description": "Build a Next.js app.",