Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(nextjs): Add standalone Nextjs option to react selection when running CNW #16317

Merged
merged 1 commit into from
Apr 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion docs/generated/cli/create-nx-workspace.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,12 @@ Type: `string`

Workspace name (e.g. org name)

### nextAppDir

Type: `boolean`

Add Experimental app/ layout for next.js

### nxCloud

Type: `boolean`
Expand All @@ -129,7 +135,7 @@ Package manager to use

Type: `string`

Customizes the initial content of your workspace. Default presets include: ["apps", "empty", "core", "npm", "ts", "web-components", "angular-monorepo", "angular-standalone", "react-monorepo", "react-standalone", "react-native", "expo", "next", "nest", "express", "react", "angular", "node-standalone"]. To build your own see https://nx.dev/packages/nx-plugin#preset
Customizes the initial content of your workspace. Default presets include: ["apps", "empty", "core", "npm", "ts", "web-components", "angular-monorepo", "angular-standalone", "react-monorepo", "react-standalone", "nextjs-standalone", "react-native", "expo", "next", "nest", "express", "react", "angular", "node-standalone"]. To build your own see https://nx.dev/packages/nx-plugin#preset

### routing

Expand Down
7 changes: 7 additions & 0 deletions docs/generated/packages/next/generators/application.json
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,13 @@
"default": false,
"description": "Enable experimental app directory for the project",
"x-prompt": "Do you want to use experimental app/ in this project?"
},
"rootProject": {
"description": "Create an application at the root of the workspace.",
"type": "boolean",
"default": false,
"hidden": true,
"x-priority": "internal"
}
},
"required": [],
Expand Down
7 changes: 7 additions & 0 deletions docs/generated/packages/next/generators/init.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@
"default": false,
"description": "Do not add dependencies to `package.json`.",
"x-priority": "internal"
},
"rootProject": {
"description": "Create an application at the root of the workspace.",
"type": "boolean",
"default": false,
"hidden": true,
"x-priority": "internal"
}
},
"required": [],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,12 @@ Type: `string`

Workspace name (e.g. org name)

### nextAppDir

Type: `boolean`

Add Experimental app/ layout for next.js

### nxCloud

Type: `boolean`
Expand All @@ -129,7 +135,7 @@ Package manager to use

Type: `string`

Customizes the initial content of your workspace. Default presets include: ["apps", "empty", "core", "npm", "ts", "web-components", "angular-monorepo", "angular-standalone", "react-monorepo", "react-standalone", "react-native", "expo", "next", "nest", "express", "react", "angular", "node-standalone"]. To build your own see https://nx.dev/packages/nx-plugin#preset
Customizes the initial content of your workspace. Default presets include: ["apps", "empty", "core", "npm", "ts", "web-components", "angular-monorepo", "angular-standalone", "react-monorepo", "react-standalone", "nextjs-standalone", "react-native", "expo", "next", "nest", "express", "react", "angular", "node-standalone"]. To build your own see https://nx.dev/packages/nx-plugin#preset

### routing

Expand Down
5 changes: 5 additions & 0 deletions docs/generated/packages/workspace/generators/new.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,11 @@
"description": "The framework which the application is using",
"type": "string",
"enum": ["express", "koa", "fastify", "nest", "none"]
},
"nextAppDir": {
"description": "Enable experimental app directory for the project",
"type": "boolean",
"default": false
}
},
"additionalProperties": true,
Expand Down
5 changes: 5 additions & 0 deletions docs/generated/packages/workspace/generators/preset.json
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,11 @@
"description": "Generate a Dockerfile",
"type": "boolean",
"default": false
},
"nextAppDir": {
"description": "Enable experimental app/ for the project",
"type": "boolean",
"default": false
}
},
"presets": []
Expand Down
22 changes: 21 additions & 1 deletion e2e/next/src/next.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import {
} from '@nrwl/e2e/utils';
import * as http from 'http';
import { checkApp } from './utils';
import { removeSync } from 'fs-extra';

