feat(nextjs): add support for experimental appDir (#16132)

This commit is contained in:
Nicholas Cunningham 2023-04-05 14:07:46 -06:00 committed by GitHub
parent a8b8ea91f2
commit 18e965d2ef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 128 additions and 2 deletions

View File

@ -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": [],

View File

@ -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'));
});
});
});

View File

@ -0,0 +1,4 @@
export async function GET(request: Request) {
return new Response('Hello, from API!')
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -0,0 +1 @@
<%- styleContent %>

View File

@ -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 (
<html lang="en">
<Head>
<title>Welcome to <%= name %>!</title>
</Head>
<body>{children}</body>
</html>
)
}

View File

@ -0,0 +1 @@
<%- pageStyleContent %>

View File

@ -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' ? `<style jsx>{\`${pageStyleContent}\`}</style>` : `` %>
<%- appContent %>
</<%= wrapper %>>
);
};
export default Index;

View File

@ -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);

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -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`);
}

View File

@ -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,

View File

@ -17,4 +17,5 @@ export interface Schema {
swc?: boolean;
customServer?: boolean;
skipPackageJson?: boolean;
appDir?: boolean;
}

View File

@ -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": [],