-
Notifications
You must be signed in to change notification settings - Fork 27.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Creates a root layout if it is missing in DEV when building the page in `next-app-loader`. If the page is in a route group, the layout will be created there. Otherwise it will create a layout directly under `/app`. Breaks the build if a page is found that's missing a root layout. ## Bug - [ ] Related issues linked using `fixes #number` - [ ] Integration tests added - [ ] Errors have a helpful link attached, see `contributing.md` ## Feature - [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR. - [ ] Related issues linked using `fixes #number` - [ ] Integration tests added - [ ] Documentation added - [ ] Telemetry added. In case of a feature if it's used or not. - [ ] Errors have a helpful link attached, see `contributing.md` ## Documentation / Examples - [ ] Make sure the linting passes by running `pnpm lint` - [ ] The "examples guidelines" are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md)
- Loading branch information
Hannes Bornö
authored
Oct 23, 2022
1 parent
0a97d07
commit a105515
Showing
12 changed files
with
392 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
import path from 'path' | ||
import { promises as fs } from 'fs' | ||
import chalk from 'next/dist/compiled/chalk' | ||
import * as Log from '../build/output/log' | ||
import { APP_DIR_ALIAS } from './constants' | ||
|
||
const globOrig = | ||
require('next/dist/compiled/glob') as typeof import('next/dist/compiled/glob') | ||
const glob = (cwd: string, pattern: string): Promise<string[]> => { | ||
return new Promise((resolve, reject) => { | ||
globOrig(pattern, { cwd }, (err, files) => { | ||
if (err) { | ||
return reject(err) | ||
} | ||
resolve(files) | ||
}) | ||
}) | ||
} | ||
|
||
function getRootLayout(isTs: boolean) { | ||
if (isTs) { | ||
return `export default function RootLayout({ | ||
children, | ||
}: { | ||
children: React.ReactNode | ||
}) { | ||
return ( | ||
<html> | ||
<head></head> | ||
<body>{children}</body> | ||
</html> | ||
) | ||
} | ||
` | ||
} | ||
|
||
return `export default function RootLayout({ children }) { | ||
return ( | ||
<html> | ||
<head></head> | ||
<body>{children}</body> | ||
</html> | ||
) | ||
} | ||
` | ||
} | ||
|
||
export async function verifyRootLayout({ | ||
dir, | ||
appDir, | ||
tsconfigPath, | ||
pagePath, | ||
pageExtensions, | ||
}: { | ||
dir: string | ||
appDir: string | ||
tsconfigPath: string | ||
pagePath: string | ||
pageExtensions: string[] | ||
}) { | ||
try { | ||
const layoutFiles = await glob( | ||
appDir, | ||
`**/layout.{${pageExtensions.join(',')}}` | ||
) | ||
const hasLayout = layoutFiles.length !== 0 | ||
|
||
const normalizedPagePath = pagePath.replace(`${APP_DIR_ALIAS}/`, '') | ||
const firstSegmentValue = normalizedPagePath.split('/')[0] | ||
const pageRouteGroup = firstSegmentValue.startsWith('(') | ||
? firstSegmentValue | ||
: undefined | ||
|
||
if (pageRouteGroup || !hasLayout) { | ||
const resolvedTsConfigPath = path.join(dir, tsconfigPath) | ||
const hasTsConfig = await fs.access(resolvedTsConfigPath).then( | ||
() => true, | ||
() => false | ||
) | ||
|
||
const rootLayoutPath = path.join( | ||
appDir, | ||
// If the page is within a route group directly under app (e.g. app/(routegroup)/page.js) | ||
// prefer creating the root layout in that route group. Otherwise create the root layout in the app root. | ||
pageRouteGroup ? pageRouteGroup : '', | ||
`layout.${hasTsConfig ? 'tsx' : 'js'}` | ||
) | ||
await fs.writeFile(rootLayoutPath, getRootLayout(hasTsConfig)) | ||
console.log( | ||
chalk.green( | ||
`\nYour page ${chalk.bold( | ||
`app/${normalizedPagePath}` | ||
)} did not have a root layout, we created ${chalk.bold( | ||
`app${rootLayoutPath.replace(appDir, '')}` | ||
)} for you.` | ||
) + '\n' | ||
) | ||
|
||
// Created root layout | ||
return true | ||
} | ||
} catch (error) { | ||
Log.error('Failed to create root layout', error) | ||
} | ||
|
||
// Didn't create root layout | ||
return false | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
export default function RootLayout({ children }) { | ||
return ( | ||
<html> | ||
<body>{children}</body> | ||
</html> | ||
) | ||
} |
Oops, something went wrong.