@nx/next 24.0.0-beta.2 → 24.0.0-beta.3

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 (50) hide show
  1. package/dist/plugins/component-testing.js +19 -62
  2. package/dist/plugins/with-nx.d.ts +14 -10
  3. package/dist/plugins/with-nx.js +24 -255
  4. package/dist/src/generators/application/application.js +1 -2
  5. package/dist/src/generators/application/files/common/next.config.js__tmpl__ +0 -22
  6. package/dist/src/generators/application/lib/add-e2e.js +5 -6
  7. package/dist/src/generators/application/lib/add-linting.js +0 -1
  8. package/dist/src/generators/application/lib/add-project.js +1 -46
  9. package/dist/src/generators/application/lib/add-vitest.js +0 -1
  10. package/dist/src/generators/application/lib/normalize-options.js +0 -4
  11. package/dist/src/generators/application/schema.d.ts +0 -1
  12. package/dist/src/generators/custom-server/custom-server.js +6 -25
  13. package/dist/src/generators/custom-server/files/server/main.ts__tmpl__ +3 -3
  14. package/dist/src/generators/custom-server/files/tsconfig.server.json__tmpl__ +1 -1
  15. package/dist/src/generators/cypress-component-configuration/cypress-component-configuration.js +1 -14
  16. package/dist/src/generators/cypress-component-configuration/schema.d.ts +0 -1
  17. package/dist/src/generators/init/init.js +14 -28
  18. package/dist/src/generators/init/schema.d.ts +0 -1
  19. package/dist/src/generators/library/lib/add-rollup-server-entry.js +7 -16
  20. package/dist/src/generators/library/lib/normalize-options.js +0 -5
  21. package/dist/src/generators/library/library.js +1 -2
  22. package/dist/src/generators/library/schema.d.ts +0 -1
  23. package/dist/src/migrations/update-24-0-0/finish-inferred-conversion.md +12 -0
  24. package/dist/src/migrations/update-24-0-0/migrate-config-helpers.md +80 -0
  25. package/dist/src/migrations/update-24-0-0/remove-deprecated-executors.d.ts +6 -0
  26. package/dist/src/migrations/update-24-0-0/remove-deprecated-executors.js +18 -0
  27. package/dist/src/migrations/update-24-0-0/remove-deprecated-executors.md +89 -0
  28. package/dist/src/utils/compose-plugins.d.ts +6 -1
  29. package/dist/src/utils/compose-plugins.js +20 -29
  30. package/dist/src/utils/deprecation.d.ts +0 -5
  31. package/dist/src/utils/deprecation.js +9 -31
  32. package/executors.json +1 -12
  33. package/migrations.json +12 -0
  34. package/package.json +13 -13
  35. package/dist/src/executors/build/build.impl.d.ts +0 -5
  36. package/dist/src/executors/build/build.impl.js +0 -154
  37. package/dist/src/executors/build/lib/check-project.d.ts +0 -1
  38. package/dist/src/executors/build/lib/check-project.js +0 -11
  39. package/dist/src/executors/build/lib/create-next-config-file.d.ts +0 -14
  40. package/dist/src/executors/build/lib/create-next-config-file.js +0 -171
  41. package/dist/src/executors/build/lib/update-package-json.d.ts +0 -3
  42. package/dist/src/executors/build/lib/update-package-json.js +0 -31
  43. package/dist/src/executors/build/schema.json +0 -98
  44. package/dist/src/executors/server/custom-server.impl.d.ts +0 -6
  45. package/dist/src/executors/server/custom-server.impl.js +0 -37
  46. package/dist/src/executors/server/schema.json +0 -85
  47. package/dist/src/executors/server/server.impl.d.ts +0 -6
  48. package/dist/src/executors/server/server.impl.js +0 -115
  49. package/dist/src/utils/runtime-version-utils.d.ts +0 -7
  50. package/dist/src/utils/runtime-version-utils.js +0 -28
package/migrations.json CHANGED
@@ -35,6 +35,18 @@
35
35
  "description": "Add `@svgr/webpack` when a next config references it.",
36
36
  "implementation": "./dist/src/migrations/update-23-2-0/add-svgr-webpack-if-used",
37
37
  "documentation": "./dist/src/migrations/update-23-2-0/add-svgr-webpack-if-used.md"