describe('Next.js Applications', () => {
let proj: string;
Expand Down Expand Up @@ -426,6 +425,27 @@ describe('Next.js Applications', () => {
checkExport: false,
});
}, 300_000);

it('should create a generate a next.js app with app layout enabled', async () => {
const appName = uniq('app');

runCLI(
`generate @nrwl/next:app ${appName} --style=css --appDir --no-interactive`
);

checkFilesExist(`apps/${appName}/app/api/hello/route.ts`);
checkFilesExist(`apps/${appName}/app/page.tsx`);
checkFilesExist(`apps/${appName}/app/layout.tsx`);
checkFilesExist(`apps/${appName}/app/global.css`);
checkFilesExist(`apps/${appName}/app/page.module.css`);

await checkApp(appName, {
checkUnitTest: false,
checkLint: false,
checkE2E: false,
checkExport: false,
});
}, 300_000);
});

function getData(port, path = ''): Promise<any> {
Expand Down
93 changes: 83 additions & 10 deletions packages/create-nx-workspace/bin/create-nx-workspace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ interface Arguments extends CreateWorkspaceOptions {
framework: Framework;
standaloneApi: boolean;
docker: boolean;
nextAppDir: boolean;
routing: boolean;
bundler: Bundler;
}
Expand Down Expand Up @@ -104,6 +105,10 @@ export const commandsObject: yargs.Argv<Arguments> = yargs
.option('docker', {
describe: chalk.dim`Generate a Dockerfile with your node-server`,
type: 'boolean',
})
.option('nextAppDir', {
describe: chalk.dim`Add Experimental app/ layout for next.js`,
type: 'boolean',
}),
withNxCloud,
withCI,
Expand Down Expand Up @@ -180,6 +185,7 @@ async function normalizeArgsMiddleware(
framework,
bundler,
docker,
nextAppDir,
routing,
standaloneApi;

Expand Down Expand Up @@ -209,7 +215,7 @@ async function normalizeArgsMiddleware(
if (monorepoStyle === 'package-based') {
preset = 'npm';
} else if (monorepoStyle === 'react') {
preset = Preset.ReactStandalone;
preset = await determineReactFramework(argv);
} else if (monorepoStyle === 'angular') {
preset = Preset.AngularStandalone;
} else if (monorepoStyle === 'node-standalone') {
Expand All @@ -228,7 +234,8 @@ async function normalizeArgsMiddleware(
if (
preset === Preset.ReactStandalone ||
preset === Preset.AngularStandalone ||
preset === Preset.NodeStandalone
preset === Preset.NodeStandalone ||
preset === Preset.NextJsStandalone
) {
appName =
argv.appName ?? argv.name ?? (await determineAppName(preset, argv));
Expand All @@ -241,6 +248,10 @@ async function normalizeArgsMiddleware(
}
}

if (preset === Preset.NextJsStandalone) {
nextAppDir = await isNextAppDir(argv);
}

if (preset === Preset.ReactStandalone) {
bundler = await determineBundler(argv);
}
Expand Down Expand Up @@ -291,6 +302,7 @@ async function normalizeArgsMiddleware(
ci,
bundler,
docker,
nextAppDir,
});
} catch (e) {
console.error(e);
Expand Down Expand Up @@ -363,27 +375,27 @@ async function determineMonorepoStyle(): Promise<string> {
{
name: 'package-based',
message:
'Package-based monorepo: Nx makes it fast, but lets you run things your way.',
'Package-based monorepo: Nx makes it fast, but lets you run things your way.',
},
{
name: 'integrated',
message:
'Integrated monorepo: Nx configures your favorite frameworks and lets you focus on shipping features.',
'Integrated monorepo: Nx configures your favorite frameworks and lets you focus on shipping features.',
},
{
name: 'react',
message:
'Standalone React app: Nx configures Vite (or Webpack), ESLint, and Cypress.',
'Standalone React app: Nx configures a React app with an optional framework (e.g. Next.js).',
},
{
name: 'angular',
message:
'Standalone Angular app: Nx configures Jest, ESLint and Cypress.',
'Standalone Angular app: Nx configures Jest, ESLint and Cypress.',
},
{
name: 'node-standalone',
message:
'Standalone Node app: Nx configures a framework (ex. Express), esbuild, ESlint and Jest.',
'Standalone Node app: Nx configures a framework (e.g. Express), esbuild, ESlint and Jest.',
},
],
},
Expand Down Expand Up @@ -582,6 +594,64 @@ async function determineDockerfile(
}
}

async function determineReactFramework(parsedArgs: yargs.Arguments<Arguments>) {
if (parsedArgs.framework) {
return parsedArgs.framework === 'next.js'
? Preset.NextJsStandalone
: Preset.ReactStandalone;
}
return enquirer
.prompt<{ framework: 'none' | 'next.js' }>([
{
name: 'framework',
message: 'What framework would you like to use?',
type: 'autocomplete',
choices: [
{
name: 'none',
message: 'None',
hint: 'I only want React',
},
{
name: 'next.js',
message: 'Next.js [https://nextjs.org/]',
},
],
initial: 'none' as any,
},
])
.then((choice) =>
choice.framework === 'next.js'
? Preset.NextJsStandalone
: Preset.ReactStandalone
);
}

async function isNextAppDir(parsedArgs: yargs.Arguments<Arguments>) {
if (parsedArgs.nextAppDir === undefined) {
return enquirer
.prompt<{ appDir: 'Yes' | 'No' }>([
{
name: 'appDir',
message: 'Do you want to use experimental app/ in this project?',
type: 'autocomplete',
choices: [
{
name: 'No',
},
{
name: 'Yes',
},
],
initial: 'No' as any,
},
])
.then((choice) => choice.appDir === 'Yes');
} else {
return Promise.resolve(parsedArgs.nextAppDir);
}
}

async function determineStyle(
preset: Preset,
parsedArgs: yargs.Arguments<Arguments>
Expand Down Expand Up @@ -617,9 +687,12 @@ async function determineStyle(
];

if (
[Preset.ReactMonorepo, Preset.ReactStandalone, Preset.NextJs].includes(
preset
)
[
Preset.ReactMonorepo,
Preset.ReactStandalone,
Preset.NextJs,
Preset.NextJsStandalone,
].includes(preset)
) {
choices.push(
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export function pointToTutorialAndCourse(preset: Preset) {
break;
case Preset.ReactMonorepo:
case Preset.NextJs:
case Preset.NextJsStandalone:
output.addVerticalSeparator();
output.note({
title,
Expand Down
1 change: 1 addition & 0 deletions packages/create-nx-workspace/src/utils/preset/preset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export enum Preset {
AngularStandalone = 'angular-standalone',
ReactMonorepo = 'react-monorepo',
ReactStandalone = 'react-standalone',
NextJsStandalone = 'nextjs-standalone',
ReactNative = 'react-native',
Expo = 'expo',
NextJs = 'next',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
const StyledPage = styled.div`<%- pageStyleContent %>`;
<% }%>

export async function Index() {
export default async function Index() {
/*
* Replace the elements below with your own.
*
Expand All @@ -23,6 +23,4 @@ export async function Index() {
<%- appContent %>
</<%= wrapper %>>
);
};

export default Index;
};
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
"noEmit": true,
"resolveJsonModule": true,
"isolatedModules": true,
"incremental": true
"incremental": true,
"plugins": [{ "name": "next" }]
},
"include": ["**/*.ts", "**/*.tsx", "**/*.js", "**/*.jsx", "next-env.d.ts"],
"exclude": ["node_modules", "jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export async function addCypress(host: Tree, options: NormalizedSchema) {
return cypressProjectGenerator(host, {
...options,
linter: Linter.EsLint,
name: `${options.name}-e2e`,
name: options.e2eProjectName,
directory: options.directory,
project: options.projectName,
skipFormat: true,
Expand Down
Loading