507 lines
24 KiB
JavaScript
507 lines
24 KiB
JavaScript
|
"use strict";
|
||
|
Object.defineProperty(exports, "__esModule", {
|
||
|
value: true
|
||
|
});
|
||
|
Object.defineProperty(exports, "default", {
|
||
|
enumerable: true,
|
||
|
get: function() {
|
||
|
return _default;
|
||
|
}
|
||
|
});
|
||
|
const _path = /*#__PURE__*/ _interop_require_default(require("path"));
|
||
|
const _querystring = require("querystring");
|
||
|
const _picocolors = require("../../../lib/picocolors");
|
||
|
const _getmodulebuildinfo = require("./get-module-build-info");
|
||
|
const _verifyRootLayout = require("../../../lib/verifyRootLayout");
|
||
|
const _log = /*#__PURE__*/ _interop_require_wildcard(require("../../output/log"));
|
||
|
const _constants = require("../../../lib/constants");
|
||
|
const _discover = require("./metadata/discover");
|
||
|
const _fs = require("fs");
|
||
|
const _isapprouteroute = require("../../../lib/is-app-route-route");
|
||
|
const _ismetadataroute = require("../../../lib/metadata/is-metadata-route");
|
||
|
const _apppathnamenormalizer = require("../../../server/future/normalizers/built/app/app-pathname-normalizer");
|
||
|
const _appbundlepathnormalizer = require("../../../server/future/normalizers/built/app/app-bundle-path-normalizer");
|
||
|
const _nextmetadatarouteloader = require("./next-metadata-route-loader");
|
||
|
const _utils = require("../../utils");
|
||
|
const _loadentrypoint = require("../../load-entrypoint");
|
||
|
const _segment = require("../../../shared/lib/segment");
|
||
|
function _interop_require_default(obj) {
|
||
|
return obj && obj.__esModule ? obj : {
|
||
|
default: obj
|
||
|
};
|
||
|
}
|
||
|
function _getRequireWildcardCache(nodeInterop) {
|
||
|
if (typeof WeakMap !== "function") return null;
|
||
|
var cacheBabelInterop = new WeakMap();
|
||
|
var cacheNodeInterop = new WeakMap();
|
||
|
return (_getRequireWildcardCache = function(nodeInterop) {
|
||
|
return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
|
||
|
})(nodeInterop);
|
||
|
}
|
||
|
function _interop_require_wildcard(obj, nodeInterop) {
|
||
|
if (!nodeInterop && obj && obj.__esModule) {
|
||
|
return obj;
|
||
|
}
|
||
|
if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
|
||
|
return {
|
||
|
default: obj
|
||
|
};
|
||
|
}
|
||
|
var cache = _getRequireWildcardCache(nodeInterop);
|
||
|
if (cache && cache.has(obj)) {
|
||
|
return cache.get(obj);
|
||
|
}
|
||
|
var newObj = {};
|
||
|
var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
|
||
|
for(var key in obj){
|
||
|
if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
|
||
|
var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
|
||
|
if (desc && (desc.get || desc.set)) {
|
||
|
Object.defineProperty(newObj, key, desc);
|
||
|
} else {
|
||
|
newObj[key] = obj[key];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
newObj.default = obj;
|
||
|
if (cache) {
|
||
|
cache.set(obj, newObj);
|
||
|
}
|
||
|
return newObj;
|
||
|
}
|
||
|
const FILE_TYPES = {
|
||
|
layout: "layout",
|
||
|
template: "template",
|
||
|
error: "error",
|
||
|
loading: "loading",
|
||
|
"not-found": "not-found"
|
||
|
};
|
||
|
const GLOBAL_ERROR_FILE_TYPE = "global-error";
|
||
|
const PAGE_SEGMENT = "page$";
|
||
|
const PARALLEL_CHILDREN_SEGMENT = "children$";
|
||
|
const defaultNotFoundPath = "next/dist/client/components/not-found-error";
|
||
|
async function createAppRouteCode({ name, page, pagePath, resolveAppRoute, pageExtensions, nextConfigOutput }) {
|
||
|
// routePath is the path to the route handler file,
|
||
|
// but could be aliased e.g. private-next-app-dir/favicon.ico
|
||
|
const routePath = pagePath.replace(/[\\/]/, "/");
|
||
|
// This, when used with the resolver will give us the pathname to the built
|
||
|
// route handler file.
|
||
|
let resolvedPagePath = await resolveAppRoute(routePath);
|
||
|
if (!resolvedPagePath) {
|
||
|
throw new Error(`Invariant: could not resolve page path for ${name} at ${routePath}`);
|
||
|
}
|
||
|
// If this is a metadata route, then we need to use the metadata loader for
|
||
|
// the route to ensure that the route is generated.
|
||
|
const filename = _path.default.parse(resolvedPagePath).name;
|
||
|
if ((0, _ismetadataroute.isMetadataRoute)(name) && filename !== "route") {
|
||
|
const { ext } = (0, _nextmetadatarouteloader.getFilenameAndExtension)(resolvedPagePath);
|
||
|
const isDynamic = pageExtensions.includes(ext);
|
||
|
resolvedPagePath = `next-metadata-route-loader?${(0, _querystring.stringify)({
|
||
|
page,
|
||
|
isDynamic: isDynamic ? "1" : "0"
|
||
|
})}!${resolvedPagePath}${`?${_constants.WEBPACK_RESOURCE_QUERIES.metadataRoute}`}`;
|
||
|
}
|
||
|
const pathname = new _apppathnamenormalizer.AppPathnameNormalizer().normalize(page);
|
||
|
const bundlePath = new _appbundlepathnormalizer.AppBundlePathNormalizer().normalize(page);
|
||
|
return await (0, _loadentrypoint.loadEntrypoint)("app-route", {
|
||
|
VAR_USERLAND: resolvedPagePath,
|
||
|
VAR_DEFINITION_PAGE: page,
|
||
|
VAR_DEFINITION_PATHNAME: pathname,
|
||
|
VAR_DEFINITION_FILENAME: filename,
|
||
|
VAR_DEFINITION_BUNDLE_PATH: bundlePath,
|
||
|
VAR_RESOLVED_PAGE_PATH: resolvedPagePath,
|
||
|
VAR_ORIGINAL_PATHNAME: page
|
||
|
}, {
|
||
|
nextConfigOutput: JSON.stringify(nextConfigOutput)
|
||
|
});
|
||
|
}
|
||
|
const normalizeParallelKey = (key)=>key.startsWith("@") ? key.slice(1) : key;
|
||
|
const isDirectory = async (pathname)=>{
|
||
|
try {
|
||
|
const stat = await _fs.promises.stat(pathname);
|
||
|
return stat.isDirectory();
|
||
|
} catch (err) {
|
||
|
return false;
|
||
|
}
|
||
|
};
|
||
|
async function createTreeCodeFromPath(pagePath, { page, resolveDir, resolver, resolveParallelSegments, metadataResolver, pageExtensions, basePath }) {
|
||
|
const splittedPath = pagePath.split(/[\\/]/);
|
||
|
const isNotFoundRoute = page === "/_not-found";
|
||
|
const isDefaultNotFound = (0, _utils.isAppBuiltinNotFoundPage)(pagePath);
|
||
|
const appDirPrefix = isDefaultNotFound ? _constants.APP_DIR_ALIAS : splittedPath[0];
|
||
|
const hasRootNotFound = await resolver(`${appDirPrefix}/${FILE_TYPES["not-found"]}`);
|
||
|
const pages = [];
|
||
|
let rootLayout;
|
||
|
let globalError;
|
||
|
async function resolveAdjacentParallelSegments(segmentPath) {
|
||
|
const absoluteSegmentPath = await resolveDir(`${appDirPrefix}${segmentPath}`);
|
||
|
if (!absoluteSegmentPath) {
|
||
|
return [];
|
||
|
}
|
||
|
const segmentIsDirectory = await isDirectory(absoluteSegmentPath);
|
||
|
if (!segmentIsDirectory) {
|
||
|
return [];
|
||
|
}
|
||
|
// We need to resolve all parallel routes in this level.
|
||
|
const files = await _fs.promises.opendir(absoluteSegmentPath);
|
||
|
const parallelSegments = [
|
||
|
"children"
|
||
|
];
|
||
|
for await (const dirent of files){
|
||
|
// Make sure name starts with "@" and is a directory.
|
||
|
if (dirent.isDirectory() && dirent.name.charCodeAt(0) === 64) {
|
||
|
parallelSegments.push(dirent.name);
|
||
|
}
|
||
|
}
|
||
|
return parallelSegments;
|
||
|
}
|
||
|
async function createSubtreePropsFromSegmentPath(segments) {
|
||
|
const segmentPath = segments.join("/");
|
||
|
// Existing tree are the children of the current segment
|
||
|
const props = {};
|
||
|
// Root layer could be 1st layer of normal routes
|
||
|
const isRootLayer = segments.length === 0;
|
||
|
const isRootLayoutOrRootPage = segments.length <= 1;
|
||
|
// We need to resolve all parallel routes in this level.
|
||
|
const parallelSegments = [];
|
||
|
if (isRootLayer) {
|
||
|
parallelSegments.push([
|
||
|
"children",
|
||
|
""
|
||
|
]);
|
||
|
} else {
|
||
|
parallelSegments.push(...resolveParallelSegments(segmentPath));
|
||
|
}
|
||
|
let metadata = null;
|
||
|
const routerDirPath = `${appDirPrefix}${segmentPath}`;
|
||
|
// For default not-found, don't traverse the directory to find metadata.
|
||
|
const resolvedRouteDir = isDefaultNotFound ? "" : await resolveDir(routerDirPath);
|
||
|
if (resolvedRouteDir) {
|
||
|
metadata = await (0, _discover.createStaticMetadataFromRoute)(resolvedRouteDir, {
|
||
|
basePath,
|
||
|
segment: segmentPath,
|
||
|
metadataResolver,
|
||
|
isRootLayoutOrRootPage,
|
||
|
pageExtensions
|
||
|
});
|
||
|
}
|
||
|
for (const [parallelKey, parallelSegment] of parallelSegments){
|
||
|
if (parallelSegment === PAGE_SEGMENT) {
|
||
|
const matchedPagePath = `${appDirPrefix}${segmentPath}${parallelKey === "children" ? "" : `/${parallelKey}`}/page`;
|
||
|
const resolvedPagePath = await resolver(matchedPagePath);
|
||
|
if (resolvedPagePath) pages.push(resolvedPagePath);
|
||
|
// Use '' for segment as it's the page. There can't be a segment called '' so this is the safest way to add it.
|
||
|
props[normalizeParallelKey(parallelKey)] = `['__PAGE__', {}, {
|
||
|
page: [() => import(/* webpackMode: "eager" */ ${JSON.stringify(resolvedPagePath)}), ${JSON.stringify(resolvedPagePath)}],
|
||
|
${(0, _discover.createMetadataExportsCode)(metadata)}
|
||
|
}]`;
|
||
|
continue;
|
||
|
}
|
||
|
const subSegmentPath = [
|
||
|
...segments
|
||
|
];
|
||
|
if (parallelKey !== "children") {
|
||
|
subSegmentPath.push(parallelKey);
|
||
|
}
|
||
|
const normalizedParallelSegments = Array.isArray(parallelSegment) ? parallelSegment.slice(0, 1) : [
|
||
|
parallelSegment
|
||
|
];
|
||
|
subSegmentPath.push(...normalizedParallelSegments.filter((segment)=>segment !== PAGE_SEGMENT && segment !== PARALLEL_CHILDREN_SEGMENT));
|
||
|
const { treeCode: pageSubtreeCode } = await createSubtreePropsFromSegmentPath(subSegmentPath);
|
||
|
const parallelSegmentPath = subSegmentPath.join("/");
|
||
|
// `page` is not included here as it's added above.
|
||
|
const filePaths = await Promise.all(Object.values(FILE_TYPES).map(async (file)=>{
|
||
|
return [
|
||
|
file,
|
||
|
await resolver(`${appDirPrefix}${// TODO-APP: parallelSegmentPath sometimes ends in `/` but sometimes it doesn't. This should be consistent.
|
||
|
parallelSegmentPath.endsWith("/") ? parallelSegmentPath : parallelSegmentPath + "/"}${file}`)
|
||
|
];
|
||
|
}));
|
||
|
const definedFilePaths = filePaths.filter(([, filePath])=>filePath !== undefined);
|
||
|
// Add default not found error as root not found if not present
|
||
|
const hasNotFoundFile = definedFilePaths.some(([type])=>type === "not-found");
|
||
|
// If the first layer is a group route, we treat it as root layer
|
||
|
const isFirstLayerGroupRoute = segments.length === 1 && subSegmentPath.filter((seg)=>(0, _segment.isGroupSegment)(seg)).length === 1;
|
||
|
if ((isRootLayer || isFirstLayerGroupRoute) && !hasNotFoundFile) {
|
||
|
// If you already have a root not found, don't insert default not-found to group routes root
|
||
|
if (!(hasRootNotFound && isFirstLayerGroupRoute)) {
|
||
|
definedFilePaths.push([
|
||
|
"not-found",
|
||
|
defaultNotFoundPath
|
||
|
]);
|
||
|
}
|
||
|
}
|
||
|
if (!rootLayout) {
|
||
|
var _definedFilePaths_find;
|
||
|
const layoutPath = (_definedFilePaths_find = definedFilePaths.find(([type])=>type === "layout")) == null ? void 0 : _definedFilePaths_find[1];
|
||
|
rootLayout = layoutPath;
|
||
|
if (isDefaultNotFound && !layoutPath) {
|
||
|
rootLayout = "next/dist/client/components/default-layout";
|
||
|
definedFilePaths.push([
|
||
|
"layout",
|
||
|
rootLayout
|
||
|
]);
|
||
|
}
|
||
|
if (layoutPath) {
|
||
|
globalError = await resolver(`${_path.default.dirname(layoutPath)}/${GLOBAL_ERROR_FILE_TYPE}`);
|
||
|
}
|
||
|
}
|
||
|
let parallelSegmentKey = Array.isArray(parallelSegment) ? parallelSegment[0] : parallelSegment;
|
||
|
parallelSegmentKey = parallelSegmentKey === PARALLEL_CHILDREN_SEGMENT ? "children" : parallelSegmentKey;
|
||
|
const normalizedParallelKey = normalizeParallelKey(parallelKey);
|
||
|
let subtreeCode = pageSubtreeCode;
|
||
|
// If it's root not found page, set not-found boundary as children page
|
||
|
if (isNotFoundRoute && normalizedParallelKey === "children") {
|
||
|
var _definedFilePaths_find1;
|
||
|
const notFoundPath = ((_definedFilePaths_find1 = definedFilePaths.find(([type])=>type === "not-found")) == null ? void 0 : _definedFilePaths_find1[1]) ?? defaultNotFoundPath;
|
||
|
subtreeCode = `{
|
||
|
children: ['__PAGE__', {}, {
|
||
|
page: [
|
||
|
() => import(/* webpackMode: "eager" */ ${JSON.stringify(notFoundPath)}),
|
||
|
${JSON.stringify(notFoundPath)}
|
||
|
]
|
||
|
}]
|
||
|
}`;
|
||
|
}
|
||
|
const componentsCode = `{
|
||
|
${definedFilePaths.map(([file, filePath])=>{
|
||
|
return `'${file}': [() => import(/* webpackMode: "eager" */ ${JSON.stringify(filePath)}), ${JSON.stringify(filePath)}],`;
|
||
|
}).join("\n")}
|
||
|
${(0, _discover.createMetadataExportsCode)(metadata)}
|
||
|
}`;
|
||
|
props[normalizedParallelKey] = `[
|
||
|
'${parallelSegmentKey}',
|
||
|
${subtreeCode},
|
||
|
${componentsCode}
|
||
|
]`;
|
||
|
}
|
||
|
const adjacentParallelSegments = await resolveAdjacentParallelSegments(segmentPath);
|
||
|
for (const adjacentParallelSegment of adjacentParallelSegments){
|
||
|
if (!props[normalizeParallelKey(adjacentParallelSegment)]) {
|
||
|
const actualSegment = adjacentParallelSegment === "children" ? "" : adjacentParallelSegment;
|
||
|
const defaultPath = await resolver(`${appDirPrefix}${segmentPath}/${actualSegment}/default`) ?? "next/dist/client/components/parallel-route-default";
|
||
|
props[normalizeParallelKey(adjacentParallelSegment)] = `[
|
||
|
'__DEFAULT__',
|
||
|
{},
|
||
|
{
|
||
|
defaultPage: [() => import(/* webpackMode: "eager" */ ${JSON.stringify(defaultPath)}), ${JSON.stringify(defaultPath)}],
|
||
|
}
|
||
|
]`;
|
||
|
}
|
||
|
}
|
||
|
return {
|
||
|
treeCode: `{
|
||
|
${Object.entries(props).map(([key, value])=>`${key}: ${value}`).join(",\n")}
|
||
|
}`
|
||
|
};
|
||
|
}
|
||
|
const { treeCode } = await createSubtreePropsFromSegmentPath([]);
|
||
|
return {
|
||
|
treeCode: `${treeCode}.children;`,
|
||
|
pages: `${JSON.stringify(pages)};`,
|
||
|
rootLayout,
|
||
|
globalError
|
||
|
};
|
||
|
}
|
||
|
function createAbsolutePath(appDir, pathToTurnAbsolute) {
|
||
|
return pathToTurnAbsolute// Replace all POSIX path separators with the current OS path separator
|
||
|
.replace(/\//g, _path.default.sep).replace(/^private-next-app-dir/, appDir);
|
||
|
}
|
||
|
const nextAppLoader = async function nextAppLoader() {
|
||
|
const loaderOptions = this.getOptions();
|
||
|
const { name, appDir, appPaths, pagePath, pageExtensions, rootDir, tsconfigPath, isDev, nextConfigOutput, preferredRegion, basePath, middlewareConfig: middlewareConfigBase64 } = loaderOptions;
|
||
|
const buildInfo = (0, _getmodulebuildinfo.getModuleBuildInfo)(this._module);
|
||
|
const page = name.replace(/^app/, "");
|
||
|
const middlewareConfig = JSON.parse(Buffer.from(middlewareConfigBase64, "base64").toString());
|
||
|
buildInfo.route = {
|
||
|
page,
|
||
|
absolutePagePath: createAbsolutePath(appDir, pagePath),
|
||
|
preferredRegion,
|
||
|
middlewareConfig
|
||
|
};
|
||
|
const extensions = pageExtensions.map((extension)=>`.${extension}`);
|
||
|
const normalizedAppPaths = typeof appPaths === "string" ? [
|
||
|
appPaths
|
||
|
] : appPaths || [];
|
||
|
const resolveParallelSegments = (pathname)=>{
|
||
|
const matched = {};
|
||
|
let existingChildrenPath;
|
||
|
for (const appPath of normalizedAppPaths){
|
||
|
if (appPath.startsWith(pathname + "/")) {
|
||
|
const rest = appPath.slice(pathname.length + 1).split("/");
|
||
|
// It is the actual page, mark it specially.
|
||
|
if (rest.length === 1 && rest[0] === "page") {
|
||
|
existingChildrenPath = appPath;
|
||
|
matched.children = PAGE_SEGMENT;
|
||
|
continue;
|
||
|
}
|
||
|
const isParallelRoute = rest[0].startsWith("@");
|
||
|
if (isParallelRoute) {
|
||
|
if (rest.length === 2 && rest[1] === "page") {
|
||
|
// matched will be an empty object in case the parallel route is at a path with no existing page
|
||
|
// in which case, we need to mark it as a regular page segment
|
||
|
matched[rest[0]] = Object.keys(matched).length ? [
|
||
|
PAGE_SEGMENT
|
||
|
] : PAGE_SEGMENT;
|
||
|
continue;
|
||
|
}
|
||
|
// we insert a special marker in order to also process layout/etc files at the slot level
|
||
|
matched[rest[0]] = [
|
||
|
PARALLEL_CHILDREN_SEGMENT,
|
||
|
...rest.slice(1)
|
||
|
];
|
||
|
continue;
|
||
|
}
|
||
|
// avoid clobbering existing page segments
|
||
|
// if it's a valid parallel segment, the `children` property will be set appropriately
|
||
|
if (existingChildrenPath && matched.children !== rest[0]) {
|
||
|
throw new Error(`You cannot have two parallel pages that resolve to the same path. Please check ${existingChildrenPath} and ${appPath}. Refer to the route group docs for more information: https://nextjs.org/docs/app/building-your-application/routing/route-groups`);
|
||
|
}
|
||
|
existingChildrenPath = appPath;
|
||
|
matched.children = rest[0];
|
||
|
}
|
||
|
}
|
||
|
return Object.entries(matched);
|
||
|
};
|
||
|
const resolveDir = (pathToResolve)=>{
|
||
|
return createAbsolutePath(appDir, pathToResolve);
|
||
|
};
|
||
|
const resolveAppRoute = (pathToResolve)=>{
|
||
|
return createAbsolutePath(appDir, pathToResolve);
|
||
|
};
|
||
|
// Cached checker to see if a file exists in a given directory.
|
||
|
// This can be more efficient than checking them with `fs.stat` one by one
|
||
|
// because all the thousands of files are likely in a few possible directories.
|
||
|
// Note that it should only be cached for this compilation, not globally.
|
||
|
const filesInDir = new Map();
|
||
|
const fileExistsInDirectory = async (dirname, fileName)=>{
|
||
|
const existingFiles = filesInDir.get(dirname);
|
||
|
if (existingFiles) {
|
||
|
return existingFiles.has(fileName);
|
||
|
}
|
||
|
try {
|
||
|
const files = await _fs.promises.readdir(dirname, {
|
||
|
withFileTypes: true
|
||
|
});
|
||
|
const fileNames = new Set();
|
||
|
for (const file of files){
|
||
|
if (file.isFile()) {
|
||
|
fileNames.add(file.name);
|
||
|
}
|
||
|
}
|
||
|
filesInDir.set(dirname, fileNames);
|
||
|
return fileNames.has(fileName);
|
||
|
} catch (err) {
|
||
|
return false;
|
||
|
}
|
||
|
};
|
||
|
const resolver = async (pathname)=>{
|
||
|
const absolutePath = createAbsolutePath(appDir, pathname);
|
||
|
const filenameIndex = absolutePath.lastIndexOf(_path.default.sep);
|
||
|
const dirname = absolutePath.slice(0, filenameIndex);
|
||
|
const filename = absolutePath.slice(filenameIndex + 1);
|
||
|
let result;
|
||
|
for (const ext of extensions){
|
||
|
const absolutePathWithExtension = `${absolutePath}${ext}`;
|
||
|
if (!result && await fileExistsInDirectory(dirname, `${filename}${ext}`)) {
|
||
|
result = absolutePathWithExtension;
|
||
|
}
|
||
|
// Call `addMissingDependency` for all files even if they didn't match,
|
||
|
// because they might be added or removed during development.
|
||
|
this.addMissingDependency(absolutePathWithExtension);
|
||
|
}
|
||
|
return result;
|
||
|
};
|
||
|
const metadataResolver = async (dirname, filename, exts)=>{
|
||
|
const absoluteDir = createAbsolutePath(appDir, dirname);
|
||
|
let result;
|
||
|
for (const ext of exts){
|
||
|
// Compared to `resolver` above the exts do not have the `.` included already, so it's added here.
|
||
|
const filenameWithExt = `${filename}.${ext}`;
|
||
|
const absolutePathWithExtension = `${absoluteDir}${_path.default.sep}${filenameWithExt}`;
|
||
|
if (!result && await fileExistsInDirectory(dirname, filenameWithExt)) {
|
||
|
result = absolutePathWithExtension;
|
||
|
}
|
||
|
// Call `addMissingDependency` for all files even if they didn't match,
|
||
|
// because they might be added or removed during development.
|
||
|
this.addMissingDependency(absolutePathWithExtension);
|
||
|
}
|
||
|
return result;
|
||
|
};
|
||
|
if ((0, _isapprouteroute.isAppRouteRoute)(name)) {
|
||
|
return createAppRouteCode({
|
||
|
// TODO: investigate if the local `page` is the same as the loaderOptions.page
|
||
|
page: loaderOptions.page,
|
||
|
name,
|
||
|
pagePath,
|
||
|
resolveAppRoute,
|
||
|
pageExtensions,
|
||
|
nextConfigOutput
|
||
|
});
|
||
|
}
|
||
|
let treeCodeResult = await createTreeCodeFromPath(pagePath, {
|
||
|
page,
|
||
|
resolveDir,
|
||
|
resolver,
|
||
|
metadataResolver,
|
||
|
resolveParallelSegments,
|
||
|
loaderContext: this,
|
||
|
pageExtensions,
|
||
|
basePath
|
||
|
});
|
||
|
if (!treeCodeResult.rootLayout) {
|
||
|
if (!isDev) {
|
||
|
// If we're building and missing a root layout, exit the build
|
||
|
_log.error(`${(0, _picocolors.bold)(pagePath.replace(`${_constants.APP_DIR_ALIAS}/`, ""))} doesn't have a root layout. To fix this error, make sure every page has a root layout.`);
|
||
|
process.exit(1);
|
||
|
} else {
|
||
|
// In dev we'll try to create a root layout
|
||
|
const [createdRootLayout, rootLayoutPath] = await (0, _verifyRootLayout.verifyRootLayout)({
|
||
|
appDir: appDir,
|
||
|
dir: rootDir,
|
||
|
tsconfigPath: tsconfigPath,
|
||
|
pagePath,
|
||
|
pageExtensions
|
||
|
});
|
||
|
if (!createdRootLayout) {
|
||
|
let message = `${(0, _picocolors.bold)(pagePath.replace(`${_constants.APP_DIR_ALIAS}/`, ""))} doesn't have a root layout. `;
|
||
|
if (rootLayoutPath) {
|
||
|
var _this__compiler;
|
||
|
message += `We tried to create ${(0, _picocolors.bold)(_path.default.relative(((_this__compiler = this._compiler) == null ? void 0 : _this__compiler.context) ?? "", rootLayoutPath))} for you but something went wrong.`;
|
||
|
} else {
|
||
|
message += "To fix this error, make sure every page has a root layout.";
|
||
|
}
|
||
|
throw new Error(message);
|
||
|
}
|
||
|
// Clear fs cache, get the new result with the created root layout.
|
||
|
filesInDir.clear();
|
||
|
treeCodeResult = await createTreeCodeFromPath(pagePath, {
|
||
|
page,
|
||
|
resolveDir,
|
||
|
resolver,
|
||
|
metadataResolver,
|
||
|
resolveParallelSegments,
|
||
|
loaderContext: this,
|
||
|
pageExtensions,
|
||
|
basePath
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
const pathname = new _apppathnamenormalizer.AppPathnameNormalizer().normalize(page);
|
||
|
// Prefer to modify next/src/server/app-render/entry-base.ts since this is shared with Turbopack.
|
||
|
// Any changes to this code should be reflected in Turbopack's app_source.rs and/or app-renderer.tsx as well.
|
||
|
return await (0, _loadentrypoint.loadEntrypoint)("app-page", {
|
||
|
VAR_DEFINITION_PAGE: page,
|
||
|
VAR_DEFINITION_PATHNAME: pathname,
|
||
|
VAR_MODULE_GLOBAL_ERROR: treeCodeResult.globalError ? treeCodeResult.globalError : "next/dist/client/components/error-boundary",
|
||
|
VAR_ORIGINAL_PATHNAME: page
|
||
|
}, {
|
||
|
tree: treeCodeResult.treeCode,
|
||
|
pages: treeCodeResult.pages,
|
||
|
__next_app_require__: "__webpack_require__",
|
||
|
__next_app_load_chunk__: "() => Promise.resolve()"
|
||
|
});
|
||
|
};
|
||
|
const _default = nextAppLoader;
|
||
|
|
||
|
//# sourceMappingURL=next-app-loader.js.map
|