38
+ },
39
+ "remove-deprecated-executors": {
40
+ "version": "24.0.0-beta.3",
41
+ "description": "Converts targets using the removed `@nx/next` executors to inferred tasks; an AI prompt finishes the targets the converter cannot convert safely and validates the project graph.",
42
+ "implementation": "./dist/src/migrations/update-24-0-0/remove-deprecated-executors",
43
+ "prompt": "./dist/src/migrations/update-24-0-0/finish-inferred-conversion.md",
44
+ "documentation": "./dist/src/migrations/update-24-0-0/remove-deprecated-executors.md"
45
+ },
46
+ "update-24-0-0-migrate-config-helpers": {
47
+ "version": "24.0.0-beta.3",
48
+ "description": "Migrate deprecated next configuration helpers while preserving custom behavior.",
49
+ "prompt": "./dist/src/migrations/update-24-0-0/migrate-config-helpers.md"
38
50
  }
39
51
  },
40
52
  "packageJsonUpdates": {
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@nx/next",
3
- "version": "24.0.0-beta.2",
3
+ "version": "24.0.0-beta.3",
4
4
  "private": false,
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, Playwright, Cypress, and Jest. No need to configure anything: watch mode, source maps, and typings just work.",
5
+ "description": "The Next.js plugin for Nx infers tasks and provides 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, Playwright, Cypress, and Jest. No need to configure anything: watch mode, source maps, and typings just work.",
6
6
  "repository": {
7
7
  "type": "git",
8
8
  "url": "https://github.com/nrwl/nx.git",
@@ -68,7 +68,7 @@
68
68
  },
69
69
  "peerDependencies": {
70
70
  "next": ">=14.0.0 <17.0.0",
71
- "@nx/webpack": "24.0.0-beta.2"
71
+ "@nx/webpack": "24.0.0-beta.3"
72
72
  },
73
73
  "peerDependenciesMeta": {
74
74
  "@nx/webpack": {
@@ -76,26 +76,26 @@
76
76
  }
77
77
  },
78
78
  "dependencies": {
79
- "@nx/devkit": "24.0.0-beta.2",
79
+ "@nx/devkit": "24.0.0-beta.3",
80
80
  "@babel/plugin-proposal-decorators": "^7.22.7",
81
81
  "copy-webpack-plugin": "^14.0.0",
82
82
  "ignore": "^7.0.5",
83
83
  "semver": "^7.6.3",
84
84
  "tslib": "^2.3.0",
85
85
  "webpack-merge": "^5.8.0",
86
- "@nx/js": "24.0.0-beta.2",
87
- "@nx/eslint": "24.0.0-beta.2",
88
- "@nx/react": "24.0.0-beta.2",
89
- "@nx/web": "24.0.0-beta.2",
86
+ "@nx/js": "24.0.0-beta.3",
87
+ "@nx/eslint": "24.0.0-beta.3",
88
+ "@nx/react": "24.0.0-beta.3",
89
+ "@nx/web": "24.0.0-beta.3",
90
90
  "@phenomnomnominal/tsquery": "~6.2.0"
91
91
  },
92
92
  "devDependencies": {
93
- "@nx/cypress": "24.0.0-beta.2",
94
- "@nx/playwright": "24.0.0-beta.2",
95
- "@nx/vitest": "24.0.0-beta.2",
96
- "@nx/webpack": "24.0.0-beta.2",
93
+ "@nx/cypress": "24.0.0-beta.3",
94
+ "@nx/playwright": "24.0.0-beta.3",
95
+ "@nx/vitest": "24.0.0-beta.3",
96
+ "@nx/webpack": "24.0.0-beta.3",
97
97
  "next": "15.5.25",
98
- "nx": "24.0.0-beta.2"
98
+ "nx": "24.0.0-beta.3"
99
99
  },
100
100
  "publishConfig": {
101
101
  "access": "public"
@@ -1,5 +0,0 @@
1
- import { ExecutorContext } from '@nx/devkit';
2
- import { NextBuildBuilderOptions } from '../../utils/types';
3
- export default function buildExecutor(options: NextBuildBuilderOptions, context: ExecutorContext): Promise<{
4
- success: boolean;
5
- }>;
@@ -1,154 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.default = buildExecutor;
4
- const devkit_1 = require("@nx/devkit");
5
- const js_1 = require("@nx/js");
6
- const path_1 = require("path");
7
- const node_fs_1 = require("node:fs");
8
- const promises_1 = require("node:fs/promises");
9
- const semver_1 = require("semver");
10
- const update_package_json_1 = require("./lib/update-package-json");
11
- const create_next_config_file_1 = require("./lib/create-next-config-file");
12
- const check_project_1 = require("./lib/check-project");
13
- const child_process_1 = require("child_process");
14
- const internal_1 = require("@nx/devkit/internal");
15
- const runtime_version_utils_1 = require("../../utils/runtime-version-utils");
16
- const deprecation_1 = require("../../utils/deprecation");
17
- let childProcess;
18
- async function buildExecutor(options, context) {
19
- (0, deprecation_1.warnNextBuildExecutorDeprecation)();
20
- // Cast to any to overwrite NODE_ENV
21
- process.env.NODE_ENV ||= 'production';
22
- const projectRoot = context.projectGraph.nodes[context.projectName].data.root;
23
- (0, check_project_1.checkPublicDirectory)(projectRoot);
24
- // Set `__NEXT_REACT_ROOT` based on installed ReactDOM version
25
- const packageJsonPath = (0, path_1.join)(projectRoot, 'package.json');
26
- const packageJson = (0, node_fs_1.existsSync)(packageJsonPath)
27
- ? (0, devkit_1.readJsonFile)(packageJsonPath)
28
- : undefined;
29
- const rootPackageJson = (0, devkit_1.readJsonFile)((0, path_1.join)(context.root, 'package.json'));
30
- const reactDomVersion = packageJson?.dependencies?.['react-dom'] ??
31
- rootPackageJson.dependencies?.['react-dom'];
32
- const hasReact18 = reactDomVersion &&
33
- (0, semver_1.gte)((0, internal_1.checkAndCleanWithSemver)('react-dom', reactDomVersion), '18.0.0');
34
- if (hasReact18) {
35
- process.env['__NEXT_REACT_ROOT'] ||= 'true';
36
- }
37
- try {
38
- await runCliBuild(devkit_1.workspaceRoot, projectRoot, options);
39
- }
40
- catch ({ error, code, signal }) {
41
- if (code || signal) {
42
- devkit_1.logger.error(`Build process exited due to ${code ? 'code ' + code : ''} ${code && signal ? 'and' : ''} ${signal ? 'signal ' + signal : ''}`);
43
- }
44
- else {
45
- devkit_1.logger.error(`Error occurred while trying to run the build command`);
46
- devkit_1.logger.error(error);
47
- }
48
- return { success: false };
49
- }
50
- finally {
51
- if (childProcess) {
52
- childProcess.kill();
53
- }
54
- }
55
- await (0, promises_1.mkdir)(options.outputPath, { recursive: true });
56
- const builtPackageJson = (0, js_1.createPackageJson)(context.projectName, context.projectGraph, {
57
- target: context.targetName,
58
- root: context.root,
59
- isProduction: !options.includeDevDependenciesInPackageJson, // By default we remove devDependencies since this is a production build.
60
- skipOverrides: options.skipOverrides,
61
- skipPackageManager: options.skipPackageManager,
62
- });
63
- // Update `package.json` to reflect how users should run the build artifacts
64
- builtPackageJson.scripts = {
65
- start: 'next start',
66
- };
67
- (0, update_package_json_1.updatePackageJson)(builtPackageJson, context);
68
- const packageManager = (0, devkit_1.detectPackageManager)(context.root);
69
- if (options.generateLockfile) {
70
- (0, js_1.generatePrunedDeployOutput)(builtPackageJson, context.projectGraph, projectRoot, {
71
- outputDirectory: options.outputPath,
72
- packageManager,
73
- workspaceRoot: context.root,
74
- });
75
- }
76
- (0, devkit_1.writeJsonFile)(`${options.outputPath}/package.json`, builtPackageJson);
77
- // If output path is different from source path, then copy over the config and public files.
78
- // This is the default behavior when running `nx build <app>`.
79
- if (options.outputPath.replace(/\/$/, '') !== projectRoot) {
80
- (0, create_next_config_file_1.createNextConfigFile)(options, context);
81
- (0, node_fs_1.cpSync)((0, path_1.join)(projectRoot, 'public'), (0, path_1.join)(options.outputPath, 'public'), {
82
- dereference: true,
83
- recursive: true,
84
- });
85
- }
86
- return { success: true };
87
- }
88
- function runCliBuild(workspaceRoot, projectRoot, options) {
89
- const { experimentalAppOnly, experimentalBuildMode, profile, debug, outputPath, turbo, webpack, } = options;
90
- // Set output path here since it can also be set via CLI
91
- // We can retrieve it inside plugins/with-nx
92
- process.env.NX_NEXT_OUTPUT_PATH ??= outputPath;
93
- // Check for conflicting flags
94
- if (turbo && webpack) {
95
- throw new Error('Cannot specify both --turbo and --webpack flags. Please use only one bundler option.');
96
- }
97
- // Determine bundler flag based on Next.js version and options
98
- const cliOptions = {
99
- experimentalAppOnly,
100
- experimentalBuildMode,
101
- profile,
102
- debug,
103
- };
104
- const nextJsVersion = (0, runtime_version_utils_1.getInstalledNextVersionRuntime)();
105
- const isNext16Plus = nextJsVersion !== null && nextJsVersion >= 16;
106
- if (isNext16Plus) {
107
- // Next.js 16+: Turbopack is default, use --webpack to opt-in to webpack
108
- if (webpack) {
109
- cliOptions.webpack = true;
110
- devkit_1.logger.info('Using webpack bundler for build (Next.js 16+ detected)');
111
- }
112
- else if (turbo) {
113
- devkit_1.logger.warn('The --turbo flag is redundant in Next.js 16+ as Turbopack is now the default bundler. You can remove this flag.');
114
- }
115
- }
116
- else {
117
- // Next.js 15 and below: webpack is default, use --turbo to opt-in to turbopack
118
- if (turbo) {
119
- cliOptions.turbo = true;
120
- }
121
- else if (webpack) {
122
- devkit_1.logger.warn('The --webpack flag is only applicable in Next.js 16 and above. It will be ignored.');
123
- }
124
- }
125
- const args = (0, internal_1.createCliOptions)(cliOptions);
126
- return new Promise((resolve, reject) => {
127
- childProcess = (0, child_process_1.fork)(require.resolve('next/dist/bin/next'), ['build', ...args], {
128
- cwd: (0, path_1.resolve)(workspaceRoot, projectRoot),
129
- stdio: ['ignore', 'inherit', 'inherit', 'ipc'],
130
- env: process.env,
131
- });
132
- // Ensure the child process is killed when the parent exits
133
- process.on('exit', () => childProcess.kill());
134
- process.on('SIGTERM', (signal) => {
135
- reject({ code: (0, internal_1.signalToCode)(signal), signal });
136
- });
137
- process.on('SIGINT', (signal) => {
138
- reject({ code: (0, internal_1.signalToCode)(signal), signal });
139
- });
140
- childProcess.on('error', (err) => {
141
- reject({ error: err });
142
- });
143
- childProcess.on('exit', (code, signal) => {
144
- if (code === null)
145
- code = (0, internal_1.signalToCode)(signal);
146
- if (code === 0) {
147
- resolve({ code, signal });
148
- }
149
- else {
150
- reject({ code, signal });
151
- }
152
- });
153
- });
154
- }
@@ -1 +0,0 @@
1
- export declare function checkPublicDirectory(root: string): void;
@@ -1,11 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.checkPublicDirectory = checkPublicDirectory;
4
- const devkit_1 = require("@nx/devkit");
5
- const node_fs_1 = require("node:fs");
6
- const path_1 = require("path");
7
- function checkPublicDirectory(root) {
8
- if ((0, node_fs_1.readdirSync)((0, path_1.join)(root, 'public')).length === 0) {
9
- devkit_1.logger.warn('public directory cannot be empty. This may result in errors during the deployment. Consider adding a public/.gitkeep file');
10
- }
11
- }
@@ -1,14 +0,0 @@
1
- import type { ExecutorContext } from '@nx/devkit';
2
- import type { NextBuildBuilderOptions } from '../../../utils/types';
3
- export declare function createNextConfigFile(options: NextBuildBuilderOptions, context: ExecutorContext): void;
4
- export declare function getWithNxContent({ file, content }?: {
5
- file: string;
6
- content: string;
7
- }): string;
8
- export declare function findNextConfigPath(dirname: string, userDefinedConfigPath?: string): string;
9
- export declare function getRelativeFilesToCopy(fileName: string, cwd: string): string[];
10
- export declare function getRelativeImports({ file, content, }: {
11
- file: string;
12
- content: string;
13
- }): string[];
14
- export declare function ensureFileExtensions(files: string[], absoluteDir: string): string[];
@@ -1,171 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createNextConfigFile = createNextConfigFile;
4
- exports.getWithNxContent = getWithNxContent;
5
- exports.findNextConfigPath = findNextConfigPath;
6
- exports.getRelativeFilesToCopy = getRelativeFilesToCopy;
7
- exports.getRelativeImports = getRelativeImports;
8
- exports.ensureFileExtensions = ensureFileExtensions;
9
- const tslib_1 = require("tslib");
10
- const devkit_1 = require("@nx/devkit");
11
- const ts = tslib_1.__importStar(require("typescript"));
12
- const node_fs_1 = require("node:fs");
13
- const path_1 = require("path");
14
- const js_1 = require("@nx/js");
15
- function createNextConfigFile(options, context) {
16
- // Don't overwrite the next.config.js file if output path is the same as the source path.
17
- if (options.outputPath.replace(/\/$/, '') ===
18
- context.projectGraph.nodes[context.projectName].data.root) {
19
- return;
20
- }
21
- const projectRoot = context.projectGraph.nodes[context.projectName].data.root;
22
- const configRelativeToProjectRoot = findNextConfigPath(projectRoot,
23
- // If user passed a config then it is relative to the workspace root, need to normalize it to be relative to the project root.
24
- options.nextConfig ? (0, path_1.relative)(projectRoot, options.nextConfig) : undefined);
25
- const configAbsolutePath = (0, path_1.join)(projectRoot, configRelativeToProjectRoot);
26
- if (!(0, node_fs_1.existsSync)(configAbsolutePath)) {
27
- throw new Error('next.config.js not found');
28
- }
29
- // Copy config file and our `.nx-helpers` folder to remove dependency on @nrwl/next for production build.
30
- const helpersPath = (0, path_1.join)(options.outputPath, '.nx-helpers');
31
- (0, node_fs_1.mkdirSync)(helpersPath, { recursive: true });
32
- (0, node_fs_1.copyFileSync)((0, path_1.join)(__dirname, '../../../utils/compose-plugins.js'), (0, path_1.join)(helpersPath, 'compose-plugins.js'));
33
- (0, node_fs_1.writeFileSync)((0, path_1.join)(helpersPath, 'with-nx.js'), getWithNxContent());
34
- (0, node_fs_1.writeFileSync)((0, path_1.join)(helpersPath, 'compiled.js'), `
35
- const withNx = require('./with-nx');
36
- module.exports = withNx;
37
- module.exports.withNx = withNx;
38
- module.exports.composePlugins = require('./compose-plugins').composePlugins;
39
- `);
40
- (0, node_fs_1.writeFileSync)((0, path_1.join)(options.outputPath, configRelativeToProjectRoot), (0, node_fs_1.readFileSync)(configAbsolutePath)
41
- .toString()
42
- .replace(/["']@nx\/next["']/, `'./.nx-helpers/compiled.js'`)
43
- // TODO(v17): Remove this once users have all migrated to new @nx scope and import from '@nx/next' not the deep import paths.
44
- .replace('@nx/next/plugins/with-nx', './.nx-helpers/compiled.js')
45
- .replace('@nrwl/next/plugins/with-nx', './.nx-helpers/compiled.js'));
46
- // Find all relative imports needed by next.config.js and copy them to the dist folder.
47
- const moduleFilesToCopy = getRelativeFilesToCopy(configRelativeToProjectRoot, projectRoot);
48
- for (const moduleFile of moduleFilesToCopy) {
49
- const moduleFileDir = (0, path_1.dirname)((0, path_1.join)(context.root, options.outputPath, moduleFile));
50
- (0, node_fs_1.mkdirSync)(moduleFileDir, { recursive: true });
51
- // We already generate a build version of package.json in the dist folder.
52
- if (moduleFile !== 'package.json') {
53
- (0, node_fs_1.copyFileSync)((0, path_1.join)(context.root, projectRoot, moduleFile), (0, path_1.join)(context.root, options.outputPath, moduleFile));
54
- }
55
- }
56
- }
57
- function readSource(getFile) {
58
- return {
59
- file: getFile(),
60
- content: (0, node_fs_1.readFileSync)(getFile()).toString(),
61
- };
62
- }
63
- // Exported for testing
64
- function getWithNxContent({ file, content } = readSource(() => (0, path_1.join)(__dirname, '../../../../plugins/with-nx.js'))) {
65
- const withNxSource = ts.createSourceFile(file, content, ts.ScriptTarget.Latest, true);
66
- const getWithNxContextDeclaration = (0, js_1.findNodes)(withNxSource, ts.SyntaxKind.FunctionDeclaration)?.find((node) => node.name?.text === 'getWithNxContext');
67
- if (getWithNxContextDeclaration) {
68
- content = (0, devkit_1.applyChangesToString)(content, [
69
- {
70
- type: devkit_1.ChangeType.Delete,
71
- start: getWithNxContextDeclaration.getStart(withNxSource),
72
- length: getWithNxContextDeclaration.getWidth(withNxSource),
73
- },
74
- {
75
- type: devkit_1.ChangeType.Insert,
76
- index: getWithNxContextDeclaration.getStart(withNxSource),
77
- text: (0, devkit_1.stripIndents) `function getWithNxContext() {
78
- return {
79
- workspaceRoot: '${
80
- // For Windows, paths like C:\Users\foo\bar need to be written as C:\\Users\\foo\\bar,
81
- // or else when the file is read back, the single "\" will be treated as an escape character.
82
- devkit_1.workspaceRoot.replaceAll('\\', '\\\\')}',
83
- libsDir: '${(0, devkit_1.workspaceLayout)().libsDir}'
84
- }
85
- }`,
86
- },
87
- ]);
88
- }
89
- return content;
90
- }
91
- function findNextConfigPath(dirname, userDefinedConfigPath) {
92
- if (userDefinedConfigPath) {
93
- const file = userDefinedConfigPath;
94
- if ((0, node_fs_1.existsSync)((0, path_1.join)(dirname, file)))
95
- return file;
96
- throw new Error(`Cannot find the Next.js config file: ${userDefinedConfigPath}. Is the path correct in project.json?`);
97
- }
98
- const candidates = [
99
- 'next.config.js',
100
- 'next.config.cjs',
101
- 'next.config.mjs',
102
- 'next.config.ts',
103
- ];
104
- for (const candidate of candidates) {
105
- if ((0, node_fs_1.existsSync)((0, path_1.join)(dirname, candidate)))
106
- return candidate;
107
- }
108
- throw new Error(`Cannot find any of the following files in your project: ${candidates.join(', ')}. Is this a Next.js project?`);
109
- }
110
- // Exported for testing
111
- function getRelativeFilesToCopy(fileName, cwd) {
112
- const seen = new Set();
113
- const collected = new Set();
114
- function doCollect(currFile) {
115
- // Prevent circular dependencies from causing infinite loop
116
- if (seen.has(currFile))
117
- return;
118
- seen.add(currFile);
119
- const absoluteFilePath = (0, path_1.join)(cwd, currFile);
120
- const content = (0, node_fs_1.readFileSync)(absoluteFilePath).toString();
121
- const files = getRelativeImports({ file: currFile, content });
122
- const modules = ensureFileExtensions(files, (0, path_1.dirname)(absoluteFilePath));
123
- const relativeDirPath = (0, path_1.dirname)(currFile);
124
- for (const moduleName of modules) {
125
- const relativeModulePath = (0, path_1.join)(relativeDirPath, moduleName);
126
- collected.add(relativeModulePath);
127
- doCollect(relativeModulePath);
128
- }
129
- }
130
- doCollect(fileName);
131
- return Array.from(collected);
132
- }
133
- // Exported for testing
134
- function getRelativeImports({ file, content, }) {
135
- const source = ts.createSourceFile(file, content, ts.ScriptTarget.Latest, true);
136
- const callExpressionsOrImportDeclarations = (0, js_1.findNodes)(source, [
137
- ts.SyntaxKind.CallExpression,
138
- ts.SyntaxKind.ImportDeclaration,
139
- ]);
140
- const modulePaths = [];
141
- for (const node of callExpressionsOrImportDeclarations) {
142
- if (node.kind === ts.SyntaxKind.ImportDeclaration) {
143
- modulePaths.push(stripOuterQuotes(node.moduleSpecifier.getText(source)));
144
- }
145
- else {
146
- if (node.expression.getText(source) === 'require') {
147
- modulePaths.push(stripOuterQuotes(node.arguments[0].getText(source)));
148
- }
149
- }
150
- }
151
- return modulePaths.filter((path) => path.startsWith('.'));
152
- }
153
- function stripOuterQuotes(str) {
154
- return str.match(/^["'](.*)["']/)?.[1] ?? str;
155
- }
156
- // Exported for testing
157
- function ensureFileExtensions(files, absoluteDir) {
158
- const extensions = ['.js', '.cjs', '.mjs', '.json', '.ts'];
159
- return files.map((file) => {
160
- const providedExt = (0, path_1.extname)(file);
161
- if (providedExt && extensions.includes(providedExt))
162
- return file;
163
- const ext = extensions.find((ext) => (0, node_fs_1.existsSync)((0, path_1.join)(absoluteDir, file + ext)));
164
- if (ext) {
165
- return file + ext;
166
- }
167
- else {
168
- throw new Error(`Cannot find file "${file}" with any of the following extensions: ${extensions.join(', ')}`);
169
- }
170
- });
171
- }
@@ -1,3 +0,0 @@
1
- import type { ExecutorContext } from '@nx/devkit';
2
- import { type PackageJson } from '@nx/devkit/internal';
3
- export declare function updatePackageJson(packageJson: PackageJson, context: ExecutorContext): void;
@@ -1,31 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.updatePackageJson = updatePackageJson;
4
- function updatePackageJson(packageJson, context) {
5
- if (!packageJson.scripts) {
6
- packageJson.scripts = {};
7
- }
8
- if (!packageJson.scripts.start) {
9
- packageJson.scripts.start = 'next start';
10
- }
11
- packageJson.dependencies ??= {};
12
- // These are always required for a production Next.js app to run.
13
- // sharp is for next/image https://nextjs.org/docs/messages/sharp-missing-in-production
14
- // critters is required for experimental optimizing CSS
15
- // semver is required by .nx-helpers/with-nx.js at runtime
16
- const requiredPackages = [
17
- 'react',
18
- 'react-dom',
19
- 'next',
20
- 'typescript',
21
- 'sharp',
22
- 'critters',
23
- 'semver',
24
- ];
25
- for (const pkg of requiredPackages) {
26
- const externalNode = context.projectGraph.externalNodes[`npm:${pkg}`];
27
- if (externalNode) {
28
- packageJson.dependencies[pkg] ??= externalNode.data.version;
29
- }
30
- }
31
- }
@@ -1,98 +0,0 @@
1
- {
2
- "version": 2,
3
- "outputCapture": "pipe",
4
- "$schema": "https://json-schema.org/schema",
5
- "cli": "nx",
6
- "title": "Next Build",
7
- "description": "Build a Next.js app.",
8
- "type": "object",
9
- "x-deprecated": "The `@nx/next:build` executor is deprecated and will be removed in Nx v24. Run `nx g @nx/next:convert-to-inferred` to migrate to the `@nx/next/plugin` inferred plugin. See https://nx.dev/docs/guides/tasks--caching/convert-to-inferred for details.",
10
- "properties": {
11
- "outputPath": {
12
- "type": "string",
13
- "description": "The output path of the generated files.",
14
- "x-completion-type": "directory",
15
- "x-priority": "important"
16
- },
17
- "fileReplacements": {
18
- "description": "Replace files with other files in the build.",
19
- "type": "array",
20
- "items": {
21
- "type": "object",
22
- "properties": {
23
- "replace": {
24
- "type": "string",
25
- "description": "The file to be replaced.",
26
- "x-completion-type": "file"
27
- },
28
- "with": {
29
- "type": "string",
30
- "description": "The file to replace with.",
31
- "x-completion-type": "file"
32
- }
33
- },
34
- "additionalProperties": false,
35
- "required": ["replace", "with"]
36
- },
37
- "default": []
38
- },
39
- "nextConfig": {
40
- "description": "Path (relative to workspace root) to a function which takes phase, config, and builder options, and returns the resulting config. This is an advanced option and should not be used with a normal Next.js config file (i.e. `next.config.js`).",
41
- "type": "string",
42
- "x-completion-type": "file",
43
- "x-completion-glob": "next?(*).js",
44
- "x-priority": "important"
45
- },
46
- "buildLibsFromSource": {
47
- "type": "boolean",
48
- "description": "Read buildable libraries from source instead of building them separately.",
49
- "default": true
50
- },
51
- "includeDevDependenciesInPackageJson": {
52
- "type": "boolean",
53
- "description": "Include `devDependencies` in the generated package.json file. By default only production `dependencies` are included.",
54
- "default": false
55
- },
56
- "generateLockfile": {
57
- "type": "boolean",
58
- "description": "Generate a lockfile (e.g. package-lock.json) that matches the workspace lockfile to ensure package versions match.",
59
- "default": false,
60
- "x-priority": "internal"
61
- },
62
- "skipOverrides": {
63
- "type": "boolean",
64
- "description": "Do not add a `overrides` and `resolutions` entries to the generated package.json file. Only works in conjunction with `generatePackageJson` option."
65
- },
66
- "skipPackageManager": {
67
- "type": "boolean",
68
- "description": "Do not add a `packageManager` entry to the generated package.json file."
69
- },
70
- "debug": {
71
- "type": "boolean",
72
- "description": "Enable Next.js debug build logging"
73
- },
74
- "profile": {
75
- "type": "boolean",
76
- "description": "Used to enable React Production Profiling"
77
- },
78
- "experimentalAppOnly": {
79
- "type": "boolean",
80
- "description": "Only build 'app' routes"
81
- },
82
- "experimentalBuildMode": {
83
- "type": "string",
84
- "description": "Change the build mode.",
85
- "enum": ["compile", "generate"]
86
- },
87
- "turbo": {
88
- "type": "boolean",
89
- "description": "Use Turbopack for building (Next.js 15 and below). In Next.js 16+, Turbopack is enabled by default."
90
- },
91
- "webpack": {
92
- "type": "boolean",
93
- "description": "Use webpack bundler instead of Turbopack (Next.js 16+ only). This flag is only applicable in Next.js 16 and above where Turbopack is the default."
94
- }
95
- },
96
- "required": ["outputPath"],
97
- "examplesFile": "../../../docs/build-next-executor-examples.md"
98
- }
@@ -1,6 +0,0 @@
1
- import { ExecutorContext } from '@nx/devkit';
2
- import { NextServeBuilderOptions } from '../../utils/types';
3
- export default function serveExecutor(options: NextServeBuilderOptions, context: ExecutorContext): AsyncGenerator<{
4
- success: boolean;
5
- baseUrl: string;
6
- }, void, unknown>;
@@ -1,37 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.default = serveExecutor;
4
- const devkit_1 = require("@nx/devkit");
5
- const path_1 = require("path");
6
- async function* serveExecutor(options, context) {
7
- // Cast to any to overwrite NODE_ENV
8
- process.env.NODE_ENV = process.env.NODE_ENV
9
- ? process.env.NODE_ENV
10
- : options.dev
11
- ? 'development'
12
- : 'production';
13
- // Setting port that the custom server should use.
14
- process.env.PORT = options.port ? `${options.port}` : process.env.PORT;
15
- options.port = parseInt(process.env.PORT);
16
- const projectRoot = context.projectGraph.nodes[context.projectName].data.root;
17
- yield* runCustomServer(projectRoot, options, context);
18
- }
19
- async function* runCustomServer(root, options, context) {
20
- process.env.NX_NEXT_DIR ??= root;
21
- process.env.NX_NEXT_PUBLIC_DIR = (0, path_1.join)(root, 'public');
22
- const httpProtocol = options.customServerHttps ? 'https' : 'http';
23
- const baseUrl = `${httpProtocol}://${options.hostname || 'localhost'}:${options.port}`;
24
- const customServerBuild = await (0, devkit_1.runExecutor)((0, devkit_1.parseTargetString)(options.customServerTarget, context), {
25
- watch: options.dev ? true : false,
26
- }, context);
27
- for await (const result of customServerBuild) {
28
- if (!result.success) {
29
- return result;
30
- }
31
- yield {
32
- success: true,
33
- baseUrl,
34
- };
35
- }
36
- return { success: true };
37
- }