feat(nextjs): add support for experimental appDir (#16132)
This commit is contained in:
parent
a8b8ea91f2
commit
18e965d2ef
@ -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": [],
|
||||
|
||||
@ -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'));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -0,0 +1,4 @@
|
||||
export async function GET(request: Request) {
|
||||
return new Response('Hello, from API!')
|
||||
}
|
||||
|
||||
BIN
packages/next/src/generators/application/files/app/favicon.ico
Normal file
BIN
packages/next/src/generators/application/files/app/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
@ -0,0 +1 @@
|
||||
<%- styleContent %>
|
||||
@ -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>
|
||||
)
|
||||
}
|
||||
@ -0,0 +1 @@
|
||||
<%- pageStyleContent %>
|
||||
@ -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;
|
||||
@ -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);
|
||||
BIN
packages/next/src/generators/application/files/pages/favicon.ico
Normal file
BIN
packages/next/src/generators/application/files/pages/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
@ -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`);
|
||||
}
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -17,4 +17,5 @@ export interface Schema {
|
||||
swc?: boolean;
|
||||
customServer?: boolean;
|
||||
skipPackageJson?: boolean;
|
||||
appDir?: boolean;
|
||||
}
|
||||
|
||||
@ -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": [],
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user