diff --git a/docs/generated/packages/next/generators/application.json b/docs/generated/packages/next/generators/application.json index da58d772463b2..5ad1db11b4e52 100644 --- a/docs/generated/packages/next/generators/application.json +++ b/docs/generated/packages/next/generators/application.json @@ -124,6 +124,12 @@ "default": false, "description": "Do not add dependencies to `package.json`.", "x-priority": "internal" + }, + "appDir": { + "type": "boolean", + "default": false, + "description": "Enable experimental app directory for the project", + "x-prompt": "Do you want to use experimental app/ in this project?" } }, "required": [], diff --git a/packages/next/src/generators/application/application.spec.ts b/packages/next/src/generators/application/application.spec.ts index 12a2885d1b46f..dad0f6e8cd13e 100644 --- a/packages/next/src/generators/application/application.spec.ts +++ b/packages/next/src/generators/application/application.spec.ts @@ -1,7 +1,6 @@ import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing'; import { getProjects, - NxJsonConfiguration, readJson, readProjectConfiguration, Tree, @@ -418,4 +417,23 @@ describe('app', () => { expect(tree.exists('apps/my-app/public/.gitkeep')).toBe(true); }); + + describe('--appDir', () => { + it('should generate app directory instead of pages', async () => { + await applicationGenerator(tree, { + name: 'testApp', + style: 'css', + appDir: true, + }); + + expect(tree.exists('apps/testApp/pages/styles.css')).toBeFalsy(); + + expect(tree.exists('apps/testApp/app/global.css')); + expect(tree.exists('apps/testApp/app/page.tsx')); + expect(tree.exists('apps/testApp/app/layout.tsx')); + expect(tree.exists('apps/testApp/app/api/hello/route.ts')); + expect(tree.exists('apps/testApp/app/page.module.css')); + expect(tree.exists('apps/testApp/app/favicon.ico')); + }); + }); }); diff --git a/packages/next/src/generators/application/files/app/api/hello/route.ts__tmpl__ b/packages/next/src/generators/application/files/app/api/hello/route.ts__tmpl__ new file mode 100644 index 0000000000000..e5655e266b078 --- /dev/null +++ b/packages/next/src/generators/application/files/app/api/hello/route.ts__tmpl__ @@ -0,0 +1,4 @@ +export async function GET(request: Request) { + return new Response('Hello, from API!') + } + \ No newline at end of file diff --git a/packages/next/src/generators/application/files/app/favicon.ico b/packages/next/src/generators/application/files/app/favicon.ico new file mode 100644 index 0000000000000..317ebcb2336e0 Binary files /dev/null and b/packages/next/src/generators/application/files/app/favicon.ico differ diff --git a/packages/next/src/generators/application/files/app/global.__stylesExt____tmpl__ b/packages/next/src/generators/application/files/app/global.__stylesExt____tmpl__ new file mode 100644 index 0000000000000..c3f24863cb434 --- /dev/null +++ b/packages/next/src/generators/application/files/app/global.__stylesExt____tmpl__ @@ -0,0 +1 @@ +<%- styleContent %> diff --git a/packages/next/src/generators/application/files/app/layout.tsx__tmpl__ b/packages/next/src/generators/application/files/app/layout.tsx__tmpl__ new file mode 100644 index 0000000000000..498a427d892ab --- /dev/null +++ b/packages/next/src/generators/application/files/app/layout.tsx__tmpl__ @@ -0,0 +1,22 @@ +import Head from 'next/head'; +import './global.<%= stylesExt %>'; + +export const metadata = { + title: 'Nx Next App', + description: 'Generated by create-nx-workspace', +} + +export default function RootLayout({ + children, +}: { + children: React.ReactNode +}) { + return ( + + + Welcome to <%= name %>! + + {children} + + ) +} diff --git a/packages/next/src/generators/application/files/app/page.module.__style__ b/packages/next/src/generators/application/files/app/page.module.__style__ new file mode 100644 index 0000000000000..40d88f3d797b7 --- /dev/null +++ b/packages/next/src/generators/application/files/app/page.module.__style__ @@ -0,0 +1 @@ +<%- pageStyleContent %> diff --git a/packages/next/src/generators/application/files/app/page.tsx__tmpl__ b/packages/next/src/generators/application/files/app/page.tsx__tmpl__ new file mode 100644 index 0000000000000..4d4e80e033070 --- /dev/null +++ b/packages/next/src/generators/application/files/app/page.tsx__tmpl__ @@ -0,0 +1,28 @@ +<% if (styledModule && styledModule !== 'styled-jsx') { + var wrapper = 'StyledPage'; +%>import styled from '<%= styledModule %>';<% } else { + var wrapper = 'div'; +%> + <%- style !== 'styled-jsx' ? `import styles from './page.module.${style}';` : '' %> +<% } +%> + +<% if (styledModule && styledModule !== 'styled-jsx') { %> +const StyledPage = styled.div`<%- pageStyleContent %>`; +<% }%> + +export async function Index() { + /* + * Replace the elements below with your own. + * + * Note: The corresponding styles are in the ./<%= fileName %>.<%= style %> file. + */ + return ( + <<%= wrapper %><% if (!styledModule) {%> className={styles.page}<% } %>> + <%- styledModule === 'styled-jsx' ? `` : `` %> + <%- appContent %> + > + ); +}; + +export default Index; \ No newline at end of file diff --git a/packages/next/src/generators/application/files/.babelrc__tmpl__ b/packages/next/src/generators/application/files/common/.babelrc__tmpl__ similarity index 100% rename from packages/next/src/generators/application/files/.babelrc__tmpl__ rename to packages/next/src/generators/application/files/common/.babelrc__tmpl__ diff --git a/packages/next/src/generators/application/files/index.d.ts__tmpl__ b/packages/next/src/generators/application/files/common/index.d.ts__tmpl__ similarity index 100% rename from packages/next/src/generators/application/files/index.d.ts__tmpl__ rename to packages/next/src/generators/application/files/common/index.d.ts__tmpl__ diff --git a/packages/next/src/generators/application/files/next-env.d.ts__tmpl__ b/packages/next/src/generators/application/files/common/next-env.d.ts__tmpl__ similarity index 100% rename from packages/next/src/generators/application/files/next-env.d.ts__tmpl__ rename to packages/next/src/generators/application/files/common/next-env.d.ts__tmpl__ diff --git a/packages/next/src/generators/application/files/next.config.js__tmpl__ b/packages/next/src/generators/application/files/common/next.config.js__tmpl__ similarity index 85% rename from packages/next/src/generators/application/files/next.config.js__tmpl__ rename to packages/next/src/generators/application/files/common/next.config.js__tmpl__ index 8cef6587befb4..69c955d9d1223 100644 --- a/packages/next/src/generators/application/files/next.config.js__tmpl__ +++ b/packages/next/src/generators/application/files/common/next.config.js__tmpl__ @@ -17,6 +17,11 @@ const nextConfig = { // See: https://github.com/gregberge/svgr svgr: false, }, + <% if(appDir) { %> + experimental: { + appDir: true + }, + <% } %> }; module.exports = withLess(withNx(nextConfig)); @@ -32,6 +37,11 @@ const nextConfig = { // See: https://github.com/gregberge/svgr svgr: false, }, + <% if(appDir) { %> + experimental: { + appDir: true + }, + <% } %> }; module.exports = withStylus(withNx(nextConfig)); @@ -50,6 +60,11 @@ const nextConfig = { // See: https://github.com/gregberge/svgr svgr: false, }, + <% if(appDir) { %> + experimental: { + appDir: true + }, + <% } %> }; module.exports = withNx(nextConfig); @@ -64,6 +79,11 @@ const nextConfig = { // See: https://github.com/gregberge/svgr svgr: false, }, + <% if(appDir) { %> + experimental: { + appDir: true + }, + <% } %> }; module.exports = withNx(nextConfig); diff --git a/packages/next/src/generators/application/files/public/.gitkeep b/packages/next/src/generators/application/files/common/public/.gitkeep similarity index 100% rename from packages/next/src/generators/application/files/public/.gitkeep rename to packages/next/src/generators/application/files/common/public/.gitkeep diff --git a/packages/next/src/generators/application/files/specs/__fileName__.spec.tsx__tmpl__ b/packages/next/src/generators/application/files/common/specs/__fileName__.spec.tsx__tmpl__ similarity index 100% rename from packages/next/src/generators/application/files/specs/__fileName__.spec.tsx__tmpl__ rename to packages/next/src/generators/application/files/common/specs/__fileName__.spec.tsx__tmpl__ diff --git a/packages/next/src/generators/application/files/tsconfig.json__tmpl__ b/packages/next/src/generators/application/files/common/tsconfig.json__tmpl__ similarity index 100% rename from packages/next/src/generators/application/files/tsconfig.json__tmpl__ rename to packages/next/src/generators/application/files/common/tsconfig.json__tmpl__ diff --git a/packages/next/src/generators/application/files/pages/favicon.ico b/packages/next/src/generators/application/files/pages/favicon.ico new file mode 100644 index 0000000000000..317ebcb2336e0 Binary files /dev/null and b/packages/next/src/generators/application/files/pages/favicon.ico differ diff --git a/packages/next/src/generators/application/lib/create-application-files.ts b/packages/next/src/generators/application/lib/create-application-files.ts index c4319c306da45..e1c9323ca7804 100644 --- a/packages/next/src/generators/application/lib/create-application-files.ts +++ b/packages/next/src/generators/application/lib/create-application-files.ts @@ -28,11 +28,27 @@ export function createApplicationFiles(host: Tree, options: NormalizedSchema) { generateFiles( host, - join(__dirname, '../files'), + join(__dirname, '../files/common'), options.appProjectRoot, templateVariables ); + if (options.appDir) { + generateFiles( + host, + join(__dirname, '../files/app'), + join(options.appProjectRoot, 'app'), + templateVariables + ); + } else { + generateFiles( + host, + join(__dirname, '../files/pages'), + join(options.appProjectRoot, 'pages'), + templateVariables + ); + } + if (options.unitTestRunner === 'none') { host.delete(`${options.appProjectRoot}/specs/${options.fileName}.spec.tsx`); } diff --git a/packages/next/src/generators/application/lib/normalize-options.ts b/packages/next/src/generators/application/lib/normalize-options.ts index fab1c9653bfe9..4df023ad29efe 100644 --- a/packages/next/src/generators/application/lib/normalize-options.ts +++ b/packages/next/src/generators/application/lib/normalize-options.ts @@ -47,6 +47,8 @@ export function normalizeOptions( const fileName = 'index'; + const appDir = options.appDir ?? false; + const styledModule = /^(css|scss|less|styl)$/.test(options.style) ? null : options.style; @@ -55,6 +57,7 @@ export function normalizeOptions( return { ...options, + appDir, name: names(options.name).fileName, projectName: appProjectName, linter: options.linter || Linter.EsLint, diff --git a/packages/next/src/generators/application/schema.d.ts b/packages/next/src/generators/application/schema.d.ts index dc6de0d244ea4..180a02846f7d3 100644 --- a/packages/next/src/generators/application/schema.d.ts +++ b/packages/next/src/generators/application/schema.d.ts @@ -17,4 +17,5 @@ export interface Schema { swc?: boolean; customServer?: boolean; skipPackageJson?: boolean; + appDir?: boolean; } diff --git a/packages/next/src/generators/application/schema.json b/packages/next/src/generators/application/schema.json index 79db0c6d1bc6c..93ac82b521bb7 100644 --- a/packages/next/src/generators/application/schema.json +++ b/packages/next/src/generators/application/schema.json @@ -124,6 +124,12 @@ "default": false, "description": "Do not add dependencies to `package.json`.", "x-priority": "internal" + }, + "appDir": { + "type": "boolean", + "default": false, + "description": "Enable experimental app directory for the project", + "x-prompt": "Do you want to use experimental app/ in this project?" } }, "required": [],