@nx/next 18.1.0-beta.0 → 18.1.0-beta.10
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.
- package/package.json +9 -9
- package/plugins/with-nx.js +18 -13
- package/src/executors/build/build.impl.js +20 -9
- package/src/executors/server/server.impl.js +1 -1
- package/src/generators/application/files/app/page.tsx__tmpl__ +1 -1
- package/src/generators/application/files/common/specs/__fileName__.spec.tsx__tmpl__ +9 -4
- package/src/generators/application/lib/add-e2e.js +16 -0
- package/src/generators/application/lib/create-application-files.helpers.js +1 -1
- package/src/generators/application/lib/create-application-files.js +3 -2
- package/src/generators/application/lib/normalize-options.js +4 -1
- package/src/generators/cypress-component-configuration/cypress-component-configuration.js +1 -0
- package/src/generators/init/init.js +4 -1
- package/src/generators/init/lib/add-plugin.js +1 -0
- package/src/generators/library/lib/normalize-options.js +5 -1
- package/src/plugins/plugin.d.ts +1 -0
- package/src/plugins/plugin.js +13 -0
- package/src/utils/add-gitignore-entry.js +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nx/next",
|
|
3
|
-
"version": "18.1.0-beta.
|
|
3
|
+
"version": "18.1.0-beta.10",
|
|
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": {
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"next": ">=14.0.0"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@nx/devkit": "18.1.0-beta.
|
|
37
|
+
"@nx/devkit": "18.1.0-beta.10",
|
|
38
38
|
"@babel/plugin-proposal-decorators": "^7.22.7",
|
|
39
39
|
"@svgr/webpack": "^8.0.1",
|
|
40
40
|
"chalk": "^4.1.0",
|
|
@@ -45,13 +45,13 @@
|
|
|
45
45
|
"url-loader": "^4.1.1",
|
|
46
46
|
"tslib": "^2.3.0",
|
|
47
47
|
"webpack-merge": "^5.8.0",
|
|
48
|
-
"@nx/js": "18.1.0-beta.
|
|
49
|
-
"@nx/eslint": "18.1.0-beta.
|
|
50
|
-
"@nx/react": "18.1.0-beta.
|
|
51
|
-
"@nx/web": "18.1.0-beta.
|
|
52
|
-
"@nx/webpack": "18.1.0-beta.
|
|
53
|
-
"@nx/workspace": "18.1.0-beta.
|
|
54
|
-
"@nrwl/next": "18.1.0-beta.
|
|
48
|
+
"@nx/js": "18.1.0-beta.10",
|
|
49
|
+
"@nx/eslint": "18.1.0-beta.10",
|
|
50
|
+
"@nx/react": "18.1.0-beta.10",
|
|
51
|
+
"@nx/web": "18.1.0-beta.10",
|
|
52
|
+
"@nx/webpack": "18.1.0-beta.10",
|
|
53
|
+
"@nx/workspace": "18.1.0-beta.10",
|
|
54
|
+
"@nrwl/next": "18.1.0-beta.10"
|
|
55
55
|
},
|
|
56
56
|
"publishConfig": {
|
|
57
57
|
"access": "public"
|
package/plugins/with-nx.js
CHANGED
|
@@ -59,10 +59,12 @@ function getNxContext(graph, target) {
|
|
|
59
59
|
function withNx(_nextConfig = {}, context = getWithNxContext()) {
|
|
60
60
|
return async (phase) => {
|
|
61
61
|
const { PHASE_PRODUCTION_SERVER, PHASE_DEVELOPMENT_SERVER } = await Promise.resolve().then(() => require('next/constants'));
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
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) {
|
|
66
68
|
const { nx, ...validNextConfig } = _nextConfig;
|
|
67
69
|
return {
|
|
68
70
|
distDir: '.next',
|
|
@@ -70,15 +72,13 @@ function withNx(_nextConfig = {}, context = getWithNxContext()) {
|
|
|
70
72
|
};
|
|
71
73
|
}
|
|
72
74
|
else {
|
|
73
|
-
const { createProjectGraphAsync,
|
|
74
|
-
let graph
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
throw new Error('Could not create project graph. Please ensure that your workspace is valid.');
|
|
81
|
-
}
|
|
75
|
+
const { createProjectGraphAsync, joinPathFragments, offsetFromRoot, workspaceRoot, } = require('@nx/devkit');
|
|
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
82
|
}
|
|
83
83
|
const originalTarget = {
|
|
84
84
|
project: process.env.NX_TASK_TARGET_PROJECT,
|
|
@@ -119,6 +119,11 @@ function withNx(_nextConfig = {}, context = getWithNxContext()) {
|
|
|
119
119
|
? joinPathFragments(outputDir, nextConfig.distDir)
|
|
120
120
|
: joinPathFragments(outputDir, '.next');
|
|
121
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
|
+
}
|
|
122
127
|
const userWebpackConfig = nextConfig.webpack;
|
|
123
128
|
const { createWebpackConfig } = require('@nx/next/src/utils/config');
|
|
124
129
|
nextConfig.webpack = (a, b) => createWebpackConfig(workspaceRoot, projectDirectory, options.fileReplacements, options.assets)(userWebpackConfig ? userWebpackConfig(a, b) : a, b);
|
|
@@ -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
|
-
|
|
39
|
-
|
|
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', () =>
|
|
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
|
});
|
|
@@ -11,7 +11,7 @@ async function* serveExecutor(options, context) {
|
|
|
11
11
|
const buildOptions = (0, devkit_1.readTargetOptions)((0, devkit_1.parseTargetString)(options.buildTarget, context), context);
|
|
12
12
|
const projectRoot = context.workspace.projects[context.projectName].root;
|
|
13
13
|
// This is required for the default custom server to work. See the @nx/next:app generator.
|
|
14
|
-
const nextDir = (0, path_1.resolve)(context.root, buildOptions.outputPath);
|
|
14
|
+
const nextDir = !options.dev && (0, path_1.resolve)(context.root, buildOptions.outputPath);
|
|
15
15
|
process.env.NX_NEXT_DIR ??= options.dev ? projectRoot : nextDir;
|
|
16
16
|
if (options.customServerTarget) {
|
|
17
17
|
return yield* (0, custom_server_impl_1.default)(options, context);
|
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { render } from '@testing-library/react';
|
|
3
|
-
<% if (src) { %>
|
|
3
|
+
<% if (src && !appDir) { %>
|
|
4
4
|
import Index from '../src/pages/index';
|
|
5
|
-
<% } else { %>
|
|
5
|
+
<% } else if (!appDir) { %>
|
|
6
6
|
import Index from '../pages/index';
|
|
7
|
+
<% } else if (appDir && src) {%>
|
|
8
|
+
import Page from '../src/app/page';
|
|
9
|
+
<% } else { %>
|
|
10
|
+
import Page from '../app/page';
|
|
7
11
|
<% } %>
|
|
8
|
-
|
|
12
|
+
|
|
13
|
+
describe(<%- appDir ? `'Page'` : `'Index'` %>, () => {
|
|
9
14
|
it('should render successfully', () => {
|
|
10
|
-
const { baseElement } = render(
|
|
15
|
+
const { baseElement } = render(<%- appDir ? `<Page />` : `<Index />` %>);
|
|
11
16
|
expect(baseElement).toBeTruthy();
|
|
12
17
|
});
|
|
13
18
|
});
|
|
@@ -4,6 +4,7 @@ exports.addE2e = void 0;
|
|
|
4
4
|
const devkit_1 = require("@nx/devkit");
|
|
5
5
|
const eslint_1 = require("@nx/eslint");
|
|
6
6
|
const versions_1 = require("../../../utils/versions");
|
|
7
|
+
const web_1 = require("@nx/web");
|
|
7
8
|
async function addE2e(host, options) {
|
|
8
9
|
const nxJson = (0, devkit_1.readNxJson)(host);
|
|
9
10
|
const hasPlugin = nxJson.plugins?.some((p) => typeof p === 'string'
|
|
@@ -11,6 +12,13 @@ async function addE2e(host, options) {
|
|
|
11
12
|
: p.plugin === '@nx/next/plugin');
|
|
12
13
|
if (options.e2eTestRunner === 'cypress') {
|
|
13
14
|
const { configurationGenerator } = (0, devkit_1.ensurePackage)('@nx/cypress', versions_1.nxVersion);
|
|
15
|
+
if (!hasPlugin) {
|
|
16
|
+
(0, web_1.webStaticServeGenerator)(host, {
|
|
17
|
+
buildTarget: `${options.projectName}:build`,
|
|
18
|
+
outputPath: `${options.outputPath}/out`,
|
|
19
|
+
targetName: 'serve-static',
|
|
20
|
+
});
|
|
21
|
+
}
|
|
14
22
|
(0, devkit_1.addProjectConfiguration)(host, options.e2eProjectName, {
|
|
15
23
|
root: options.e2eProjectRoot,
|
|
16
24
|
sourceRoot: (0, devkit_1.joinPathFragments)(options.e2eProjectRoot, 'src'),
|
|
@@ -27,6 +35,14 @@ async function addE2e(host, options) {
|
|
|
27
35
|
devServerTarget: `${options.projectName}:${hasPlugin ? 'start' : 'serve'}`,
|
|
28
36
|
baseUrl: `http://localhost:${hasPlugin ? '3000' : '4200'}`,
|
|
29
37
|
jsx: true,
|
|
38
|
+
webServerCommands: hasPlugin
|
|
39
|
+
? {
|
|
40
|
+
default: `nx run ${options.projectName}:start`,
|
|
41
|
+
}
|
|
42
|
+
: undefined,
|
|
43
|
+
ciWebServerCommand: hasPlugin
|
|
44
|
+
? `nx run ${options.projectName}:serve-static`
|
|
45
|
+
: undefined,
|
|
30
46
|
});
|
|
31
47
|
}
|
|
32
48
|
else if (options.e2eTestRunner === 'playwright') {
|
|
@@ -304,7 +304,7 @@ function createAppJsx(name) {
|
|
|
304
304
|
You can activate distributed tasks executions and caching by
|
|
305
305
|
running:
|
|
306
306
|
</p>
|
|
307
|
-
<pre>nx connect
|
|
307
|
+
<pre>nx connect</pre>
|
|
308
308
|
<a
|
|
309
309
|
href="https://nx.app/?utm_source=nx-project"
|
|
310
310
|
target="_blank"
|
|
@@ -38,8 +38,9 @@ function createApplicationFiles(host, options) {
|
|
|
38
38
|
(0, devkit_1.generateFiles)(host, (0, path_1.join)(__dirname, '../files/common'), options.appProjectRoot, templateVariables);
|
|
39
39
|
if (options.appDir) {
|
|
40
40
|
(0, devkit_1.generateFiles)(host, (0, path_1.join)(__dirname, '../files/app'), (0, path_1.join)(generatedAppFilePath, 'app'), templateVariables);
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
if (options.unitTestRunner === 'none') {
|
|
42
|
+
host.delete((0, devkit_1.joinPathFragments)(options.appProjectRoot, 'specs', `index.spec.${options.js ? 'jsx' : 'tsx'}`));
|
|
43
|
+
}
|
|
43
44
|
if (options.style === 'styled-components') {
|
|
44
45
|
(0, devkit_1.generateFiles)(host, (0, path_1.join)(__dirname, '../files/app-styled-components'), (0, path_1.join)(generatedAppFilePath, 'app'), templateVariables);
|
|
45
46
|
}
|
|
@@ -16,7 +16,10 @@ async function normalizeOptions(host, options) {
|
|
|
16
16
|
});
|
|
17
17
|
options.rootProject = appProjectRoot === '.';
|
|
18
18
|
options.projectNameAndRootFormat = projectNameAndRootFormat;
|
|
19
|
-
|
|
19
|
+
const nxJson = (0, devkit_1.readNxJson)(host);
|
|
20
|
+
const addPlugin = process.env.NX_ADD_PLUGINS !== 'false' &&
|
|
21
|
+
nxJson.useInferencePlugins !== false;
|
|
22
|
+
options.addPlugin ??= addPlugin;
|
|
20
23
|
const e2eProjectName = options.rootProject ? 'e2e' : `${appProjectName}-e2e`;
|
|
21
24
|
const e2eProjectRoot = options.rootProject ? 'e2e' : `${appProjectRoot}-e2e`;
|
|
22
25
|
const name = (0, devkit_1.names)(options.name).fileName;
|
|
@@ -24,7 +24,10 @@ function nextInitGenerator(tree, schema) {
|
|
|
24
24
|
}
|
|
25
25
|
exports.nextInitGenerator = nextInitGenerator;
|
|
26
26
|
async function nextInitGeneratorInternal(host, schema) {
|
|
27
|
-
|
|
27
|
+
const nxJson = (0, devkit_1.readNxJson)(host);
|
|
28
|
+
const addPluginDefault = process.env.NX_ADD_PLUGINS !== 'false' &&
|
|
29
|
+
nxJson.useInferencePlugins !== false;
|
|
30
|
+
schema.addPlugin ??= addPluginDefault;
|
|
28
31
|
if (schema.addPlugin) {
|
|
29
32
|
(0, add_plugin_1.addPlugin)(host);
|
|
30
33
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.normalizeOptions = void 0;
|
|
4
|
+
const devkit_1 = require("@nx/devkit");
|
|
4
5
|
const project_name_and_root_utils_1 = require("@nx/devkit/src/generators/project-name-and-root-utils");
|
|
5
6
|
async function normalizeOptions(host, options) {
|
|
6
7
|
const { projectRoot, importPath, projectNameAndRootFormat } = await (0, project_name_and_root_utils_1.determineProjectNameAndRootOptions)(host, {
|
|
@@ -12,7 +13,10 @@ async function normalizeOptions(host, options) {
|
|
|
12
13
|
callingGenerator: '@nx/next:library',
|
|
13
14
|
});
|
|
14
15
|
options.projectNameAndRootFormat = projectNameAndRootFormat;
|
|
15
|
-
|
|
16
|
+
const nxJson = (0, devkit_1.readNxJson)(host);
|
|
17
|
+
const addPlugin = process.env.NX_ADD_PLUGINS !== 'false' &&
|
|
18
|
+
nxJson.useInferencePlugins !== false;
|
|
19
|
+
options.addPlugin ??= addPlugin;
|
|
16
20
|
return {
|
|
17
21
|
...options,
|
|
18
22
|
importPath,
|
package/src/plugins/plugin.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ export interface NextPluginOptions {
|
|
|
4
4
|
buildTargetName?: string;
|
|
5
5
|
devTargetName?: string;
|
|
6
6
|
startTargetName?: string;
|
|
7
|
+
serveStaticTargetName?: string;
|
|
7
8
|
}
|
|
8
9
|
export declare const createDependencies: CreateDependencies;
|
|
9
10
|
export declare const createNodes: CreateNodes<NextPluginOptions>;
|
package/src/plugins/plugin.js
CHANGED
|
@@ -56,6 +56,7 @@ async function buildNextTargets(nextConfigPath, projectRoot, options, context) {
|
|
|
56
56
|
targets[options.buildTargetName] = await getBuildTargetConfig(namedInputs, projectRoot, nextConfig);
|
|
57
57
|
targets[options.devTargetName] = getDevTargetConfig(projectRoot);
|
|
58
58
|
targets[options.startTargetName] = getStartTargetConfig(options, projectRoot);
|
|
59
|
+
targets[options.serveStaticTargetName] = getStaticServeTargetConfig(options);
|
|
59
60
|
return targets;
|
|
60
61
|
}
|
|
61
62
|
async function getBuildTargetConfig(namedInputs, projectRoot, nextConfig) {
|
|
@@ -92,6 +93,17 @@ function getStartTargetConfig(options, projectRoot) {
|
|
|
92
93
|
};
|
|
93
94
|
return targetConfig;
|
|
94
95
|
}
|
|
96
|
+
function getStaticServeTargetConfig(options) {
|
|
97
|
+
const targetConfig = {
|
|
98
|
+
executor: '@nx/web:file-server',
|
|
99
|
+
options: {
|
|
100
|
+
buildTarget: options.buildTargetName,
|
|
101
|
+
staticFilePath: '{projectRoot}/out',
|
|
102
|
+
port: 3000,
|
|
103
|
+
},
|
|
104
|
+
};
|
|
105
|
+
return targetConfig;
|
|
106
|
+
}
|
|
95
107
|
async function getOutputs(projectRoot, nextConfig) {
|
|
96
108
|
let dir = '.next';
|
|
97
109
|
const { PHASE_PRODUCTION_BUILD } = require('next/constants');
|
|
@@ -129,6 +141,7 @@ function normalizeOptions(options) {
|
|
|
129
141
|
options.buildTargetName ??= 'build';
|
|
130
142
|
options.devTargetName ??= 'dev';
|
|
131
143
|
options.startTargetName ??= 'start';
|
|
144
|
+
options.serveStaticTargetName ??= 'serve-static';
|
|
132
145
|
return options;
|
|
133
146
|
}
|
|
134
147
|
function getInputs(namedInputs) {
|
|
@@ -10,7 +10,7 @@ function addGitIgnoreEntry(host) {
|
|
|
10
10
|
const ig = (0, ignore_1.default)();
|
|
11
11
|
ig.add(host.read('.gitignore', 'utf-8'));
|
|
12
12
|
if (!ig.ignores('apps/example/.next')) {
|
|
13
|
-
content = `${content}\n\n# Next.js\n.next\n`;
|
|
13
|
+
content = `${content}\n\n# Next.js\n.next\nout\n`;
|
|
14
14
|
}
|
|
15
15
|
host.write('.gitignore', content);
|
|
16
16
|
}
|