.
This commit is contained in:
+4
@@ -0,0 +1,4 @@
|
||||
export * from '../shared/lib/app-dynamic';
|
||||
export { default } from '../shared/lib/app-dynamic';
|
||||
|
||||
//# sourceMappingURL=app-dynamic.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../../../src/api/app-dynamic.ts"],"sourcesContent":["export * from '../shared/lib/app-dynamic'\nexport { default } from '../shared/lib/app-dynamic'\n"],"names":["default"],"mappings":"AAAA,cAAc,4BAA2B;AACzC,SAASA,OAAO,QAAQ,4BAA2B","ignoreList":[0]}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
export * from '../pages/_app';
|
||||
export { default } from '../pages/_app';
|
||||
|
||||
//# sourceMappingURL=app.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../../../src/api/app.tsx"],"sourcesContent":["export * from '../pages/_app'\nexport { default } from '../pages/_app'\n"],"names":["default"],"mappings":"AAAA,cAAc,gBAAe;AAC7B,SAASA,OAAO,QAAQ,gBAAe","ignoreList":[0]}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
export * from '../shared/lib/constants';
|
||||
|
||||
//# sourceMappingURL=constants.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../../../src/api/constants.ts"],"sourcesContent":["export * from '../shared/lib/constants'\n"],"names":[],"mappings":"AAAA,cAAc,0BAAyB","ignoreList":[0]}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
export * from '../pages/_document';
|
||||
export { default } from '../pages/_document';
|
||||
|
||||
//# sourceMappingURL=document.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../../../src/api/document.tsx"],"sourcesContent":["export * from '../pages/_document'\nexport { default } from '../pages/_document'\n"],"names":["default"],"mappings":"AAAA,cAAc,qBAAoB;AAClC,SAASA,OAAO,QAAQ,qBAAoB","ignoreList":[0]}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
export { default } from '../shared/lib/dynamic';
|
||||
export * from '../shared/lib/dynamic';
|
||||
|
||||
//# sourceMappingURL=dynamic.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../../../src/api/dynamic.ts"],"sourcesContent":["export { default } from '../shared/lib/dynamic'\nexport * from '../shared/lib/dynamic'\n"],"names":["default"],"mappings":"AAAA,SAASA,OAAO,QAAQ,wBAAuB;AAC/C,cAAc,wBAAuB","ignoreList":[0]}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
// Pages Router only
|
||||
export { default } from '../pages/_error';
|
||||
export * from '../pages/_error';
|
||||
export { unstable_catchError } from '../client/components/catch-error';
|
||||
|
||||
//# sourceMappingURL=error.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../../../src/api/error.ts"],"sourcesContent":["// Pages Router only\nexport { default } from '../pages/_error'\nexport * from '../pages/_error'\n\nexport { unstable_catchError } from '../client/components/catch-error'\nexport type { ErrorInfo } from '../client/components/error-boundary'\n"],"names":["default","unstable_catchError"],"mappings":"AAAA,oBAAoB;AACpB,SAASA,OAAO,QAAQ,kBAAiB;AACzC,cAAc,kBAAiB;AAE/B,SAASC,mBAAmB,QAAQ,mCAAkC","ignoreList":[0]}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
export function unstable_catchError() {
|
||||
throw Object.defineProperty(new Error('`unstable_catchError` can only be used in Client Components.'), "__NEXT_ERROR_CODE", {
|
||||
value: "E1139",
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
}
|
||||
|
||||
//# sourceMappingURL=error.react-server.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../../../src/api/error.react-server.ts"],"sourcesContent":["export function unstable_catchError(): never {\n throw new Error(\n '`unstable_catchError` can only be used in Client Components.'\n )\n}\n\nexport type { ErrorInfo } from '../client/components/error-boundary'\n"],"names":["unstable_catchError","Error"],"mappings":"AAAA,OAAO,SAASA;IACd,MAAM,qBAEL,CAFK,IAAIC,MACR,iEADI,qBAAA;eAAA;oBAAA;sBAAA;IAEN;AACF","ignoreList":[0]}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
export { default } from '../client/form';
|
||||
export * from '../client/form';
|
||||
|
||||
//# sourceMappingURL=form.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../../../src/api/form.ts"],"sourcesContent":["export { default } from '../client/form'\nexport * from '../client/form'\n"],"names":["default"],"mappings":"AAAA,SAASA,OAAO,QAAQ,iBAAgB;AACxC,cAAc,iBAAgB","ignoreList":[0]}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
export { default } from '../shared/lib/head';
|
||||
export * from '../shared/lib/head';
|
||||
|
||||
//# sourceMappingURL=head.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../../../src/api/head.ts"],"sourcesContent":["export { default } from '../shared/lib/head'\nexport * from '../shared/lib/head'\n"],"names":["default"],"mappings":"AAAA,SAASA,OAAO,QAAQ,qBAAoB;AAC5C,cAAc,qBAAoB","ignoreList":[0]}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
export * from '../server/request/cookies';
|
||||
export * from '../server/request/headers';
|
||||
export * from '../server/request/draft-mode';
|
||||
|
||||
//# sourceMappingURL=headers.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../../../src/api/headers.ts"],"sourcesContent":["export * from '../server/request/cookies'\nexport * from '../server/request/headers'\nexport * from '../server/request/draft-mode'\n"],"names":[],"mappings":"AAAA,cAAc,4BAA2B;AACzC,cAAc,4BAA2B;AACzC,cAAc,+BAA8B","ignoreList":[0]}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
export { default } from '../shared/lib/image-external';
|
||||
export * from '../shared/lib/image-external';
|
||||
|
||||
//# sourceMappingURL=image.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../../../src/api/image.ts"],"sourcesContent":["export { default } from '../shared/lib/image-external'\nexport * from '../shared/lib/image-external'\n"],"names":["default"],"mappings":"AAAA,SAASA,OAAO,QAAQ,+BAA8B;AACtD,cAAc,+BAA8B","ignoreList":[0]}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
export { default } from '../client/link';
|
||||
export * from '../client/link';
|
||||
|
||||
//# sourceMappingURL=link.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../../../src/api/link.ts"],"sourcesContent":["export { default } from '../client/link'\nexport * from '../client/link'\n"],"names":["default"],"mappings":"AAAA,SAASA,OAAO,QAAQ,iBAAgB;AACxC,cAAc,iBAAgB","ignoreList":[0]}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
export * from '../client/components/navigation';
|
||||
|
||||
//# sourceMappingURL=navigation.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../../../src/api/navigation.ts"],"sourcesContent":["export * from '../client/components/navigation'\n"],"names":[],"mappings":"AAAA,cAAc,kCAAiC","ignoreList":[0]}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
export * from '../client/components/navigation.react-server';
|
||||
|
||||
//# sourceMappingURL=navigation.react-server.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../../../src/api/navigation.react-server.ts"],"sourcesContent":["export * from '../client/components/navigation.react-server'\n"],"names":[],"mappings":"AAAA,cAAc,+CAA8C","ignoreList":[0]}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
export * from '../server/og/image-response';
|
||||
|
||||
//# sourceMappingURL=og.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../../../src/api/og.ts"],"sourcesContent":["export * from '../server/og/image-response'\n"],"names":[],"mappings":"AAAA,cAAc,8BAA6B","ignoreList":[0]}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
export { default } from '../client/router';
|
||||
export * from '../client/router';
|
||||
|
||||
//# sourceMappingURL=router.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../../../src/api/router.ts"],"sourcesContent":["export { default } from '../client/router'\nexport * from '../client/router'\n"],"names":["default"],"mappings":"AAAA,SAASA,OAAO,QAAQ,mBAAkB;AAC1C,cAAc,mBAAkB","ignoreList":[0]}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
export { default } from '../client/script';
|
||||
export * from '../client/script';
|
||||
|
||||
//# sourceMappingURL=script.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../../../src/api/script.ts"],"sourcesContent":["export { default } from '../client/script'\nexport * from '../client/script'\n"],"names":["default"],"mappings":"AAAA,SAASA,OAAO,QAAQ,mBAAkB;AAC1C,cAAc,mBAAkB","ignoreList":[0]}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
export * from '../server/web/exports/index';
|
||||
|
||||
//# sourceMappingURL=server.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../../../src/api/server.ts"],"sourcesContent":["export * from '../server/web/exports/index'\n"],"names":[],"mappings":"AAAA,cAAc,8BAA6B","ignoreList":[0]}
|
||||
+1253
File diff suppressed because it is too large
Load Diff
+1
File diff suppressed because one or more lines are too long
+14
@@ -0,0 +1,14 @@
|
||||
// This is a minimal import that initializes the node
|
||||
// environment, it is traced automatically for entries
|
||||
// and can be used to ensure Node.js APIs are setup
|
||||
// as expected without require `next-server`
|
||||
if (process.env.NEXT_RUNTIME !== 'edge') {
|
||||
// eslint-disable-next-line @next/internal/typechecked-require
|
||||
require('next/dist/server/node-environment');
|
||||
// eslint-disable-next-line @next/internal/typechecked-require
|
||||
require('next/dist/server/require-hook');
|
||||
// eslint-disable-next-line @next/internal/typechecked-require
|
||||
require('next/dist/server/node-polyfill-crypto');
|
||||
}
|
||||
|
||||
//# sourceMappingURL=setup-node-env.external.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../../../../src/build/adapter/setup-node-env.external.ts"],"sourcesContent":["// This is a minimal import that initializes the node\n// environment, it is traced automatically for entries\n// and can be used to ensure Node.js APIs are setup\n// as expected without require `next-server`\nif (process.env.NEXT_RUNTIME !== 'edge') {\n // eslint-disable-next-line @next/internal/typechecked-require\n require('next/dist/server/node-environment')\n // eslint-disable-next-line @next/internal/typechecked-require\n require('next/dist/server/require-hook')\n // eslint-disable-next-line @next/internal/typechecked-require\n require('next/dist/server/node-polyfill-crypto')\n}\n"],"names":["process","env","NEXT_RUNTIME","require"],"mappings":"AAAA,qDAAqD;AACrD,sDAAsD;AACtD,mDAAmD;AACnD,4CAA4C;AAC5C,IAAIA,QAAQC,GAAG,CAACC,YAAY,KAAK,QAAQ;IACvC,8DAA8D;IAC9DC,QAAQ;IACR,8DAA8D;IAC9DA,QAAQ;IACR,8DAA8D;IAC9DA,QAAQ;AACV","ignoreList":[0]}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
import * as Log from './output/log';
|
||||
import createSpinner from './spinner';
|
||||
import isError from '../lib/is-error';
|
||||
import { EVENT_BUILD_FEATURE_USAGE } from '../telemetry/events/build';
|
||||
import { hrtimeBigIntDurationToString } from './duration-to-string';
|
||||
// TODO: refactor this to account for more compiler lifecycle events
|
||||
// such as beforeProductionBuild, but for now this is the only one that is needed
|
||||
export async function runAfterProductionCompile({ config, buildSpan, telemetry, metadata }) {
|
||||
const run = config.compiler.runAfterProductionCompile;
|
||||
if (!run) {
|
||||
return;
|
||||
}
|
||||
telemetry.record([
|
||||
{
|
||||
eventName: EVENT_BUILD_FEATURE_USAGE,
|
||||
payload: {
|
||||
featureName: 'runAfterProductionCompile',
|
||||
invocationCount: 1
|
||||
}
|
||||
}
|
||||
]);
|
||||
const afterBuildSpinner = createSpinner('Running next.config.js provided runAfterProductionCompile');
|
||||
try {
|
||||
const startTime = process.hrtime.bigint();
|
||||
await buildSpan.traceChild('after-production-compile').traceAsyncFn(async ()=>{
|
||||
await run(metadata);
|
||||
});
|
||||
const duration = process.hrtime.bigint() - startTime;
|
||||
const formattedDuration = hrtimeBigIntDurationToString(duration);
|
||||
Log.event(`Completed runAfterProductionCompile in ${formattedDuration}`);
|
||||
} catch (err) {
|
||||
// Handle specific known errors differently if needed
|
||||
if (isError(err)) {
|
||||
Log.error(`Failed to run runAfterProductionCompile: ${err.message}`);
|
||||
}
|
||||
throw err;
|
||||
} finally{
|
||||
afterBuildSpinner == null ? void 0 : afterBuildSpinner.stop();
|
||||
}
|
||||
}
|
||||
|
||||
//# sourceMappingURL=after-production-compile.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../../../src/build/after-production-compile.ts"],"sourcesContent":["import type { NextConfigComplete } from '../server/config-shared'\nimport type { Span } from '../trace'\n\nimport * as Log from './output/log'\nimport createSpinner from './spinner'\nimport isError from '../lib/is-error'\nimport type { Telemetry } from '../telemetry/storage'\nimport { EVENT_BUILD_FEATURE_USAGE } from '../telemetry/events/build'\nimport { hrtimeBigIntDurationToString } from './duration-to-string'\n\n// TODO: refactor this to account for more compiler lifecycle events\n// such as beforeProductionBuild, but for now this is the only one that is needed\nexport async function runAfterProductionCompile({\n config,\n buildSpan,\n telemetry,\n metadata,\n}: {\n config: NextConfigComplete\n buildSpan: Span\n telemetry: Telemetry\n metadata: {\n projectDir: string\n distDir: string\n }\n}): Promise<void> {\n const run = config.compiler.runAfterProductionCompile\n if (!run) {\n return\n }\n telemetry.record([\n {\n eventName: EVENT_BUILD_FEATURE_USAGE,\n payload: {\n featureName: 'runAfterProductionCompile',\n invocationCount: 1,\n },\n },\n ])\n const afterBuildSpinner = createSpinner(\n 'Running next.config.js provided runAfterProductionCompile'\n )\n\n try {\n const startTime = process.hrtime.bigint()\n await buildSpan\n .traceChild('after-production-compile')\n .traceAsyncFn(async () => {\n await run(metadata)\n })\n const duration = process.hrtime.bigint() - startTime\n const formattedDuration = hrtimeBigIntDurationToString(duration)\n Log.event(`Completed runAfterProductionCompile in ${formattedDuration}`)\n } catch (err) {\n // Handle specific known errors differently if needed\n if (isError(err)) {\n Log.error(`Failed to run runAfterProductionCompile: ${err.message}`)\n }\n\n throw err\n } finally {\n afterBuildSpinner?.stop()\n }\n}\n"],"names":["Log","createSpinner","isError","EVENT_BUILD_FEATURE_USAGE","hrtimeBigIntDurationToString","runAfterProductionCompile","config","buildSpan","telemetry","metadata","run","compiler","record","eventName","payload","featureName","invocationCount","afterBuildSpinner","startTime","process","hrtime","bigint","traceChild","traceAsyncFn","duration","formattedDuration","event","err","error","message","stop"],"mappings":"AAGA,YAAYA,SAAS,eAAc;AACnC,OAAOC,mBAAmB,YAAW;AACrC,OAAOC,aAAa,kBAAiB;AAErC,SAASC,yBAAyB,QAAQ,4BAA2B;AACrE,SAASC,4BAA4B,QAAQ,uBAAsB;AAEnE,oEAAoE;AACpE,iFAAiF;AACjF,OAAO,eAAeC,0BAA0B,EAC9CC,MAAM,EACNC,SAAS,EACTC,SAAS,EACTC,QAAQ,EAST;IACC,MAAMC,MAAMJ,OAAOK,QAAQ,CAACN,yBAAyB;IACrD,IAAI,CAACK,KAAK;QACR;IACF;IACAF,UAAUI,MAAM,CAAC;QACf;YACEC,WAAWV;YACXW,SAAS;gBACPC,aAAa;gBACbC,iBAAiB;YACnB;QACF;KACD;IACD,MAAMC,oBAAoBhB,cACxB;IAGF,IAAI;QACF,MAAMiB,YAAYC,QAAQC,MAAM,CAACC,MAAM;QACvC,MAAMd,UACHe,UAAU,CAAC,4BACXC,YAAY,CAAC;YACZ,MAAMb,IAAID;QACZ;QACF,MAAMe,WAAWL,QAAQC,MAAM,CAACC,MAAM,KAAKH;QAC3C,MAAMO,oBAAoBrB,6BAA6BoB;QACvDxB,IAAI0B,KAAK,CAAC,CAAC,uCAAuC,EAAED,mBAAmB;IACzE,EAAE,OAAOE,KAAK;QACZ,qDAAqD;QACrD,IAAIzB,QAAQyB,MAAM;YAChB3B,IAAI4B,KAAK,CAAC,CAAC,yCAAyC,EAAED,IAAIE,OAAO,EAAE;QACrE;QAEA,MAAMF;IACR,SAAU;QACRV,qCAAAA,kBAAmBa,IAAI;IACzB;AACF","ignoreList":[0]}
|
||||
+224
@@ -0,0 +1,224 @@
|
||||
function isExportDeclaration(node) {
|
||||
return node.type === 'ExportDeclaration';
|
||||
}
|
||||
function isVariableDeclaration(node) {
|
||||
return node.type === 'VariableDeclaration';
|
||||
}
|
||||
function isIdentifier(node) {
|
||||
return node.type === 'Identifier';
|
||||
}
|
||||
function isBooleanLiteral(node) {
|
||||
return node.type === 'BooleanLiteral';
|
||||
}
|
||||
function isNullLiteral(node) {
|
||||
return node.type === 'NullLiteral';
|
||||
}
|
||||
function isStringLiteral(node) {
|
||||
return node.type === 'StringLiteral';
|
||||
}
|
||||
function isNumericLiteral(node) {
|
||||
return node.type === 'NumericLiteral';
|
||||
}
|
||||
function isArrayExpression(node) {
|
||||
return node.type === 'ArrayExpression';
|
||||
}
|
||||
function isObjectExpression(node) {
|
||||
return node.type === 'ObjectExpression';
|
||||
}
|
||||
function isKeyValueProperty(node) {
|
||||
return node.type === 'KeyValueProperty';
|
||||
}
|
||||
function isRegExpLiteral(node) {
|
||||
return node.type === 'RegExpLiteral';
|
||||
}
|
||||
function isTemplateLiteral(node) {
|
||||
return node.type === 'TemplateLiteral';
|
||||
}
|
||||
function isTsSatisfiesExpression(node) {
|
||||
return node.type === 'TsSatisfiesExpression';
|
||||
}
|
||||
/** Formats a path array like `["config", "runtime", "[0]", "value"]` → `"config.runtime[0].value"` */ function formatCodePath(paths) {
|
||||
if (!paths) return undefined;
|
||||
let codePath = '';
|
||||
for (const path of paths){
|
||||
if (path[0] === '[') {
|
||||
// "array" + "[0]"
|
||||
codePath += path;
|
||||
} else if (codePath === '') {
|
||||
codePath = path;
|
||||
} else {
|
||||
// "object" + ".key"
|
||||
codePath += `.${path}`;
|
||||
}
|
||||
}
|
||||
return codePath;
|
||||
}
|
||||
function extractValue(node, path) {
|
||||
if (isNullLiteral(node)) {
|
||||
return {
|
||||
value: null
|
||||
};
|
||||
} else if (isBooleanLiteral(node)) {
|
||||
// e.g. true / false
|
||||
return {
|
||||
value: node.value
|
||||
};
|
||||
} else if (isStringLiteral(node)) {
|
||||
// e.g. "abc"
|
||||
return {
|
||||
value: node.value
|
||||
};
|
||||
} else if (isNumericLiteral(node)) {
|
||||
// e.g. 123
|
||||
return {
|
||||
value: node.value
|
||||
};
|
||||
} else if (isRegExpLiteral(node)) {
|
||||
// e.g. /abc/i
|
||||
return {
|
||||
value: new RegExp(node.pattern, node.flags)
|
||||
};
|
||||
} else if (isIdentifier(node)) {
|
||||
switch(node.value){
|
||||
case 'undefined':
|
||||
return {
|
||||
value: undefined
|
||||
};
|
||||
default:
|
||||
return {
|
||||
unsupported: `Unknown identifier "${node.value}"`,
|
||||
path: formatCodePath(path)
|
||||
};
|
||||
}
|
||||
} else if (isArrayExpression(node)) {
|
||||
// e.g. [1, 2, 3]
|
||||
const arr = [];
|
||||
for(let i = 0, len = node.elements.length; i < len; i++){
|
||||
const elem = node.elements[i];
|
||||
if (elem) {
|
||||
if (elem.spread) {
|
||||
// e.g. [ ...a ]
|
||||
return {
|
||||
unsupported: 'Unsupported spread operator in the Array Expression',
|
||||
path: formatCodePath(path)
|
||||
};
|
||||
}
|
||||
const result = extractValue(elem.expression, path && [
|
||||
...path,
|
||||
`[${i}]`
|
||||
]);
|
||||
if ('unsupported' in result) return result;
|
||||
arr.push(result.value);
|
||||
} else {
|
||||
// e.g. [1, , 2]
|
||||
// ^^
|
||||
arr.push(undefined);
|
||||
}
|
||||
}
|
||||
return {
|
||||
value: arr
|
||||
};
|
||||
} else if (isObjectExpression(node)) {
|
||||
// e.g. { a: 1, b: 2 }
|
||||
const obj = {};
|
||||
for (const prop of node.properties){
|
||||
if (!isKeyValueProperty(prop)) {
|
||||
// e.g. { ...a }
|
||||
return {
|
||||
unsupported: 'Unsupported spread operator in the Object Expression',
|
||||
path: formatCodePath(path)
|
||||
};
|
||||
}
|
||||
let key;
|
||||
if (isIdentifier(prop.key)) {
|
||||
// e.g. { a: 1, b: 2 }
|
||||
key = prop.key.value;
|
||||
} else if (isStringLiteral(prop.key)) {
|
||||
// e.g. { "a": 1, "b": 2 }
|
||||
key = prop.key.value;
|
||||
} else {
|
||||
return {
|
||||
unsupported: `Unsupported key type "${prop.key.type}" in the Object Expression`,
|
||||
path: formatCodePath(path)
|
||||
};
|
||||
}
|
||||
const result = extractValue(prop.value, path && [
|
||||
...path,
|
||||
key
|
||||
]);
|
||||
if ('unsupported' in result) return result;
|
||||
obj[key] = result.value;
|
||||
}
|
||||
return {
|
||||
value: obj
|
||||
};
|
||||
} else if (isTemplateLiteral(node)) {
|
||||
// e.g. `abc`
|
||||
if (node.expressions.length !== 0) {
|
||||
// TODO: should we add support for `${'e'}d${'g'}'e'`?
|
||||
return {
|
||||
unsupported: 'Unsupported template literal with expressions',
|
||||
path: formatCodePath(path)
|
||||
};
|
||||
}
|
||||
// When TemplateLiteral has 0 expressions, the length of quasis is always 1.
|
||||
// Because when parsing TemplateLiteral, the parser yields the first quasi,
|
||||
// then the first expression, then the next quasi, then the next expression, etc.,
|
||||
// until the last quasi.
|
||||
// Thus if there is no expression, the parser ends at the frst and also last quasis
|
||||
//
|
||||
// A "cooked" interpretation where backslashes have special meaning, while a
|
||||
// "raw" interpretation where backslashes do not have special meaning
|
||||
// https://exploringjs.com/impatient-js/ch_template-literals.html#template-strings-cooked-vs-raw
|
||||
const [{ cooked, raw }] = node.quasis;
|
||||
return {
|
||||
value: cooked ?? raw
|
||||
};
|
||||
} else if (isTsSatisfiesExpression(node)) {
|
||||
return extractValue(node.expression);
|
||||
} else {
|
||||
return {
|
||||
unsupported: `Unsupported node type "${node.type}"`,
|
||||
path: formatCodePath(path)
|
||||
};
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Extracts the value of an exported const variable named `exportedName`
|
||||
* (e.g. "export const config = { runtime: 'edge' }") from swc's AST.
|
||||
* The value must be one of (or returns unsupported):
|
||||
* - string
|
||||
* - boolean
|
||||
* - number
|
||||
* - null
|
||||
* - undefined
|
||||
* - array containing values listed in this list
|
||||
* - object containing values listed in this list
|
||||
*
|
||||
* Returns null if the declaration is not found.
|
||||
* Returns { unsupported, path? } if the value contains unsupported nodes.
|
||||
*/ export function extractExportedConstValue(module, exportedName) {
|
||||
if (!module) return null;
|
||||
for (const moduleItem of module.body){
|
||||
if (!isExportDeclaration(moduleItem)) {
|
||||
continue;
|
||||
}
|
||||
const declaration = moduleItem.declaration;
|
||||
if (!isVariableDeclaration(declaration)) {
|
||||
continue;
|
||||
}
|
||||
if (declaration.kind !== 'const') {
|
||||
continue;
|
||||
}
|
||||
for (const decl of declaration.declarations){
|
||||
if (isIdentifier(decl.id) && decl.id.value === exportedName && decl.init) {
|
||||
return extractValue(decl.init, [
|
||||
exportedName
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
//# sourceMappingURL=extract-const-value.js.map
|
||||
+1
File diff suppressed because one or more lines are too long
+558
@@ -0,0 +1,558 @@
|
||||
import { readFileSync } from 'fs';
|
||||
import { relative } from 'path';
|
||||
import { LRUCache } from '../../server/lib/lru-cache';
|
||||
import { extractExportedConstValue } from './extract-const-value';
|
||||
import { parseModule } from './parse-module';
|
||||
import * as Log from '../output/log';
|
||||
import { SERVER_RUNTIME, MIDDLEWARE_FILENAME, PROXY_FILENAME } from '../../lib/constants';
|
||||
import { tryToParsePath } from '../../lib/try-to-parse-path';
|
||||
import { isAPIRoute } from '../../lib/is-api-route';
|
||||
import { isEdgeRuntime } from '../../lib/is-edge-runtime';
|
||||
import { RSC_MODULE_TYPES } from '../../shared/lib/constants';
|
||||
import { PAGE_TYPES } from '../../lib/page-types';
|
||||
import { AppSegmentConfigSchemaKeys, parseAppSegmentConfig } from '../segment-config/app/app-segment-config';
|
||||
import { reportZodError } from '../../shared/lib/zod';
|
||||
import { PagesSegmentConfigSchemaKeys, parsePagesSegmentConfig } from '../segment-config/pages/pages-segment-config';
|
||||
import { MiddlewareConfigInputSchema, SourceSchema } from '../segment-config/middleware/middleware-config';
|
||||
import { normalizeAppPath } from '../../shared/lib/router/utils/app-paths';
|
||||
import { normalizePagePath } from '../../shared/lib/page-path/normalize-page-path';
|
||||
import { isProxyFile } from '../utils';
|
||||
const PARSE_PATTERN = /(?<!(_jsx|jsx-))runtime|preferredRegion|getStaticProps|getServerSideProps|generateStaticParams|export const|generateImageMetadata|generateSitemaps|middleware|proxy/;
|
||||
const CLIENT_MODULE_LABEL = /\/\* __next_internal_client_entry_do_not_use__ ([^ ]*) (cjs|auto) \*\//;
|
||||
// Match JSON object that may contain nested objects (for loc info)
|
||||
// The JSON ends right before the closing " */"
|
||||
const ACTION_MODULE_LABEL = /\/\* __next_internal_action_entry_do_not_use__ (\{.*\}) \*\//;
|
||||
const CLIENT_DIRECTIVE = 'use client';
|
||||
const SERVER_ACTION_DIRECTIVE = 'use server';
|
||||
export function getRSCModuleInformation(source, isReactServerLayer) {
|
||||
const actionsJson = source.match(ACTION_MODULE_LABEL);
|
||||
// Parse action metadata - supports both old format (string) and new format (object with loc)
|
||||
const parsedActionsMeta = actionsJson ? JSON.parse(actionsJson[1]) : undefined;
|
||||
const clientInfoMatch = source.match(CLIENT_MODULE_LABEL);
|
||||
const isClientRef = !!clientInfoMatch;
|
||||
if (!isReactServerLayer) {
|
||||
return {
|
||||
type: RSC_MODULE_TYPES.client,
|
||||
actionIds: parsedActionsMeta,
|
||||
isClientRef
|
||||
};
|
||||
}
|
||||
const clientRefsString = clientInfoMatch == null ? void 0 : clientInfoMatch[1];
|
||||
const clientRefs = clientRefsString ? clientRefsString.split(',') : [];
|
||||
const clientEntryType = clientInfoMatch == null ? void 0 : clientInfoMatch[2];
|
||||
const type = clientInfoMatch ? RSC_MODULE_TYPES.client : RSC_MODULE_TYPES.server;
|
||||
return {
|
||||
type,
|
||||
actionIds: parsedActionsMeta,
|
||||
clientRefs,
|
||||
clientEntryType,
|
||||
isClientRef
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Receives a parsed AST from SWC and checks if it belongs to a module that
|
||||
* requires a runtime to be specified. Those are:
|
||||
* - Modules with `export function getStaticProps | getServerSideProps`
|
||||
* - Modules with `export { getStaticProps | getServerSideProps } <from ...>`
|
||||
* - Modules with `export const runtime = ...`
|
||||
*/ function checkExports(ast, expectedExports, page) {
|
||||
const exportsSet = new Set([
|
||||
'getStaticProps',
|
||||
'getServerSideProps',
|
||||
'generateImageMetadata',
|
||||
'generateSitemaps',
|
||||
'generateStaticParams'
|
||||
]);
|
||||
if (!Array.isArray(ast == null ? void 0 : ast.body)) {
|
||||
return {};
|
||||
}
|
||||
try {
|
||||
let getStaticProps = false;
|
||||
let getServerSideProps = false;
|
||||
let generateImageMetadata = false;
|
||||
let generateSitemaps = false;
|
||||
let generateStaticParams = false;
|
||||
let exports = new Set();
|
||||
let directives = new Set();
|
||||
let hasLeadingNonDirectiveNode = false;
|
||||
for (const node of ast.body){
|
||||
var _node_declaration, _node_declaration1, _node_declaration_identifier, _node_declaration2;
|
||||
// There should be no non-string literals nodes before directives
|
||||
if (node.type === 'ExpressionStatement' && node.expression.type === 'StringLiteral') {
|
||||
if (!hasLeadingNonDirectiveNode) {
|
||||
const directive = node.expression.value;
|
||||
if (CLIENT_DIRECTIVE === directive) {
|
||||
directives.add('client');
|
||||
}
|
||||
if (SERVER_ACTION_DIRECTIVE === directive) {
|
||||
directives.add('server');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
hasLeadingNonDirectiveNode = true;
|
||||
}
|
||||
if (node.type === 'ExportDeclaration' && ((_node_declaration = node.declaration) == null ? void 0 : _node_declaration.type) === 'VariableDeclaration') {
|
||||
var _node_declaration3;
|
||||
for (const declaration of (_node_declaration3 = node.declaration) == null ? void 0 : _node_declaration3.declarations){
|
||||
if (expectedExports.includes(declaration.id.value)) {
|
||||
exports.add(declaration.id.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (node.type === 'ExportDeclaration' && ((_node_declaration1 = node.declaration) == null ? void 0 : _node_declaration1.type) === 'FunctionDeclaration' && exportsSet.has((_node_declaration_identifier = node.declaration.identifier) == null ? void 0 : _node_declaration_identifier.value)) {
|
||||
const id = node.declaration.identifier.value;
|
||||
getServerSideProps = id === 'getServerSideProps';
|
||||
getStaticProps = id === 'getStaticProps';
|
||||
generateImageMetadata = id === 'generateImageMetadata';
|
||||
generateSitemaps = id === 'generateSitemaps';
|
||||
generateStaticParams = id === 'generateStaticParams';
|
||||
}
|
||||
if (node.type === 'ExportDeclaration' && ((_node_declaration2 = node.declaration) == null ? void 0 : _node_declaration2.type) === 'VariableDeclaration') {
|
||||
var _node_declaration_declarations_, _node_declaration4;
|
||||
const id = (_node_declaration4 = node.declaration) == null ? void 0 : (_node_declaration_declarations_ = _node_declaration4.declarations[0]) == null ? void 0 : _node_declaration_declarations_.id.value;
|
||||
if (exportsSet.has(id)) {
|
||||
getServerSideProps = id === 'getServerSideProps';
|
||||
getStaticProps = id === 'getStaticProps';
|
||||
generateImageMetadata = id === 'generateImageMetadata';
|
||||
generateSitemaps = id === 'generateSitemaps';
|
||||
generateStaticParams = id === 'generateStaticParams';
|
||||
}
|
||||
}
|
||||
if (node.type === 'ExportNamedDeclaration') {
|
||||
for (const specifier of node.specifiers){
|
||||
var _specifier_orig;
|
||||
if (specifier.type === 'ExportSpecifier' && ((_specifier_orig = specifier.orig) == null ? void 0 : _specifier_orig.type) === 'Identifier') {
|
||||
const value = specifier.orig.value;
|
||||
if (!getServerSideProps && value === 'getServerSideProps') {
|
||||
getServerSideProps = true;
|
||||
}
|
||||
if (!getStaticProps && value === 'getStaticProps') {
|
||||
getStaticProps = true;
|
||||
}
|
||||
if (!generateImageMetadata && value === 'generateImageMetadata') {
|
||||
generateImageMetadata = true;
|
||||
}
|
||||
if (!generateSitemaps && value === 'generateSitemaps') {
|
||||
generateSitemaps = true;
|
||||
}
|
||||
if (!generateStaticParams && value === 'generateStaticParams') {
|
||||
generateStaticParams = true;
|
||||
}
|
||||
if (expectedExports.includes(value) && !exports.has(value)) {
|
||||
// An export was found that was actually a re-export, and not a
|
||||
// literal value. We should warn here.
|
||||
Log.warn(`Next.js can't recognize the exported \`${value}\` field in "${page}", it may be re-exported from another file. The default config will be used instead.`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
getStaticProps,
|
||||
getServerSideProps,
|
||||
generateImageMetadata,
|
||||
generateSitemaps,
|
||||
generateStaticParams,
|
||||
directives,
|
||||
exports
|
||||
};
|
||||
} catch {}
|
||||
return {};
|
||||
}
|
||||
function validateMiddlewareProxyExports({ ast, page, pageFilePath, isDev }) {
|
||||
// Check if this is middleware/proxy
|
||||
const isMiddleware = page === `/${MIDDLEWARE_FILENAME}` || page === `/src/${MIDDLEWARE_FILENAME}`;
|
||||
const isProxy = page === `/${PROXY_FILENAME}` || page === `/src/${PROXY_FILENAME}`;
|
||||
if (!isMiddleware && !isProxy) {
|
||||
return;
|
||||
}
|
||||
if (!ast || !Array.isArray(ast.body)) {
|
||||
return;
|
||||
}
|
||||
const fileName = isProxy ? PROXY_FILENAME : MIDDLEWARE_FILENAME;
|
||||
// Parse AST to get export info (since checkExports doesn't return middleware/proxy info)
|
||||
let hasDefaultExport = false;
|
||||
let hasMiddlewareExport = false;
|
||||
let hasProxyExport = false;
|
||||
for (const node of ast.body){
|
||||
var _node_declaration, _node_declaration1;
|
||||
if (node.type === 'ExportDefaultDeclaration' || node.type === 'ExportDefaultExpression') {
|
||||
hasDefaultExport = true;
|
||||
}
|
||||
if (node.type === 'ExportDeclaration' && ((_node_declaration = node.declaration) == null ? void 0 : _node_declaration.type) === 'FunctionDeclaration') {
|
||||
var _node_declaration_identifier;
|
||||
const id = (_node_declaration_identifier = node.declaration.identifier) == null ? void 0 : _node_declaration_identifier.value;
|
||||
if (id === 'middleware') {
|
||||
hasMiddlewareExport = true;
|
||||
}
|
||||
if (id === 'proxy') {
|
||||
hasProxyExport = true;
|
||||
}
|
||||
}
|
||||
if (node.type === 'ExportDeclaration' && ((_node_declaration1 = node.declaration) == null ? void 0 : _node_declaration1.type) === 'VariableDeclaration') {
|
||||
var _node_declaration_declarations_, _node_declaration2;
|
||||
const id = (_node_declaration2 = node.declaration) == null ? void 0 : (_node_declaration_declarations_ = _node_declaration2.declarations[0]) == null ? void 0 : _node_declaration_declarations_.id.value;
|
||||
if (id === 'middleware') {
|
||||
hasMiddlewareExport = true;
|
||||
}
|
||||
if (id === 'proxy') {
|
||||
hasProxyExport = true;
|
||||
}
|
||||
}
|
||||
if (node.type === 'ExportNamedDeclaration') {
|
||||
for (const specifier of node.specifiers){
|
||||
var _specifier_orig;
|
||||
if (specifier.type === 'ExportSpecifier' && ((_specifier_orig = specifier.orig) == null ? void 0 : _specifier_orig.type) === 'Identifier') {
|
||||
// Use the exported name if it exists (for aliased exports like `export { foo as proxy }`),
|
||||
// otherwise fall back to the original name (for simple re-exports like `export { proxy }`)
|
||||
const exportedIdentifier = specifier.exported || specifier.orig;
|
||||
const value = exportedIdentifier.value;
|
||||
if (value === 'middleware') {
|
||||
hasMiddlewareExport = true;
|
||||
}
|
||||
if (value === 'proxy') {
|
||||
hasProxyExport = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
const hasValidExport = hasDefaultExport || isMiddleware && hasMiddlewareExport || isProxy && hasProxyExport;
|
||||
const relativePath = relative(process.cwd(), pageFilePath);
|
||||
const resolvedPath = relativePath.startsWith('.') ? relativePath : `./${relativePath}`;
|
||||
if (!hasValidExport) {
|
||||
const message = `The file "${resolvedPath}" must export a function, either as a default export or as a named "${fileName}" export.\n` + `This function is what Next.js runs for every request handled by this ${fileName === 'proxy' ? 'proxy (previously called middleware)' : 'middleware'}.\n\n` + `Why this happens:\n` + (isProxy ? "- You are migrating from `middleware` to `proxy`, but haven't updated the exported function.\n" : '') + `- The file exists but doesn't export a function.\n` + `- The export is not a function (e.g., an object or constant).\n` + `- There's a syntax error preventing the export from being recognized.\n\n` + `To fix it:\n` + `- Ensure this file has either a default or "${fileName}" function export.\n\n` + `Learn more: https://nextjs.org/docs/messages/middleware-to-proxy`;
|
||||
if (isDev) {
|
||||
// errorOnce as proxy/middleware runs per request including multiple
|
||||
// internal _next/ routes and spams logs.
|
||||
Log.errorOnce(message);
|
||||
} else {
|
||||
throw Object.defineProperty(new Error(message), "__NEXT_ERROR_CODE", {
|
||||
value: "E903",
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
function tryToReadFile(filePath, shouldThrow) {
|
||||
try {
|
||||
return readFileSync(filePath, {
|
||||
encoding: 'utf8'
|
||||
});
|
||||
} catch (error) {
|
||||
if (shouldThrow) {
|
||||
error.message = `Next.js ERROR: Failed to read file ${filePath}:\n${error.message}`;
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @internal - required to exclude zod types from the build
|
||||
*/ export function getMiddlewareMatchers(matcherOrMatchers, nextConfig) {
|
||||
const matchers = Array.isArray(matcherOrMatchers) ? matcherOrMatchers : [
|
||||
matcherOrMatchers
|
||||
];
|
||||
const { i18n } = nextConfig;
|
||||
return matchers.map((matcher)=>{
|
||||
matcher = typeof matcher === 'string' ? {
|
||||
source: matcher
|
||||
} : matcher;
|
||||
const originalSource = matcher.source;
|
||||
let { source, ...rest } = matcher;
|
||||
const isRoot = source === '/';
|
||||
if ((i18n == null ? void 0 : i18n.locales) && matcher.locale !== false) {
|
||||
source = `/:nextInternalLocale((?!_next/)[^/.]{1,})${isRoot ? '' : source}`;
|
||||
}
|
||||
source = `/:nextData(_next/data/[^/]{1,})?${source}${isRoot ? `(${nextConfig.i18n ? '|\\.json|' : ''}/?index|/?index\\.json)?` : '{(\\.json)}?'}`;
|
||||
if (nextConfig.basePath) {
|
||||
source = `${nextConfig.basePath}${source}`;
|
||||
}
|
||||
// Validate that the source is still.
|
||||
const result = SourceSchema.safeParse(source);
|
||||
if (!result.success) {
|
||||
reportZodError('Failed to parse middleware source', result.error);
|
||||
// We need to exit here because middleware being built occurs before we
|
||||
// finish setting up the server. Exiting here is the only way to ensure
|
||||
// that we don't hang.
|
||||
process.exit(1);
|
||||
}
|
||||
return {
|
||||
...rest,
|
||||
// We know that parsed.regexStr is not undefined because we already
|
||||
// checked that the source is valid.
|
||||
regexp: tryToParsePath(result.data).regexStr,
|
||||
originalSource: originalSource || source
|
||||
};
|
||||
});
|
||||
}
|
||||
function parseMiddlewareConfig(page, rawConfig, nextConfig) {
|
||||
// If there's no config to parse, then return nothing.
|
||||
if (typeof rawConfig !== 'object' || !rawConfig) return {};
|
||||
const input = MiddlewareConfigInputSchema.safeParse(rawConfig);
|
||||
if (!input.success) {
|
||||
reportZodError(`${page} contains invalid middleware config`, input.error);
|
||||
// We need to exit here because middleware being built occurs before we
|
||||
// finish setting up the server. Exiting here is the only way to ensure
|
||||
// that we don't hang.
|
||||
process.exit(1);
|
||||
}
|
||||
const config = {};
|
||||
if (input.data.matcher) {
|
||||
config.matchers = getMiddlewareMatchers(input.data.matcher, nextConfig);
|
||||
}
|
||||
if (input.data.unstable_allowDynamic) {
|
||||
config.unstable_allowDynamic = Array.isArray(input.data.unstable_allowDynamic) ? input.data.unstable_allowDynamic : [
|
||||
input.data.unstable_allowDynamic
|
||||
];
|
||||
}
|
||||
if (input.data.regions) {
|
||||
config.regions = input.data.regions;
|
||||
}
|
||||
return config;
|
||||
}
|
||||
const apiRouteWarnings = new LRUCache(250);
|
||||
function warnAboutExperimentalEdge(apiRoute) {
|
||||
if (process.env.NODE_ENV === 'production' && process.env.NEXT_PRIVATE_BUILD_WORKER === '1') {
|
||||
return;
|
||||
}
|
||||
if (apiRoute && apiRouteWarnings.has(apiRoute)) {
|
||||
return;
|
||||
}
|
||||
Log.warn(apiRoute ? `${apiRoute} provided runtime 'experimental-edge'. It can be updated to 'edge' instead.` : `You are using an experimental edge runtime, the API might change.`);
|
||||
if (apiRoute) {
|
||||
apiRouteWarnings.set(apiRoute, 1);
|
||||
}
|
||||
}
|
||||
let hadUnsupportedValue = false;
|
||||
const warnedUnsupportedValueMap = new LRUCache(250, ()=>1);
|
||||
function warnAboutUnsupportedValue(pageFilePath, page, result) {
|
||||
hadUnsupportedValue = true;
|
||||
const isProductionBuild = process.env.NODE_ENV === 'production';
|
||||
if (// we only log for the server compilation so it's not
|
||||
// duplicated due to webpack build worker having fresh
|
||||
// module scope for each compiler
|
||||
process.env.NEXT_COMPILER_NAME !== 'server' || isProductionBuild && warnedUnsupportedValueMap.has(pageFilePath)) {
|
||||
return;
|
||||
}
|
||||
warnedUnsupportedValueMap.set(pageFilePath, true);
|
||||
const message = `Next.js can't recognize the exported \`config\` field in ` + (page ? `route "${page}"` : `"${pageFilePath}"`) + ':\n' + result.unsupported + (result.path ? ` at "${result.path}"` : '') + '.\n' + 'Read More - https://nextjs.org/docs/messages/invalid-page-config';
|
||||
// for a build we use `Log.error` instead of throwing
|
||||
// so that all errors can be logged before exiting the process
|
||||
if (isProductionBuild) {
|
||||
Log.error(message);
|
||||
} else {
|
||||
throw Object.defineProperty(new Error(message), "__NEXT_ERROR_CODE", {
|
||||
value: "E1013",
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
}
|
||||
}
|
||||
export async function getAppPageStaticInfo({ pageFilePath, nextConfig, isDev, page }) {
|
||||
const content = tryToReadFile(pageFilePath, !isDev);
|
||||
if (!content || !PARSE_PATTERN.test(content)) {
|
||||
return {
|
||||
type: PAGE_TYPES.APP,
|
||||
config: undefined,
|
||||
runtime: undefined,
|
||||
preferredRegion: undefined,
|
||||
maxDuration: undefined,
|
||||
hadUnsupportedValue: false
|
||||
};
|
||||
}
|
||||
const ast = await parseModule(pageFilePath, content);
|
||||
validateMiddlewareProxyExports({
|
||||
ast,
|
||||
page,
|
||||
pageFilePath,
|
||||
isDev
|
||||
});
|
||||
const { generateStaticParams, generateImageMetadata, generateSitemaps, exports, directives } = checkExports(ast, AppSegmentConfigSchemaKeys, page);
|
||||
const { type: rsc } = getRSCModuleInformation(content, true);
|
||||
const exportedConfig = {};
|
||||
if (exports) {
|
||||
for (const property of exports){
|
||||
const result = extractExportedConstValue(ast, property);
|
||||
if (result !== null && 'unsupported' in result) {
|
||||
warnAboutUnsupportedValue(pageFilePath, page, result);
|
||||
} else if (result !== null) {
|
||||
exportedConfig[property] = result.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
const configResult = extractExportedConstValue(ast, 'config');
|
||||
if (configResult !== null && 'unsupported' in configResult) {
|
||||
warnAboutUnsupportedValue(pageFilePath, page, configResult);
|
||||
} else if (configResult !== null) {
|
||||
exportedConfig.config = configResult.value;
|
||||
}
|
||||
const route = normalizeAppPath(page);
|
||||
const config = parseAppSegmentConfig(exportedConfig, route);
|
||||
// Prevent edge runtime and generateStaticParams in the same file.
|
||||
if (isEdgeRuntime(config.runtime) && generateStaticParams) {
|
||||
throw Object.defineProperty(new Error(`Page "${page}" cannot use both \`export const runtime = 'edge'\` and export \`generateStaticParams\`.`), "__NEXT_ERROR_CODE", {
|
||||
value: "E42",
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
}
|
||||
// Prevent use client and generateStaticParams in the same file.
|
||||
if ((directives == null ? void 0 : directives.has('client')) && generateStaticParams) {
|
||||
throw Object.defineProperty(new Error(`Page "${page}" cannot use both "use client" and export function "generateStaticParams()".`), "__NEXT_ERROR_CODE", {
|
||||
value: "E475",
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
}
|
||||
// Prevent use client and unstable_instant in the same file.
|
||||
if ((directives == null ? void 0 : directives.has('client')) && 'unstable_instant' in config) {
|
||||
throw Object.defineProperty(new Error(`Page "${page}" cannot export "unstable_instant" from a Client Component module. To use this API, convert this module to a Server Component by removing the "use client" directive.`), "__NEXT_ERROR_CODE", {
|
||||
value: "E1075",
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
}
|
||||
if ('unstable_instant' in config && !nextConfig.cacheComponents) {
|
||||
throw Object.defineProperty(new Error(`Page "${page}" cannot use \`export const unstable_instant = ...\` without enabling \`cacheComponents\`.`), "__NEXT_ERROR_CODE", {
|
||||
value: "E990",
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
}
|
||||
// Prevent unstable_dynamicStaleTime in layouts.
|
||||
if ('unstable_dynamicStaleTime' in config) {
|
||||
const isLayout = /\/layout\.[^/]+$/.test(pageFilePath);
|
||||
if (isLayout) {
|
||||
throw Object.defineProperty(new Error(`"${page}" cannot use \`export const unstable_dynamicStaleTime\`. This config is only supported in page files, not layouts.`), "__NEXT_ERROR_CODE", {
|
||||
value: "E1137",
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
}
|
||||
}
|
||||
// Prevent combining unstable_dynamicStaleTime and unstable_instant.
|
||||
if ('unstable_dynamicStaleTime' in config && 'unstable_instant' in config) {
|
||||
throw Object.defineProperty(new Error(`Page "${page}" cannot use both \`export const unstable_dynamicStaleTime\` and \`export const unstable_instant\`.`), "__NEXT_ERROR_CODE", {
|
||||
value: "E1136",
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
}
|
||||
return {
|
||||
type: PAGE_TYPES.APP,
|
||||
rsc,
|
||||
generateImageMetadata,
|
||||
generateSitemaps,
|
||||
generateStaticParams,
|
||||
config,
|
||||
middleware: parseMiddlewareConfig(page, exportedConfig.config, nextConfig),
|
||||
runtime: config.runtime,
|
||||
preferredRegion: config.preferredRegion,
|
||||
maxDuration: config.maxDuration,
|
||||
hadUnsupportedValue
|
||||
};
|
||||
}
|
||||
export async function getPagesPageStaticInfo({ pageFilePath, nextConfig, isDev, page }) {
|
||||
var _config_config, _config_config1, _config_config2;
|
||||
const content = tryToReadFile(pageFilePath, !isDev);
|
||||
if (!content || !PARSE_PATTERN.test(content)) {
|
||||
return {
|
||||
type: PAGE_TYPES.PAGES,
|
||||
config: undefined,
|
||||
runtime: undefined,
|
||||
preferredRegion: undefined,
|
||||
maxDuration: undefined,
|
||||
hadUnsupportedValue: false
|
||||
};
|
||||
}
|
||||
const ast = await parseModule(pageFilePath, content);
|
||||
validateMiddlewareProxyExports({
|
||||
ast,
|
||||
page,
|
||||
pageFilePath,
|
||||
isDev
|
||||
});
|
||||
const { getServerSideProps, getStaticProps, exports } = checkExports(ast, PagesSegmentConfigSchemaKeys, page);
|
||||
const { type: rsc } = getRSCModuleInformation(content, true);
|
||||
const exportedConfig = {};
|
||||
if (exports) {
|
||||
for (const property of exports){
|
||||
const result = extractExportedConstValue(ast, property);
|
||||
if (result !== null && 'unsupported' in result) {
|
||||
warnAboutUnsupportedValue(pageFilePath, page, result);
|
||||
} else if (result !== null) {
|
||||
exportedConfig[property] = result.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
const configResult = extractExportedConstValue(ast, 'config');
|
||||
if (configResult !== null && 'unsupported' in configResult) {
|
||||
warnAboutUnsupportedValue(pageFilePath, page, configResult);
|
||||
} else if (configResult !== null) {
|
||||
exportedConfig.config = configResult.value;
|
||||
}
|
||||
// Validate the config.
|
||||
const route = normalizePagePath(page);
|
||||
const config = parsePagesSegmentConfig(exportedConfig, route);
|
||||
const isAnAPIRoute = isAPIRoute(route);
|
||||
let resolvedRuntime = config.runtime ?? ((_config_config = config.config) == null ? void 0 : _config_config.runtime);
|
||||
if (isProxyFile(page) && resolvedRuntime) {
|
||||
const relativePath = relative(process.cwd(), pageFilePath);
|
||||
const resolvedPath = relativePath.startsWith('.') ? relativePath : `./${relativePath}`;
|
||||
const message = `Route segment config is not allowed in Proxy file at "${resolvedPath}". Proxy always runs on Node.js runtime. Learn more: https://nextjs.org/docs/messages/middleware-to-proxy`;
|
||||
if (isDev) {
|
||||
// errorOnce as proxy/middleware runs per request including multiple
|
||||
// internal _next/ routes and spams logs.
|
||||
Log.errorOnce(message);
|
||||
resolvedRuntime = SERVER_RUNTIME.nodejs;
|
||||
} else {
|
||||
throw Object.defineProperty(new Error(message), "__NEXT_ERROR_CODE", {
|
||||
value: "E1031",
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
}
|
||||
}
|
||||
if (resolvedRuntime === SERVER_RUNTIME.experimentalEdge) {
|
||||
warnAboutExperimentalEdge(isAnAPIRoute ? page : null);
|
||||
}
|
||||
if (!isProxyFile(page) && resolvedRuntime === SERVER_RUNTIME.edge && page && !isAnAPIRoute) {
|
||||
const message = `Page ${page} provided runtime 'edge', the edge runtime for rendering is currently experimental. Use runtime 'experimental-edge' instead.`;
|
||||
if (isDev) {
|
||||
Log.error(message);
|
||||
} else {
|
||||
throw Object.defineProperty(new Error(message), "__NEXT_ERROR_CODE", {
|
||||
value: "E1015",
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
}
|
||||
}
|
||||
return {
|
||||
type: PAGE_TYPES.PAGES,
|
||||
getStaticProps,
|
||||
getServerSideProps,
|
||||
rsc,
|
||||
config,
|
||||
middleware: parseMiddlewareConfig(page, exportedConfig.config, nextConfig),
|
||||
runtime: resolvedRuntime,
|
||||
preferredRegion: (_config_config1 = config.config) == null ? void 0 : _config_config1.regions,
|
||||
maxDuration: config.maxDuration ?? ((_config_config2 = config.config) == null ? void 0 : _config_config2.maxDuration),
|
||||
hadUnsupportedValue
|
||||
};
|
||||
}
|
||||
/**
|
||||
* For a given pageFilePath and nextConfig, if the config supports it, this
|
||||
* function will read the file and return the runtime that should be used.
|
||||
* It will look into the file content only if the page *requires* a runtime
|
||||
* to be specified, that is, when gSSP or gSP is used.
|
||||
* Related discussion: https://github.com/vercel/next.js/discussions/34179
|
||||
*/ export async function getPageStaticInfo(params) {
|
||||
if (params.pageType === PAGE_TYPES.APP) {
|
||||
return getAppPageStaticInfo(params);
|
||||
}
|
||||
return getPagesPageStaticInfo(params);
|
||||
}
|
||||
|
||||
//# sourceMappingURL=get-page-static-info.js.map
|
||||
+1
File diff suppressed because one or more lines are too long
+13
@@ -0,0 +1,13 @@
|
||||
import { LRUCache } from '../../server/lib/lru-cache';
|
||||
import { withPromiseCache } from '../../lib/with-promise-cache';
|
||||
import { createHash } from 'crypto';
|
||||
import { parse } from '../swc';
|
||||
/**
|
||||
* Parses a module with SWC using an LRU cache where the parsed module will
|
||||
* be indexed by a sha of its content holding up to 500 entries.
|
||||
*/ export const parseModule = withPromiseCache(new LRUCache(500), async (filename, content)=>parse(content, {
|
||||
isModule: 'unknown',
|
||||
filename
|
||||
}).catch(()=>null), (_, content)=>createHash('sha1').update(content).digest('hex'));
|
||||
|
||||
//# sourceMappingURL=parse-module.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../../../../src/build/analysis/parse-module.ts"],"sourcesContent":["import { LRUCache } from '../../server/lib/lru-cache'\nimport { withPromiseCache } from '../../lib/with-promise-cache'\nimport { createHash } from 'crypto'\nimport { parse } from '../swc'\n\n/**\n * Parses a module with SWC using an LRU cache where the parsed module will\n * be indexed by a sha of its content holding up to 500 entries.\n */\nexport const parseModule = withPromiseCache(\n new LRUCache<any>(500),\n async (filename: string, content: string) =>\n parse(content, { isModule: 'unknown', filename }).catch(() => null),\n (_, content) => createHash('sha1').update(content).digest('hex')\n)\n"],"names":["LRUCache","withPromiseCache","createHash","parse","parseModule","filename","content","isModule","catch","_","update","digest"],"mappings":"AAAA,SAASA,QAAQ,QAAQ,6BAA4B;AACrD,SAASC,gBAAgB,QAAQ,+BAA8B;AAC/D,SAASC,UAAU,QAAQ,SAAQ;AACnC,SAASC,KAAK,QAAQ,SAAQ;AAE9B;;;CAGC,GACD,OAAO,MAAMC,cAAcH,iBACzB,IAAID,SAAc,MAClB,OAAOK,UAAkBC,UACvBH,MAAMG,SAAS;QAAEC,UAAU;QAAWF;IAAS,GAAGG,KAAK,CAAC,IAAM,OAChE,CAACC,GAAGH,UAAYJ,WAAW,QAAQQ,MAAM,CAACJ,SAASK,MAAM,CAAC,QAC3D","ignoreList":[0]}
|
||||
+174
@@ -0,0 +1,174 @@
|
||||
import { setGlobal } from '../../trace';
|
||||
import * as Log from '../output/log';
|
||||
import * as path from 'node:path';
|
||||
import loadConfig from '../../server/config';
|
||||
import { PHASE_ANALYZE } from '../../shared/lib/constants';
|
||||
import { turbopackAnalyze } from '../turbopack-analyze';
|
||||
import { durationToString } from '../duration-to-string';
|
||||
import { cp, writeFile, mkdir } from 'node:fs/promises';
|
||||
import { discoverRoutes } from '../route-discovery';
|
||||
import { findPagesDir } from '../../lib/find-pages-dir';
|
||||
import loadCustomRoutes from '../../lib/load-custom-routes';
|
||||
import { generateRoutesManifest } from '../generate-routes-manifest';
|
||||
import { checkIsAppPPREnabled } from '../../server/lib/experimental/ppr';
|
||||
import { normalizeAppPath } from '../../shared/lib/router/utils/app-paths';
|
||||
import http from 'node:http';
|
||||
// @ts-expect-error types are in @types/serve-handler
|
||||
import serveHandler from 'next/dist/compiled/serve-handler';
|
||||
import { Telemetry } from '../../telemetry/storage';
|
||||
import { eventAnalyzeCompleted } from '../../telemetry/events';
|
||||
import { traceGlobals } from '../../trace/shared';
|
||||
import { Bundler } from '../../lib/bundler';
|
||||
export default async function analyze({ dir, reactProductionProfiling = false, noMangling = false, appDirOnly = false, output = false, port = 4000 }) {
|
||||
try {
|
||||
const config = await loadConfig(PHASE_ANALYZE, dir, {
|
||||
silent: false,
|
||||
reactProductionProfiling,
|
||||
bundler: Bundler.Turbopack
|
||||
});
|
||||
process.env.NEXT_DEPLOYMENT_ID = config.deploymentId || '';
|
||||
const distDir = path.join(dir, '.next');
|
||||
const telemetry = new Telemetry({
|
||||
distDir
|
||||
});
|
||||
setGlobal('phase', PHASE_ANALYZE);
|
||||
setGlobal('distDir', distDir);
|
||||
setGlobal('telemetry', telemetry);
|
||||
Log.info('Analyzing a production build...');
|
||||
const analyzeContext = {
|
||||
config,
|
||||
dir,
|
||||
distDir,
|
||||
noMangling,
|
||||
appDirOnly
|
||||
};
|
||||
const { duration: analyzeDuration, shutdownPromise } = await turbopackAnalyze(analyzeContext);
|
||||
const durationString = durationToString(analyzeDuration);
|
||||
const analyzeDir = path.join(distDir, 'diagnostics/analyze');
|
||||
await shutdownPromise;
|
||||
const routes = await collectRoutesForAnalyze(dir, config, appDirOnly);
|
||||
await cp(path.join(__dirname, '../../bundle-analyzer'), analyzeDir, {
|
||||
recursive: true
|
||||
});
|
||||
await mkdir(path.join(analyzeDir, 'data'), {
|
||||
recursive: true
|
||||
});
|
||||
await writeFile(path.join(analyzeDir, 'data', 'routes.json'), JSON.stringify(routes, null, 2));
|
||||
let logMessage = `Analyze completed in ${durationString}.`;
|
||||
if (output) {
|
||||
logMessage += ` Results written to ${analyzeDir}.\nTo explore the analyze results interactively, run \`next experimental-analyze\` without \`--output\`.`;
|
||||
}
|
||||
Log.event(logMessage);
|
||||
telemetry.record(eventAnalyzeCompleted({
|
||||
success: true,
|
||||
durationInSeconds: Math.round(analyzeDuration),
|
||||
totalPageCount: routes.length
|
||||
}));
|
||||
if (!output) {
|
||||
await startServer(analyzeDir, port);
|
||||
}
|
||||
} catch (e) {
|
||||
const telemetry = traceGlobals.get('telemetry');
|
||||
if (telemetry) {
|
||||
telemetry.record(eventAnalyzeCompleted({
|
||||
success: false
|
||||
}));
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Collects all routes from the project for the bundle analyzer.
|
||||
* Returns a list of route paths (both static and dynamic).
|
||||
*/ async function collectRoutesForAnalyze(dir, config, appDirOnly) {
|
||||
const { pagesDir, appDir } = findPagesDir(dir);
|
||||
let appType;
|
||||
if (pagesDir && appDir) {
|
||||
appType = 'hybrid';
|
||||
} else if (pagesDir) {
|
||||
appType = 'pages';
|
||||
} else if (appDir) {
|
||||
appType = 'app';
|
||||
} else {
|
||||
throw Object.defineProperty(new Error('No pages or app directory found.'), "__NEXT_ERROR_CODE", {
|
||||
value: "E929",
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
}
|
||||
const discovery = await discoverRoutes({
|
||||
appDir,
|
||||
pagesDir,
|
||||
pageExtensions: config.pageExtensions,
|
||||
isDev: false,
|
||||
baseDir: dir,
|
||||
isSrcDir: path.relative(dir, pagesDir || appDir || '').startsWith('src'),
|
||||
appDirOnly
|
||||
});
|
||||
const pageKeys = {
|
||||
pages: Object.keys(discovery.mappedPages || {}),
|
||||
app: discovery.mappedAppPages ? Object.keys(discovery.mappedAppPages).map((key)=>normalizeAppPath(key)) : []
|
||||
};
|
||||
// Load custom routes
|
||||
const { redirects, headers, onMatchHeaders, rewrites } = await loadCustomRoutes(config);
|
||||
// Compute restricted redirect paths
|
||||
const restrictedRedirectPaths = [
|
||||
'/_next'
|
||||
].map((pathPrefix)=>config.basePath ? `${config.basePath}${pathPrefix}` : pathPrefix);
|
||||
const isAppPPREnabled = checkIsAppPPREnabled(config.experimental.ppr);
|
||||
// Generate routes manifest
|
||||
const { routesManifest } = generateRoutesManifest({
|
||||
appType,
|
||||
pageKeys,
|
||||
config,
|
||||
redirects,
|
||||
headers,
|
||||
onMatchHeaders,
|
||||
rewrites,
|
||||
restrictedRedirectPaths,
|
||||
isAppPPREnabled
|
||||
});
|
||||
return routesManifest.dynamicRoutes.map((r)=>r.page).concat(routesManifest.staticRoutes.map((r)=>r.page));
|
||||
}
|
||||
function startServer(dir, port) {
|
||||
const server = http.createServer((req, res)=>{
|
||||
return serveHandler(req, res, {
|
||||
public: dir
|
||||
});
|
||||
});
|
||||
return new Promise((resolve, reject)=>{
|
||||
function onError(err) {
|
||||
server.close(()=>{
|
||||
reject(err);
|
||||
});
|
||||
}
|
||||
server.on('error', onError);
|
||||
server.listen(port, 'localhost', ()=>{
|
||||
const address = server.address();
|
||||
if (address == null) {
|
||||
reject(Object.defineProperty(new Error('Unable to get server address'), "__NEXT_ERROR_CODE", {
|
||||
value: "E928",
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
}));
|
||||
return;
|
||||
}
|
||||
// No longer needed after startup
|
||||
server.removeListener('error', onError);
|
||||
let addressString;
|
||||
if (typeof address === 'string') {
|
||||
addressString = address;
|
||||
} else if (address.family === 'IPv6' && (address.address === '::' || address.address === '::1')) {
|
||||
addressString = `localhost:${address.port}`;
|
||||
} else if (address.family === 'IPv6') {
|
||||
addressString = `[${address.address}]:${address.port}`;
|
||||
} else {
|
||||
addressString = `${address.address}:${address.port}`;
|
||||
}
|
||||
Log.info(`Bundle analyzer available at http://${addressString}`);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
//# sourceMappingURL=index.js.map
|
||||
+1
File diff suppressed because one or more lines are too long
+373
@@ -0,0 +1,373 @@
|
||||
import { readFileSync } from 'node:fs';
|
||||
import { inspect } from 'node:util';
|
||||
import JSON5 from 'next/dist/compiled/json5';
|
||||
import { createConfigItem, loadOptions } from 'next/dist/compiled/babel/core';
|
||||
import loadFullConfig from 'next/dist/compiled/babel/core-lib-config';
|
||||
import { consumeIterator } from './util';
|
||||
import * as Log from '../../output/log';
|
||||
import { isReactCompilerRequired } from '../../swc';
|
||||
import { installBindings } from '../../swc/install-bindings';
|
||||
const nextDistPath = /(next[\\/]dist[\\/]shared[\\/]lib)|(next[\\/]dist[\\/]client)|(next[\\/]dist[\\/]pages)/;
|
||||
function shouldSkipBabel(transformMode, configFilePath, hasReactCompiler) {
|
||||
return transformMode === 'standalone' && configFilePath == null && !hasReactCompiler;
|
||||
}
|
||||
const fileExtensionRegex = /\.([a-z]+)$/;
|
||||
async function getCacheCharacteristics(loaderOptions, source, filename) {
|
||||
var _fileExtensionRegex_exec;
|
||||
let isStandalone, isServer, pagesDir;
|
||||
switch(loaderOptions.transformMode){
|
||||
case 'default':
|
||||
isStandalone = false;
|
||||
isServer = loaderOptions.isServer;
|
||||
pagesDir = loaderOptions.pagesDir;
|
||||
break;
|
||||
case 'standalone':
|
||||
isStandalone = true;
|
||||
break;
|
||||
default:
|
||||
throw Object.defineProperty(new Error(`unsupported transformMode in loader options: ${inspect(loaderOptions)}`), "__NEXT_ERROR_CODE", {
|
||||
value: "E811",
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
}
|
||||
const isPageFile = pagesDir != null && filename.startsWith(pagesDir);
|
||||
const isNextDist = nextDistPath.test(filename);
|
||||
const hasModuleExports = source.indexOf('module.exports') !== -1;
|
||||
const fileExt = ((_fileExtensionRegex_exec = fileExtensionRegex.exec(filename)) == null ? void 0 : _fileExtensionRegex_exec[1]) || 'unknown';
|
||||
let { reactCompilerPlugins, reactCompilerExclude, configFile: configFilePath, transformMode } = loaderOptions;
|
||||
// Compute `hasReactCompiler` as part of the cache characteristics / key,
|
||||
// rather than inside of `getFreshConfig`:
|
||||
// - `isReactCompilerRequired` depends on the file contents
|
||||
// - `node_modules` and `reactCompilerExclude` depend on the file path, which
|
||||
// isn't part of the cache characteristics
|
||||
let hasReactCompiler = reactCompilerPlugins != null && reactCompilerPlugins.length !== 0 && !loaderOptions.isServer && !/[/\\]node_modules[/\\]/.test(filename) && // Assumption: `reactCompilerExclude` is cheap because it should only
|
||||
// operate on the file path and *not* the file contents (it's sync)
|
||||
!(reactCompilerExclude == null ? void 0 : reactCompilerExclude(filename));
|
||||
// `isReactCompilerRequired` is expensive to run (parses/visits with SWC), so
|
||||
// only run it if there's a good chance we might be able to skip calling Babel
|
||||
// entirely (speculatively call `shouldSkipBabel`).
|
||||
//
|
||||
// Otherwise, we can let react compiler handle this logic for us. It should
|
||||
// behave equivalently.
|
||||
if (hasReactCompiler && shouldSkipBabel(transformMode, configFilePath, /*hasReactCompiler*/ false)) {
|
||||
hasReactCompiler &&= await isReactCompilerRequired(filename);
|
||||
}
|
||||
return {
|
||||
isStandalone,
|
||||
isServer,
|
||||
isPageFile,
|
||||
isNextDist,
|
||||
hasModuleExports,
|
||||
hasReactCompiler,
|
||||
fileExt,
|
||||
configFilePath
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Return an array of Babel plugins, conditioned upon loader options and
|
||||
* source file characteristics.
|
||||
*/ function getPlugins(loaderOptions, cacheCharacteristics) {
|
||||
const { isServer, isPageFile, isNextDist, hasModuleExports } = cacheCharacteristics;
|
||||
const { development, hasReactRefresh } = loaderOptions;
|
||||
const applyCommonJsItem = hasModuleExports ? createConfigItem(require('../plugins/commonjs'), {
|
||||
type: 'plugin'
|
||||
}) : null;
|
||||
const reactRefreshItem = hasReactRefresh ? createConfigItem([
|
||||
require('next/dist/compiled/react-refresh/babel'),
|
||||
{
|
||||
skipEnvCheck: true
|
||||
}
|
||||
], {
|
||||
type: 'plugin'
|
||||
}) : null;
|
||||
const pageConfigItem = !isServer && isPageFile ? createConfigItem([
|
||||
require('../plugins/next-page-config')
|
||||
], {
|
||||
type: 'plugin'
|
||||
}) : null;
|
||||
const disallowExportAllItem = !isServer && isPageFile ? createConfigItem([
|
||||
require('../plugins/next-page-disallow-re-export-all-exports')
|
||||
], {
|
||||
type: 'plugin'
|
||||
}) : null;
|
||||
const transformDefineItem = createConfigItem([
|
||||
require.resolve('next/dist/compiled/babel/plugin-transform-define'),
|
||||
{
|
||||
'process.env.NODE_ENV': development ? 'development' : 'production',
|
||||
'typeof window': isServer ? 'undefined' : 'object',
|
||||
'process.browser': isServer ? false : true
|
||||
},
|
||||
'next-js-transform-define-instance'
|
||||
], {
|
||||
type: 'plugin'
|
||||
});
|
||||
const nextSsgItem = !isServer && isPageFile ? createConfigItem([
|
||||
require.resolve('../plugins/next-ssg-transform')
|
||||
], {
|
||||
type: 'plugin'
|
||||
}) : null;
|
||||
const commonJsItem = isNextDist ? createConfigItem(require('next/dist/compiled/babel/plugin-transform-modules-commonjs'), {
|
||||
type: 'plugin'
|
||||
}) : null;
|
||||
const nextFontUnsupported = createConfigItem([
|
||||
require('../plugins/next-font-unsupported')
|
||||
], {
|
||||
type: 'plugin'
|
||||
});
|
||||
return [
|
||||
reactRefreshItem,
|
||||
pageConfigItem,
|
||||
disallowExportAllItem,
|
||||
applyCommonJsItem,
|
||||
transformDefineItem,
|
||||
nextSsgItem,
|
||||
commonJsItem,
|
||||
nextFontUnsupported
|
||||
].filter(Boolean);
|
||||
}
|
||||
const isJsonFile = /\.(json|babelrc)$/;
|
||||
const isJsFile = /\.js$/;
|
||||
/**
|
||||
* While this function does block execution while reading from disk, it
|
||||
* should not introduce any issues. The function is only invoked when
|
||||
* generating a fresh config, and only a small handful of configs should
|
||||
* be generated during compilation.
|
||||
*/ function getCustomBabelConfig(configFilePath) {
|
||||
if (isJsonFile.exec(configFilePath)) {
|
||||
const babelConfigRaw = readFileSync(configFilePath, 'utf8');
|
||||
return JSON5.parse(babelConfigRaw);
|
||||
} else if (isJsFile.exec(configFilePath)) {
|
||||
return require(configFilePath);
|
||||
}
|
||||
throw Object.defineProperty(new Error('The Next.js Babel loader does not support .mjs or .cjs config files.'), "__NEXT_ERROR_CODE", {
|
||||
value: "E477",
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
}
|
||||
let babelConfigWarned = false;
|
||||
/**
|
||||
* Check if custom babel configuration from user only contains options that
|
||||
* can be migrated into latest Next.js features supported by SWC.
|
||||
*
|
||||
* This raises soft warning messages only, not making any errors yet.
|
||||
*/ function checkCustomBabelConfigDeprecation(config) {
|
||||
if (!config || Object.keys(config).length === 0) {
|
||||
return;
|
||||
}
|
||||
const { plugins, presets, ...otherOptions } = config;
|
||||
if (Object.keys(otherOptions ?? {}).length > 0) {
|
||||
return;
|
||||
}
|
||||
if (babelConfigWarned) {
|
||||
return;
|
||||
}
|
||||
babelConfigWarned = true;
|
||||
const isPresetReadyToDeprecate = !presets || presets.length === 0 || presets.length === 1 && presets[0] === 'next/babel';
|
||||
const pluginReasons = [];
|
||||
const unsupportedPlugins = [];
|
||||
if (Array.isArray(plugins)) {
|
||||
for (const plugin of plugins){
|
||||
const pluginName = Array.isArray(plugin) ? plugin[0] : plugin;
|
||||
// [NOTE]: We cannot detect if the user uses babel-plugin-macro based transform plugins,
|
||||
// such as `styled-components/macro` in here.
|
||||
switch(pluginName){
|
||||
case 'styled-components':
|
||||
case 'babel-plugin-styled-components':
|
||||
pluginReasons.push(`\t- 'styled-components' can be enabled via 'compiler.styledComponents' in 'next.config.js'`);
|
||||
break;
|
||||
case '@emotion/babel-plugin':
|
||||
pluginReasons.push(`\t- '@emotion/babel-plugin' can be enabled via 'compiler.emotion' in 'next.config.js'`);
|
||||
break;
|
||||
case 'babel-plugin-relay':
|
||||
pluginReasons.push(`\t- 'babel-plugin-relay' can be enabled via 'compiler.relay' in 'next.config.js'`);
|
||||
break;
|
||||
case 'react-remove-properties':
|
||||
pluginReasons.push(`\t- 'react-remove-properties' can be enabled via 'compiler.reactRemoveProperties' in 'next.config.js'`);
|
||||
break;
|
||||
case 'transform-remove-console':
|
||||
pluginReasons.push(`\t- 'transform-remove-console' can be enabled via 'compiler.removeConsole' in 'next.config.js'`);
|
||||
break;
|
||||
default:
|
||||
unsupportedPlugins.push(pluginName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isPresetReadyToDeprecate && unsupportedPlugins.length === 0) {
|
||||
Log.warn(`It looks like there is a custom Babel configuration that can be removed${pluginReasons.length > 0 ? ':' : '.'}`);
|
||||
if (pluginReasons.length > 0) {
|
||||
Log.warn(`Next.js supports the following features natively: `);
|
||||
Log.warn(pluginReasons.join(''));
|
||||
Log.warn(`For more details configuration options, please refer https://nextjs.org/docs/architecture/nextjs-compiler#supported-features`);
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Generate a new, flat Babel config, ready to be handed to Babel-traverse.
|
||||
* This config should have no unresolved overrides, presets, etc.
|
||||
*
|
||||
* The config returned by this function is cached, so the function should not
|
||||
* depend on file-specific configuration or configuration that could change
|
||||
* across invocations without a process restart.
|
||||
*/ async function getFreshConfig(ctx, cacheCharacteristics, loaderOptions, target) {
|
||||
const { transformMode } = loaderOptions;
|
||||
const { hasReactCompiler, configFilePath, fileExt } = cacheCharacteristics;
|
||||
let customConfig = configFilePath && getCustomBabelConfig(configFilePath);
|
||||
if (shouldSkipBabel(transformMode, configFilePath, hasReactCompiler)) {
|
||||
// Optimization: There's nothing useful to do, bail out and skip babel on
|
||||
// this file
|
||||
return null;
|
||||
}
|
||||
checkCustomBabelConfigDeprecation(customConfig);
|
||||
// We can assume that `reactCompilerPlugins` does not change without a process
|
||||
// restart (it's safe to cache), as it's specified in the `next.config.js`,
|
||||
// which always causes a full restart of `next dev` if changed.
|
||||
const reactCompilerPluginsIfEnabled = hasReactCompiler ? loaderOptions.reactCompilerPlugins ?? [] : [];
|
||||
let isServer, pagesDir, srcDir, development;
|
||||
if (transformMode === 'default') {
|
||||
isServer = loaderOptions.isServer;
|
||||
pagesDir = loaderOptions.pagesDir;
|
||||
srcDir = loaderOptions.srcDir;
|
||||
development = loaderOptions.development;
|
||||
}
|
||||
let options = {
|
||||
babelrc: false,
|
||||
cloneInputAst: false,
|
||||
// Use placeholder file info. `updateBabelConfigWithFileDetails` will
|
||||
// replace this after caching.
|
||||
filename: `basename.${fileExt}`,
|
||||
inputSourceMap: undefined,
|
||||
sourceFileName: `basename.${fileExt}`,
|
||||
// Set the default sourcemap behavior based on Webpack's mapping flag,
|
||||
// but allow users to override if they want.
|
||||
sourceMaps: loaderOptions.sourceMaps === undefined ? ctx.sourceMap : loaderOptions.sourceMaps
|
||||
};
|
||||
const baseCaller = {
|
||||
name: 'next-babel-turbo-loader',
|
||||
supportsStaticESM: true,
|
||||
supportsDynamicImport: true,
|
||||
// Provide plugins with insight into webpack target.
|
||||
// https://github.com/babel/babel-loader/issues/787
|
||||
target,
|
||||
// Webpack 5 supports TLA behind a flag. We enable it by default
|
||||
// for Babel, and then webpack will throw an error if the experimental
|
||||
// flag isn't enabled.
|
||||
supportsTopLevelAwait: true,
|
||||
isServer,
|
||||
srcDir,
|
||||
pagesDir,
|
||||
isDev: development,
|
||||
transformMode,
|
||||
...loaderOptions.caller
|
||||
};
|
||||
options.plugins = [
|
||||
...transformMode === 'default' ? getPlugins(loaderOptions, cacheCharacteristics) : [],
|
||||
...reactCompilerPluginsIfEnabled,
|
||||
...(customConfig == null ? void 0 : customConfig.plugins) || []
|
||||
];
|
||||
// target can be provided in babelrc
|
||||
options.target = isServer ? undefined : customConfig == null ? void 0 : customConfig.target;
|
||||
// env can be provided in babelrc
|
||||
options.env = customConfig == null ? void 0 : customConfig.env;
|
||||
options.presets = (()=>{
|
||||
// If presets is defined the user will have next/babel in their babelrc
|
||||
if (customConfig == null ? void 0 : customConfig.presets) {
|
||||
return customConfig.presets;
|
||||
}
|
||||
// If presets is not defined the user will likely have "env" in their babelrc
|
||||
if (customConfig) {
|
||||
return undefined;
|
||||
}
|
||||
// If no custom config is provided the default is to use next/babel
|
||||
return [
|
||||
'next/babel'
|
||||
];
|
||||
})();
|
||||
options.overrides = loaderOptions.overrides;
|
||||
options.caller = {
|
||||
...baseCaller,
|
||||
hasJsxRuntime: transformMode === 'default' ? loaderOptions.hasJsxRuntime : undefined
|
||||
};
|
||||
// Babel does strict checks on the config so undefined is not allowed
|
||||
if (typeof options.target === 'undefined') {
|
||||
delete options.target;
|
||||
}
|
||||
Object.defineProperty(options.caller, 'onWarning', {
|
||||
enumerable: false,
|
||||
writable: false,
|
||||
value: (reason)=>{
|
||||
if (!(reason instanceof Error)) {
|
||||
reason = Object.defineProperty(new Error(reason), "__NEXT_ERROR_CODE", {
|
||||
value: "E394",
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
}
|
||||
ctx.emitWarning(reason);
|
||||
}
|
||||
});
|
||||
const loadedOptions = loadOptions(options);
|
||||
const config = consumeIterator(loadFullConfig(loadedOptions));
|
||||
return config;
|
||||
}
|
||||
/**
|
||||
* Each key returned here corresponds with a Babel config that can be shared.
|
||||
* The conditions of permissible sharing between files is dependent on specific
|
||||
* file attributes and Next.js compiler states: `CharacteristicsGermaneToCaching`.
|
||||
*/ function getCacheKey(cacheCharacteristics) {
|
||||
const { isStandalone, isServer, isPageFile, isNextDist, hasModuleExports, hasReactCompiler, fileExt, configFilePath } = cacheCharacteristics;
|
||||
const flags = 0 | (isStandalone ? 1 : 0) | (isServer ? 2 : 0) | (isPageFile ? 4 : 0) | (isNextDist ? 8 : 0) | (hasModuleExports ? 16 : 0) | (hasReactCompiler ? 32 : 0);
|
||||
// separate strings with null bytes, assuming null bytes are not valid in file
|
||||
// paths
|
||||
return `${configFilePath || ''}\x00${fileExt}\x00${flags}`;
|
||||
}
|
||||
const configCache = new Map();
|
||||
const configFiles = new Set();
|
||||
/**
|
||||
* Applies file-specific values to a potentially-cached configuration object.
|
||||
*/ function updateBabelConfigWithFileDetails(cachedConfig, loaderOptions, filename, inputSourceMap) {
|
||||
if (cachedConfig == null) {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
...cachedConfig,
|
||||
options: {
|
||||
...cachedConfig.options,
|
||||
cwd: loaderOptions.cwd,
|
||||
root: loaderOptions.cwd,
|
||||
filename,
|
||||
inputSourceMap,
|
||||
// Ensure that Webpack will get a full absolute path in the sourcemap
|
||||
// so that it can properly map the module back to its internal cached
|
||||
// modules.
|
||||
sourceFileName: filename
|
||||
}
|
||||
};
|
||||
}
|
||||
export default async function getConfig(ctx, { source, target, loaderOptions, filename, inputSourceMap }) {
|
||||
// Install bindings early so they are definitely available to the loader.
|
||||
// When run by webpack in next this is already done with correct configuration so this is a no-op.
|
||||
// In turbopack loaders are run in a subprocess so it may or may not be done.
|
||||
await installBindings();
|
||||
const cacheCharacteristics = await getCacheCharacteristics(loaderOptions, source, filename);
|
||||
if (loaderOptions.configFile) {
|
||||
// Ensures webpack invalidates the cache for this loader when the config file changes
|
||||
ctx.addDependency(loaderOptions.configFile);
|
||||
}
|
||||
const cacheKey = getCacheKey(cacheCharacteristics);
|
||||
const cachedConfig = configCache.get(cacheKey);
|
||||
if (cachedConfig !== undefined) {
|
||||
return updateBabelConfigWithFileDetails(cachedConfig, loaderOptions, filename, inputSourceMap);
|
||||
}
|
||||
if (loaderOptions.configFile && !configFiles.has(loaderOptions.configFile)) {
|
||||
configFiles.add(loaderOptions.configFile);
|
||||
Log.info(`Using external babel configuration from ${loaderOptions.configFile}`);
|
||||
}
|
||||
const freshConfig = await getFreshConfig(ctx, cacheCharacteristics, loaderOptions, target);
|
||||
configCache.set(cacheKey, freshConfig);
|
||||
return updateBabelConfigWithFileDetails(freshConfig, loaderOptions, filename, inputSourceMap);
|
||||
}
|
||||
|
||||
//# sourceMappingURL=get-config.js.map
|
||||
+1
File diff suppressed because one or more lines are too long
+41
@@ -0,0 +1,41 @@
|
||||
import transform from './transform';
|
||||
async function nextBabelLoader(ctx, parentTrace, inputSource, inputSourceMap) {
|
||||
const filename = ctx.resourcePath;
|
||||
// Ensure `.d.ts` are not processed.
|
||||
if (filename.endsWith('.d.ts')) {
|
||||
return [
|
||||
inputSource,
|
||||
inputSourceMap
|
||||
];
|
||||
}
|
||||
const target = ctx.target;
|
||||
const loaderOptions = parentTrace.traceChild('get-options')// @ts-ignore TODO: remove ignore once webpack 5 types are used
|
||||
.traceFn(()=>ctx.getOptions());
|
||||
if (loaderOptions.exclude && loaderOptions.exclude(filename)) {
|
||||
return [
|
||||
inputSource,
|
||||
inputSourceMap
|
||||
];
|
||||
}
|
||||
const loaderSpanInner = parentTrace.traceChild('next-babel-turbo-transform');
|
||||
const { code: transformedSource, map: outputSourceMap } = await loaderSpanInner.traceAsyncFn(async ()=>await transform(ctx, inputSource, inputSourceMap, loaderOptions, filename, target, loaderSpanInner));
|
||||
return [
|
||||
transformedSource,
|
||||
outputSourceMap
|
||||
];
|
||||
}
|
||||
function nextBabelLoaderOuter(inputSource, // webpack's source map format is compatible with babel, but the type signature doesn't match
|
||||
inputSourceMap) {
|
||||
const callback = this.async();
|
||||
const loaderSpan = this.currentTraceSpan.traceChild('next-babel-turbo-loader');
|
||||
loaderSpan.traceAsyncFn(()=>nextBabelLoader(this, loaderSpan, inputSource, inputSourceMap)).then(([transformedSource, outputSourceMap])=>callback == null ? void 0 : callback(/* err */ null, transformedSource, outputSourceMap ?? inputSourceMap), (err)=>{
|
||||
callback == null ? void 0 : callback(err);
|
||||
});
|
||||
}
|
||||
// check this type matches `webpack.LoaderDefinitionFunction`, but be careful
|
||||
// not to publicly rely on the webpack type since the generated typescript
|
||||
// declarations will be wrong.
|
||||
const _nextBabelLoaderOuter = nextBabelLoaderOuter;
|
||||
export default nextBabelLoaderOuter;
|
||||
|
||||
//# sourceMappingURL=index.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../../../../../src/build/babel/loader/index.ts"],"sourcesContent":["import type { Span } from '../../../trace'\nimport transform from './transform'\nimport type { NextJsLoaderContext } from './types'\nimport type { SourceMap } from './util'\nimport type { webpack } from 'next/dist/compiled/webpack/webpack'\n\nasync function nextBabelLoader(\n ctx: NextJsLoaderContext,\n parentTrace: Span,\n inputSource: string,\n inputSourceMap: SourceMap | null | undefined\n): Promise<[string, SourceMap | null | undefined]> {\n const filename = ctx.resourcePath\n\n // Ensure `.d.ts` are not processed.\n if (filename.endsWith('.d.ts')) {\n return [inputSource, inputSourceMap]\n }\n\n const target = ctx.target\n const loaderOptions: any = parentTrace\n .traceChild('get-options')\n // @ts-ignore TODO: remove ignore once webpack 5 types are used\n .traceFn(() => ctx.getOptions())\n\n if (loaderOptions.exclude && loaderOptions.exclude(filename)) {\n return [inputSource, inputSourceMap]\n }\n\n const loaderSpanInner = parentTrace.traceChild('next-babel-turbo-transform')\n const { code: transformedSource, map: outputSourceMap } =\n await loaderSpanInner.traceAsyncFn(\n async () =>\n await transform(\n ctx,\n inputSource,\n inputSourceMap,\n loaderOptions,\n filename,\n target,\n loaderSpanInner\n )\n )\n\n return [transformedSource, outputSourceMap]\n}\n\nfunction nextBabelLoaderOuter(\n this: NextJsLoaderContext,\n inputSource: string,\n // webpack's source map format is compatible with babel, but the type signature doesn't match\n inputSourceMap?: any\n) {\n const callback = this.async()\n\n const loaderSpan = this.currentTraceSpan.traceChild('next-babel-turbo-loader')\n loaderSpan\n .traceAsyncFn(() =>\n nextBabelLoader(this, loaderSpan, inputSource, inputSourceMap)\n )\n .then(\n ([transformedSource, outputSourceMap]) =>\n callback?.(\n /* err */ null,\n transformedSource,\n outputSourceMap ?? inputSourceMap\n ),\n (err) => {\n callback?.(err)\n }\n )\n}\n\n// check this type matches `webpack.LoaderDefinitionFunction`, but be careful\n// not to publicly rely on the webpack type since the generated typescript\n// declarations will be wrong.\nconst _nextBabelLoaderOuter: webpack.LoaderDefinitionFunction<\n {},\n NextJsLoaderContext\n> = nextBabelLoaderOuter\n\nexport default nextBabelLoaderOuter\n"],"names":["transform","nextBabelLoader","ctx","parentTrace","inputSource","inputSourceMap","filename","resourcePath","endsWith","target","loaderOptions","traceChild","traceFn","getOptions","exclude","loaderSpanInner","code","transformedSource","map","outputSourceMap","traceAsyncFn","nextBabelLoaderOuter","callback","async","loaderSpan","currentTraceSpan","then","err","_nextBabelLoaderOuter"],"mappings":"AACA,OAAOA,eAAe,cAAa;AAKnC,eAAeC,gBACbC,GAAwB,EACxBC,WAAiB,EACjBC,WAAmB,EACnBC,cAA4C;IAE5C,MAAMC,WAAWJ,IAAIK,YAAY;IAEjC,oCAAoC;IACpC,IAAID,SAASE,QAAQ,CAAC,UAAU;QAC9B,OAAO;YAACJ;YAAaC;SAAe;IACtC;IAEA,MAAMI,SAASP,IAAIO,MAAM;IACzB,MAAMC,gBAAqBP,YACxBQ,UAAU,CAAC,cACZ,+DAA+D;KAC9DC,OAAO,CAAC,IAAMV,IAAIW,UAAU;IAE/B,IAAIH,cAAcI,OAAO,IAAIJ,cAAcI,OAAO,CAACR,WAAW;QAC5D,OAAO;YAACF;YAAaC;SAAe;IACtC;IAEA,MAAMU,kBAAkBZ,YAAYQ,UAAU,CAAC;IAC/C,MAAM,EAAEK,MAAMC,iBAAiB,EAAEC,KAAKC,eAAe,EAAE,GACrD,MAAMJ,gBAAgBK,YAAY,CAChC,UACE,MAAMpB,UACJE,KACAE,aACAC,gBACAK,eACAJ,UACAG,QACAM;IAIR,OAAO;QAACE;QAAmBE;KAAgB;AAC7C;AAEA,SAASE,qBAEPjB,WAAmB,EACnB,6FAA6F;AAC7FC,cAAoB;IAEpB,MAAMiB,WAAW,IAAI,CAACC,KAAK;IAE3B,MAAMC,aAAa,IAAI,CAACC,gBAAgB,CAACd,UAAU,CAAC;IACpDa,WACGJ,YAAY,CAAC,IACZnB,gBAAgB,IAAI,EAAEuB,YAAYpB,aAAaC,iBAEhDqB,IAAI,CACH,CAAC,CAACT,mBAAmBE,gBAAgB,GACnCG,4BAAAA,SACE,OAAO,GAAG,MACVL,mBACAE,mBAAmBd,iBAEvB,CAACsB;QACCL,4BAAAA,SAAWK;IACb;AAEN;AAEA,6EAA6E;AAC7E,0EAA0E;AAC1E,8BAA8B;AAC9B,MAAMC,wBAGFP;AAEJ,eAAeA,qBAAoB","ignoreList":[0]}
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Partially adapted from @babel/core (MIT license).
|
||||
*/ import traverse from 'next/dist/compiled/babel/traverse';
|
||||
import generate from 'next/dist/compiled/babel/generator';
|
||||
import normalizeFile from 'next/dist/compiled/babel/core-lib-normalize-file';
|
||||
import normalizeOpts from 'next/dist/compiled/babel/core-lib-normalize-opts';
|
||||
import loadBlockHoistPlugin from 'next/dist/compiled/babel/core-lib-block-hoist-plugin';
|
||||
import PluginPass from 'next/dist/compiled/babel/core-lib-plugin-pass';
|
||||
import getConfig from './get-config';
|
||||
import { consumeIterator } from './util';
|
||||
function getTraversalParams(file, pluginPairs) {
|
||||
const passPairs = [];
|
||||
const passes = [];
|
||||
const visitors = [];
|
||||
for (const plugin of pluginPairs.concat(loadBlockHoistPlugin())){
|
||||
const pass = new PluginPass(file, plugin.key, plugin.options);
|
||||
passPairs.push([
|
||||
plugin,
|
||||
pass
|
||||
]);
|
||||
passes.push(pass);
|
||||
visitors.push(plugin.visitor);
|
||||
}
|
||||
return {
|
||||
passPairs,
|
||||
passes,
|
||||
visitors
|
||||
};
|
||||
}
|
||||
function invokePluginPre(file, passPairs) {
|
||||
for (const [{ pre }, pass] of passPairs){
|
||||
if (pre) {
|
||||
pre.call(pass, file);
|
||||
}
|
||||
}
|
||||
}
|
||||
function invokePluginPost(file, passPairs) {
|
||||
for (const [{ post }, pass] of passPairs){
|
||||
if (post) {
|
||||
post.call(pass, file);
|
||||
}
|
||||
}
|
||||
}
|
||||
function transformAstPass(file, pluginPairs, parentSpan) {
|
||||
const { passPairs, passes, visitors } = getTraversalParams(file, pluginPairs);
|
||||
invokePluginPre(file, passPairs);
|
||||
const visitor = traverse.visitors.merge(visitors, passes, // @ts-ignore - the exported types are incorrect here
|
||||
file.opts.wrapPluginVisitorMethod);
|
||||
parentSpan.traceChild('babel-turbo-traverse').traceFn(()=>traverse(file.ast, visitor, file.scope));
|
||||
invokePluginPost(file, passPairs);
|
||||
}
|
||||
function transformAst(file, babelConfig, parentSpan) {
|
||||
for (const pluginPairs of babelConfig.passes){
|
||||
transformAstPass(file, pluginPairs, parentSpan);
|
||||
}
|
||||
}
|
||||
export default async function transform(ctx, source, inputSourceMap, loaderOptions, filename, target, parentSpan) {
|
||||
const getConfigSpan = parentSpan.traceChild('babel-turbo-get-config');
|
||||
const babelConfig = await getConfig(ctx, {
|
||||
source,
|
||||
loaderOptions,
|
||||
inputSourceMap: inputSourceMap ?? undefined,
|
||||
target,
|
||||
filename
|
||||
});
|
||||
if (!babelConfig) {
|
||||
return {
|
||||
code: source,
|
||||
map: inputSourceMap ?? null
|
||||
};
|
||||
}
|
||||
getConfigSpan.stop();
|
||||
const normalizeSpan = parentSpan.traceChild('babel-turbo-normalize-file');
|
||||
const file = consumeIterator(normalizeFile(babelConfig.passes, normalizeOpts(babelConfig), source));
|
||||
normalizeSpan.stop();
|
||||
const transformSpan = parentSpan.traceChild('babel-turbo-transform');
|
||||
transformAst(file, babelConfig, transformSpan);
|
||||
transformSpan.stop();
|
||||
const generateSpan = parentSpan.traceChild('babel-turbo-generate');
|
||||
const { code, map } = generate(file.ast, file.opts.generatorOpts, file.code);
|
||||
generateSpan.stop();
|
||||
return {
|
||||
code,
|
||||
map
|
||||
};
|
||||
}
|
||||
|
||||
//# sourceMappingURL=transform.js.map
|
||||
+1
File diff suppressed because one or more lines are too long
+77
@@ -0,0 +1,77 @@
|
||||
import type { webpack } from 'next/dist/compiled/webpack/webpack'
|
||||
import type { JSONValue } from '../../../server/config-shared'
|
||||
import type { Span } from '../../../trace'
|
||||
|
||||
export interface NextJsLoaderContext extends webpack.LoaderContext<{}> {
|
||||
currentTraceSpan: Span
|
||||
target: string
|
||||
}
|
||||
|
||||
export interface NextBabelLoaderBaseOptions {
|
||||
cwd: string
|
||||
|
||||
/**
|
||||
* Should we read the user-provided custom babel config? Used in both `transformMode`s.
|
||||
*/
|
||||
configFile?: string
|
||||
|
||||
/**
|
||||
* Custom plugins to be added to the generated babel options.
|
||||
*/
|
||||
reactCompilerPlugins?: Array<JSONValue>
|
||||
|
||||
/**
|
||||
* Paths that the loader should not apply the react-compiler to.
|
||||
*/
|
||||
reactCompilerExclude?: (excludePath: string) => boolean
|
||||
|
||||
overrides?: any
|
||||
|
||||
/**
|
||||
* Extra fields to pass to presets/plugins via the Babel 'caller' API.
|
||||
*/
|
||||
caller?: any
|
||||
|
||||
/**
|
||||
* Advanced: Can override webpack's sourcemap behavior (see `NextJsLoaderContext["sourceMap"]`).
|
||||
*/
|
||||
sourceMaps?: boolean | 'inline' | 'both' | null | undefined
|
||||
}
|
||||
|
||||
/**
|
||||
* Options to create babel loader for the default transformations.
|
||||
*
|
||||
* This is primary usecase of babel-loader configuration for running
|
||||
* all of the necessary transforms for the ecmascript instead of swc loader.
|
||||
*/
|
||||
export type NextBabelLoaderOptionDefaultPresets = NextBabelLoaderBaseOptions & {
|
||||
transformMode: 'default'
|
||||
|
||||
isServer: boolean
|
||||
distDir: string
|
||||
pagesDir: string | undefined
|
||||
srcDir: string
|
||||
development: boolean
|
||||
hasJsxRuntime: boolean
|
||||
hasReactRefresh: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* Options to create babel loader for 'standalone' transformations.
|
||||
*
|
||||
* This'll create a babel loader does not enable any of the default Next.js
|
||||
* presets or plugins that perform transformations. Non-transforming syntax
|
||||
* plugins (e.g. Typescript) will still be enabled.
|
||||
*
|
||||
* This is useful when Babel is used in combination with SWC, and we expect SWC
|
||||
* to perform downleveling and Next.js-specific transforms. Standalone mode is
|
||||
* used in Turbopack and when React Compiler is used with webpack.
|
||||
*/
|
||||
export type NextBabelLoaderOptionStandalone = NextBabelLoaderBaseOptions & {
|
||||
transformMode: 'standalone'
|
||||
isServer: boolean
|
||||
}
|
||||
|
||||
export type NextBabelLoaderOptions =
|
||||
| NextBabelLoaderOptionDefaultPresets
|
||||
| NextBabelLoaderOptionStandalone
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
export function consumeIterator(iter) {
|
||||
while(true){
|
||||
const { value, done } = iter.next();
|
||||
if (done) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//# sourceMappingURL=util.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../../../../../src/build/babel/loader/util.ts"],"sourcesContent":["import type { TransformOptions } from 'next/dist/compiled/babel/core'\n\nexport function consumeIterator(iter: Iterator<any>) {\n while (true) {\n const { value, done } = iter.next()\n if (done) {\n return value\n }\n }\n}\n\n/**\n * Source map standard format as to revision 3.\n *\n * `TransformOptions` uses this type, but doesn't export it separately\n */\nexport type SourceMap = NonNullable<TransformOptions['inputSourceMap']>\n\n/**\n * An extension of the normal babel configuration, with extra `babel-loader`-specific fields that transforms can read.\n *\n * See: https://github.com/babel/babel-loader/blob/main/src/injectCaller.js\n */\nexport type BabelLoaderTransformOptions = TransformOptions & {\n target?: string\n}\n"],"names":["consumeIterator","iter","value","done","next"],"mappings":"AAEA,OAAO,SAASA,gBAAgBC,IAAmB;IACjD,MAAO,KAAM;QACX,MAAM,EAAEC,KAAK,EAAEC,IAAI,EAAE,GAAGF,KAAKG,IAAI;QACjC,IAAID,MAAM;YACR,OAAOD;QACT;IACF;AACF","ignoreList":[0]}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
import commonjsPlugin from 'next/dist/compiled/babel/plugin-transform-modules-commonjs';
|
||||
// Handle module.exports in user code
|
||||
export default function CommonJSModulePlugin(...args) {
|
||||
const commonjs = commonjsPlugin(...args);
|
||||
return {
|
||||
visitor: {
|
||||
Program: {
|
||||
exit (path, state) {
|
||||
let foundModuleExports = false;
|
||||
path.traverse({
|
||||
MemberExpression (expressionPath) {
|
||||
if (expressionPath.node.object.name !== 'module') return;
|
||||
if (expressionPath.node.property.name !== 'exports') return;
|
||||
foundModuleExports = true;
|
||||
}
|
||||
});
|
||||
if (!foundModuleExports) {
|
||||
return;
|
||||
}
|
||||
commonjs.visitor.Program.exit.call(this, path, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
//# sourceMappingURL=commonjs.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../../../../../src/build/babel/plugins/commonjs.ts"],"sourcesContent":["import type { NodePath, types } from 'next/dist/compiled/babel/core'\nimport type { PluginObj } from 'next/dist/compiled/babel/core'\nimport commonjsPlugin from 'next/dist/compiled/babel/plugin-transform-modules-commonjs'\n\n// Handle module.exports in user code\nexport default function CommonJSModulePlugin(...args: any): PluginObj {\n const commonjs = commonjsPlugin(...args)\n return {\n visitor: {\n Program: {\n exit(path: NodePath<types.Program>, state) {\n let foundModuleExports = false\n path.traverse({\n MemberExpression(expressionPath: any) {\n if (expressionPath.node.object.name !== 'module') return\n if (expressionPath.node.property.name !== 'exports') return\n foundModuleExports = true\n },\n })\n\n if (!foundModuleExports) {\n return\n }\n\n commonjs.visitor.Program.exit.call(this, path, state)\n },\n },\n },\n }\n}\n"],"names":["commonjsPlugin","CommonJSModulePlugin","args","commonjs","visitor","Program","exit","path","state","foundModuleExports","traverse","MemberExpression","expressionPath","node","object","name","property","call"],"mappings":"AAEA,OAAOA,oBAAoB,6DAA4D;AAEvF,qCAAqC;AACrC,eAAe,SAASC,qBAAqB,GAAGC,IAAS;IACvD,MAAMC,WAAWH,kBAAkBE;IACnC,OAAO;QACLE,SAAS;YACPC,SAAS;gBACPC,MAAKC,IAA6B,EAAEC,KAAK;oBACvC,IAAIC,qBAAqB;oBACzBF,KAAKG,QAAQ,CAAC;wBACZC,kBAAiBC,cAAmB;4BAClC,IAAIA,eAAeC,IAAI,CAACC,MAAM,CAACC,IAAI,KAAK,UAAU;4BAClD,IAAIH,eAAeC,IAAI,CAACG,QAAQ,CAACD,IAAI,KAAK,WAAW;4BACrDN,qBAAqB;wBACvB;oBACF;oBAEA,IAAI,CAACA,oBAAoB;wBACvB;oBACF;oBAEAN,SAASC,OAAO,CAACC,OAAO,CAACC,IAAI,CAACW,IAAI,CAAC,IAAI,EAAEV,MAAMC;gBACjD;YACF;QACF;IACF;AACF","ignoreList":[0]}
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
import jsx from 'next/dist/compiled/babel/plugin-syntax-jsx';
|
||||
export default function({ types: t }) {
|
||||
return {
|
||||
inherits: jsx,
|
||||
visitor: {
|
||||
JSXElement (_path, state) {
|
||||
state.set('jsx', true);
|
||||
},
|
||||
// Fragment syntax is still JSX since it compiles to createElement(),
|
||||
// but JSXFragment is not a JSXElement
|
||||
JSXFragment (_path, state) {
|
||||
state.set('jsx', true);
|
||||
},
|
||||
Program: {
|
||||
exit (path, state) {
|
||||
if (state.get('jsx')) {
|
||||
const pragma = t.identifier(state.opts.pragma);
|
||||
let importAs = pragma;
|
||||
// if there's already a React in scope, use that instead of adding an import
|
||||
const existingBinding = state.opts.reuseImport !== false && state.opts.importAs && path.scope.getBinding(state.opts.importAs);
|
||||
// var _jsx = _pragma.createElement;
|
||||
if (state.opts.property) {
|
||||
if (state.opts.importAs) {
|
||||
importAs = t.identifier(state.opts.importAs);
|
||||
} else {
|
||||
importAs = path.scope.generateUidIdentifier('pragma');
|
||||
}
|
||||
const mapping = t.variableDeclaration('var', [
|
||||
t.variableDeclarator(pragma, t.memberExpression(importAs, t.identifier(state.opts.property)))
|
||||
]);
|
||||
// if the React binding came from a require('react'),
|
||||
// make sure that our usage comes after it.
|
||||
let newPath;
|
||||
if (existingBinding && t.isVariableDeclarator(existingBinding.path.node) && t.isCallExpression(existingBinding.path.node.init) && t.isIdentifier(existingBinding.path.node.init.callee) && existingBinding.path.node.init.callee.name === 'require') {
|
||||
;
|
||||
[newPath] = existingBinding.path.parentPath.insertAfter(mapping);
|
||||
} else {
|
||||
;
|
||||
[newPath] = path.unshiftContainer('body', mapping);
|
||||
}
|
||||
path.scope.registerDeclaration(newPath);
|
||||
}
|
||||
if (!existingBinding) {
|
||||
const importSpecifier = t.importDeclaration([
|
||||
state.opts.import ? t.importSpecifier(importAs, t.identifier(state.opts.import)) : state.opts.importNamespace ? t.importNamespaceSpecifier(importAs) : t.importDefaultSpecifier(importAs)
|
||||
], t.stringLiteral(state.opts.module || 'react'));
|
||||
const [newPath] = path.unshiftContainer('body', importSpecifier);
|
||||
for (const specifier of newPath.get('specifiers')){
|
||||
path.scope.registerBinding('module', specifier);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
//# sourceMappingURL=jsx-pragma.js.map
|
||||
+1
File diff suppressed because one or more lines are too long
+26
@@ -0,0 +1,26 @@
|
||||
export default function NextPageDisallowReExportAllExports() {
|
||||
return {
|
||||
visitor: {
|
||||
ImportDeclaration (path) {
|
||||
if ([
|
||||
'@next/font/local',
|
||||
'@next/font/google',
|
||||
'next/font/local',
|
||||
'next/font/google'
|
||||
].includes(path.node.source.value)) {
|
||||
var _path_node_loc, _path_node_loc1;
|
||||
const err = Object.defineProperty(new SyntaxError(`"next/font" requires SWC although Babel is being used due to a custom babel config being present.\nRead more: https://nextjs.org/docs/messages/babel-font-loader-conflict`), "__NEXT_ERROR_CODE", {
|
||||
value: "E542",
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
err.code = 'BABEL_PARSE_ERROR';
|
||||
err.loc = ((_path_node_loc = path.node.loc) == null ? void 0 : _path_node_loc.start) ?? ((_path_node_loc1 = path.node.loc) == null ? void 0 : _path_node_loc1.end) ?? path.node.loc;
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
//# sourceMappingURL=next-font-unsupported.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../../../../../src/build/babel/plugins/next-font-unsupported.ts"],"sourcesContent":["import type { NodePath, types } from 'next/dist/compiled/babel/core'\nimport type { PluginObj } from 'next/dist/compiled/babel/core'\n\nexport default function NextPageDisallowReExportAllExports(): PluginObj<any> {\n return {\n visitor: {\n ImportDeclaration(path: NodePath<types.ImportDeclaration>) {\n if (\n [\n '@next/font/local',\n '@next/font/google',\n 'next/font/local',\n 'next/font/google',\n ].includes(path.node.source.value)\n ) {\n const err = new SyntaxError(\n `\"next/font\" requires SWC although Babel is being used due to a custom babel config being present.\\nRead more: https://nextjs.org/docs/messages/babel-font-loader-conflict`\n )\n ;(err as any).code = 'BABEL_PARSE_ERROR'\n ;(err as any).loc =\n path.node.loc?.start ?? path.node.loc?.end ?? path.node.loc\n throw err\n }\n },\n },\n }\n}\n"],"names":["NextPageDisallowReExportAllExports","visitor","ImportDeclaration","path","includes","node","source","value","err","SyntaxError","code","loc","start","end"],"mappings":"AAGA,eAAe,SAASA;IACtB,OAAO;QACLC,SAAS;YACPC,mBAAkBC,IAAuC;gBACvD,IACE;oBACE;oBACA;oBACA;oBACA;iBACD,CAACC,QAAQ,CAACD,KAAKE,IAAI,CAACC,MAAM,CAACC,KAAK,GACjC;wBAMEJ,gBAAwBA;oBAL1B,MAAMK,MAAM,qBAEX,CAFW,IAAIC,YACd,CAAC,yKAAyK,CAAC,GADjK,qBAAA;+BAAA;oCAAA;sCAAA;oBAEZ;oBACED,IAAYE,IAAI,GAAG;oBACnBF,IAAYG,GAAG,GACfR,EAAAA,iBAAAA,KAAKE,IAAI,CAACM,GAAG,qBAAbR,eAAeS,KAAK,OAAIT,kBAAAA,KAAKE,IAAI,CAACM,GAAG,qBAAbR,gBAAeU,GAAG,KAAIV,KAAKE,IAAI,CAACM,GAAG;oBAC7D,MAAMH;gBACR;YACF;QACF;IACF;AACF","ignoreList":[0]}
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
import { types as BabelTypes } from 'next/dist/compiled/babel/core';
|
||||
const CONFIG_KEY = 'config';
|
||||
function errorMessage(state, details) {
|
||||
const pageName = (state.filename || '').split(state.cwd || '').pop() || 'unknown';
|
||||
return `Invalid page config export found. ${details} in file ${pageName}. See: https://nextjs.org/docs/messages/invalid-page-config`;
|
||||
}
|
||||
// config to parsing pageConfig for client bundles
|
||||
export default function nextPageConfig({ types: t }) {
|
||||
return {
|
||||
visitor: {
|
||||
Program: {
|
||||
enter (path, state) {
|
||||
path.traverse({
|
||||
ExportDeclaration (exportPath, exportState) {
|
||||
var _exportPath_node_specifiers;
|
||||
if (BabelTypes.isExportNamedDeclaration(exportPath.node) && ((_exportPath_node_specifiers = exportPath.node.specifiers) == null ? void 0 : _exportPath_node_specifiers.some((specifier)=>{
|
||||
return (t.isIdentifier(specifier.exported) ? specifier.exported.name : specifier.exported.value) === CONFIG_KEY;
|
||||
})) && BabelTypes.isStringLiteral(exportPath.node.source)) {
|
||||
throw Object.defineProperty(new Error(errorMessage(exportState, 'Expected object but got export from')), "__NEXT_ERROR_CODE", {
|
||||
value: "E394",
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
}
|
||||
},
|
||||
ExportNamedDeclaration (exportPath, exportState) {
|
||||
var _exportPath_node_declaration, _exportPath_scope_getBinding;
|
||||
if (exportState.bundleDropped || !exportPath.node.declaration && exportPath.node.specifiers.length === 0) {
|
||||
return;
|
||||
}
|
||||
const declarations = [
|
||||
...((_exportPath_node_declaration = exportPath.node.declaration) == null ? void 0 : _exportPath_node_declaration.declarations) || [],
|
||||
(_exportPath_scope_getBinding = exportPath.scope.getBinding(CONFIG_KEY)) == null ? void 0 : _exportPath_scope_getBinding.path.node
|
||||
].filter(Boolean);
|
||||
for (const specifier of exportPath.node.specifiers){
|
||||
if ((t.isIdentifier(specifier.exported) ? specifier.exported.name : specifier.exported.value) === CONFIG_KEY) {
|
||||
// export {} from 'somewhere'
|
||||
if (BabelTypes.isStringLiteral(exportPath.node.source)) {
|
||||
throw Object.defineProperty(new Error(errorMessage(exportState, `Expected object but got import`)), "__NEXT_ERROR_CODE", {
|
||||
value: "E394",
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
// import hello from 'world'
|
||||
// export { hello as config }
|
||||
} else if (BabelTypes.isIdentifier(specifier.local)) {
|
||||
var _exportPath_scope_getBinding1;
|
||||
if (BabelTypes.isImportSpecifier((_exportPath_scope_getBinding1 = exportPath.scope.getBinding(specifier.local.name)) == null ? void 0 : _exportPath_scope_getBinding1.path.node)) {
|
||||
throw Object.defineProperty(new Error(errorMessage(exportState, `Expected object but got import`)), "__NEXT_ERROR_CODE", {
|
||||
value: "E394",
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const declaration of declarations){
|
||||
if (!BabelTypes.isIdentifier(declaration.id, {
|
||||
name: CONFIG_KEY
|
||||
})) {
|
||||
continue;
|
||||
}
|
||||
let { init } = declaration;
|
||||
if (BabelTypes.isTSAsExpression(init)) {
|
||||
init = init.expression;
|
||||
}
|
||||
if (!BabelTypes.isObjectExpression(init)) {
|
||||
const got = init ? init.type : 'undefined';
|
||||
throw Object.defineProperty(new Error(errorMessage(exportState, `Expected object but got ${got}`)), "__NEXT_ERROR_CODE", {
|
||||
value: "E394",
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
}
|
||||
for (const prop of init.properties){
|
||||
if (BabelTypes.isSpreadElement(prop)) {
|
||||
throw Object.defineProperty(new Error(errorMessage(exportState, `Property spread is not allowed`)), "__NEXT_ERROR_CODE", {
|
||||
value: "E394",
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
//# sourceMappingURL=next-page-config.js.map
|
||||
+1
File diff suppressed because one or more lines are too long
Generated
Vendored
+19
@@ -0,0 +1,19 @@
|
||||
export default function NextPageDisallowReExportAllExports() {
|
||||
return {
|
||||
visitor: {
|
||||
ExportAllDeclaration (path) {
|
||||
var _path_node_loc, _path_node_loc1;
|
||||
const err = Object.defineProperty(new SyntaxError(`Using \`export * from '...'\` in a page is disallowed. Please use \`export { default } from '...'\` instead.\n` + `Read more: https://nextjs.org/docs/messages/export-all-in-page`), "__NEXT_ERROR_CODE", {
|
||||
value: "E555",
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
err.code = 'BABEL_PARSE_ERROR';
|
||||
err.loc = ((_path_node_loc = path.node.loc) == null ? void 0 : _path_node_loc.start) ?? ((_path_node_loc1 = path.node.loc) == null ? void 0 : _path_node_loc1.end) ?? path.node.loc;
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
//# sourceMappingURL=next-page-disallow-re-export-all-exports.js.map
|
||||
Generated
Vendored
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../../../../../src/build/babel/plugins/next-page-disallow-re-export-all-exports.ts"],"sourcesContent":["import type { NodePath, types } from 'next/dist/compiled/babel/core'\nimport type { PluginObj } from 'next/dist/compiled/babel/core'\n\nexport default function NextPageDisallowReExportAllExports(): PluginObj<any> {\n return {\n visitor: {\n ExportAllDeclaration(path: NodePath<types.ExportAllDeclaration>) {\n const err = new SyntaxError(\n `Using \\`export * from '...'\\` in a page is disallowed. Please use \\`export { default } from '...'\\` instead.\\n` +\n `Read more: https://nextjs.org/docs/messages/export-all-in-page`\n )\n ;(err as any).code = 'BABEL_PARSE_ERROR'\n ;(err as any).loc =\n path.node.loc?.start ?? path.node.loc?.end ?? path.node.loc\n throw err\n },\n },\n }\n}\n"],"names":["NextPageDisallowReExportAllExports","visitor","ExportAllDeclaration","path","err","SyntaxError","code","loc","node","start","end"],"mappings":"AAGA,eAAe,SAASA;IACtB,OAAO;QACLC,SAAS;YACPC,sBAAqBC,IAA0C;oBAO3DA,gBAAwBA;gBAN1B,MAAMC,MAAM,qBAGX,CAHW,IAAIC,YACd,CAAC,8GAA8G,CAAC,GAC9G,CAAC,8DAA8D,CAAC,GAFxD,qBAAA;2BAAA;gCAAA;kCAAA;gBAGZ;gBACED,IAAYE,IAAI,GAAG;gBACnBF,IAAYG,GAAG,GACfJ,EAAAA,iBAAAA,KAAKK,IAAI,CAACD,GAAG,qBAAbJ,eAAeM,KAAK,OAAIN,kBAAAA,KAAKK,IAAI,CAACD,GAAG,qBAAbJ,gBAAeO,GAAG,KAAIP,KAAKK,IAAI,CAACD,GAAG;gBAC7D,MAAMH;YACR;QACF;IACF;AACF","ignoreList":[0]}
|
||||
+315
@@ -0,0 +1,315 @@
|
||||
import { SERVER_PROPS_SSG_CONFLICT } from '../../../lib/constants';
|
||||
import { SERVER_PROPS_ID, STATIC_PROPS_ID } from '../../../shared/lib/constants';
|
||||
export const EXPORT_NAME_GET_STATIC_PROPS = 'getStaticProps';
|
||||
export const EXPORT_NAME_GET_STATIC_PATHS = 'getStaticPaths';
|
||||
export const EXPORT_NAME_GET_SERVER_PROPS = 'getServerSideProps';
|
||||
const ssgExports = new Set([
|
||||
EXPORT_NAME_GET_STATIC_PROPS,
|
||||
EXPORT_NAME_GET_STATIC_PATHS,
|
||||
EXPORT_NAME_GET_SERVER_PROPS,
|
||||
// legacy methods added so build doesn't fail from importing
|
||||
// server-side only methods
|
||||
`unstable_getStaticProps`,
|
||||
`unstable_getStaticPaths`,
|
||||
`unstable_getServerProps`,
|
||||
`unstable_getServerSideProps`
|
||||
]);
|
||||
function decorateSsgExport(t, path, state) {
|
||||
const gsspName = state.isPrerender ? STATIC_PROPS_ID : SERVER_PROPS_ID;
|
||||
const gsspId = t.identifier(gsspName);
|
||||
const addGsspExport = (exportPath)=>{
|
||||
if (state.done) {
|
||||
return;
|
||||
}
|
||||
state.done = true;
|
||||
const [pageCompPath] = exportPath.replaceWithMultiple([
|
||||
t.exportNamedDeclaration(t.variableDeclaration(// We use 'var' instead of 'let' or 'const' for ES5 support. Since
|
||||
// this runs in `Program#exit`, no ES2015 transforms (preset env)
|
||||
// will be ran against this code.
|
||||
'var', [
|
||||
t.variableDeclarator(gsspId, t.booleanLiteral(true))
|
||||
]), [
|
||||
t.exportSpecifier(gsspId, gsspId)
|
||||
]),
|
||||
exportPath.node
|
||||
]);
|
||||
exportPath.scope.registerDeclaration(pageCompPath);
|
||||
};
|
||||
path.traverse({
|
||||
ExportDefaultDeclaration (exportDefaultPath) {
|
||||
addGsspExport(exportDefaultPath);
|
||||
},
|
||||
ExportNamedDeclaration (exportNamedPath) {
|
||||
addGsspExport(exportNamedPath);
|
||||
}
|
||||
});
|
||||
}
|
||||
const isDataIdentifier = (name, state)=>{
|
||||
if (ssgExports.has(name)) {
|
||||
if (name === EXPORT_NAME_GET_SERVER_PROPS) {
|
||||
if (state.isPrerender) {
|
||||
throw Object.defineProperty(new Error(SERVER_PROPS_SSG_CONFLICT), "__NEXT_ERROR_CODE", {
|
||||
value: "E394",
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
}
|
||||
state.isServerProps = true;
|
||||
} else {
|
||||
if (state.isServerProps) {
|
||||
throw Object.defineProperty(new Error(SERVER_PROPS_SSG_CONFLICT), "__NEXT_ERROR_CODE", {
|
||||
value: "E394",
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
}
|
||||
state.isPrerender = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
export default function nextTransformSsg({ types: t }) {
|
||||
function getIdentifier(path) {
|
||||
const parentPath = path.parentPath;
|
||||
if (parentPath.type === 'VariableDeclarator') {
|
||||
const pp = parentPath;
|
||||
const name = pp.get('id');
|
||||
return name.node.type === 'Identifier' ? name : null;
|
||||
}
|
||||
if (parentPath.type === 'AssignmentExpression') {
|
||||
const pp = parentPath;
|
||||
const name = pp.get('left');
|
||||
return name.node.type === 'Identifier' ? name : null;
|
||||
}
|
||||
if (path.node.type === 'ArrowFunctionExpression') {
|
||||
return null;
|
||||
}
|
||||
return path.node.id && path.node.id.type === 'Identifier' ? path.get('id') : null;
|
||||
}
|
||||
function isIdentifierReferenced(ident) {
|
||||
const b = ident.scope.getBinding(ident.node.name);
|
||||
if (b == null ? void 0 : b.referenced) {
|
||||
// Functions can reference themselves, so we need to check if there's a
|
||||
// binding outside the function scope or not.
|
||||
if (b.path.type === 'FunctionDeclaration') {
|
||||
return !b.constantViolations.concat(b.referencePaths)// Check that every reference is contained within the function:
|
||||
.every((ref)=>ref.findParent((p)=>p === b.path));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function markFunction(path, state) {
|
||||
const ident = getIdentifier(path);
|
||||
if ((ident == null ? void 0 : ident.node) && isIdentifierReferenced(ident)) {
|
||||
state.refs.add(ident);
|
||||
}
|
||||
}
|
||||
function markImport(path, state) {
|
||||
const local = path.get('local');
|
||||
if (isIdentifierReferenced(local)) {
|
||||
state.refs.add(local);
|
||||
}
|
||||
}
|
||||
return {
|
||||
visitor: {
|
||||
Program: {
|
||||
enter (path, state) {
|
||||
state.refs = new Set();
|
||||
state.isPrerender = false;
|
||||
state.isServerProps = false;
|
||||
state.done = false;
|
||||
path.traverse({
|
||||
VariableDeclarator (variablePath, variableState) {
|
||||
if (variablePath.node.id.type === 'Identifier') {
|
||||
const local = variablePath.get('id');
|
||||
if (isIdentifierReferenced(local)) {
|
||||
variableState.refs.add(local);
|
||||
}
|
||||
} else if (variablePath.node.id.type === 'ObjectPattern') {
|
||||
const pattern = variablePath.get('id');
|
||||
const properties = pattern.get('properties');
|
||||
properties.forEach((p)=>{
|
||||
const local = p.get(p.node.type === 'ObjectProperty' ? 'value' : p.node.type === 'RestElement' ? 'argument' : function() {
|
||||
throw Object.defineProperty(new Error('invariant'), "__NEXT_ERROR_CODE", {
|
||||
value: "E400",
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
}());
|
||||
if (isIdentifierReferenced(local)) {
|
||||
variableState.refs.add(local);
|
||||
}
|
||||
});
|
||||
} else if (variablePath.node.id.type === 'ArrayPattern') {
|
||||
const pattern = variablePath.get('id');
|
||||
const elements = pattern.get('elements');
|
||||
elements.forEach((e)=>{
|
||||
var _e_node, _e_node1;
|
||||
let local;
|
||||
if (((_e_node = e.node) == null ? void 0 : _e_node.type) === 'Identifier') {
|
||||
local = e;
|
||||
} else if (((_e_node1 = e.node) == null ? void 0 : _e_node1.type) === 'RestElement') {
|
||||
local = e.get('argument');
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
if (isIdentifierReferenced(local)) {
|
||||
variableState.refs.add(local);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
FunctionDeclaration: markFunction,
|
||||
FunctionExpression: markFunction,
|
||||
ArrowFunctionExpression: markFunction,
|
||||
ImportSpecifier: markImport,
|
||||
ImportDefaultSpecifier: markImport,
|
||||
ImportNamespaceSpecifier: markImport,
|
||||
ExportNamedDeclaration (exportNamedPath, exportNamedState) {
|
||||
const specifiers = exportNamedPath.get('specifiers');
|
||||
if (specifiers.length) {
|
||||
specifiers.forEach((s)=>{
|
||||
if (isDataIdentifier(t.isIdentifier(s.node.exported) ? s.node.exported.name : s.node.exported.value, exportNamedState)) {
|
||||
s.remove();
|
||||
}
|
||||
});
|
||||
if (exportNamedPath.node.specifiers.length < 1) {
|
||||
exportNamedPath.remove();
|
||||
}
|
||||
return;
|
||||
}
|
||||
const decl = exportNamedPath.get('declaration');
|
||||
if (decl == null || decl.node == null) {
|
||||
return;
|
||||
}
|
||||
switch(decl.node.type){
|
||||
case 'FunctionDeclaration':
|
||||
{
|
||||
const name = decl.node.id.name;
|
||||
if (isDataIdentifier(name, exportNamedState)) {
|
||||
exportNamedPath.remove();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'VariableDeclaration':
|
||||
{
|
||||
const inner = decl.get('declarations');
|
||||
inner.forEach((d)=>{
|
||||
if (d.node.id.type !== 'Identifier') {
|
||||
return;
|
||||
}
|
||||
const name = d.node.id.name;
|
||||
if (isDataIdentifier(name, exportNamedState)) {
|
||||
d.remove();
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}, state);
|
||||
if (!state.isPrerender && !state.isServerProps) {
|
||||
return;
|
||||
}
|
||||
const refs = state.refs;
|
||||
let count;
|
||||
function sweepFunction(sweepPath) {
|
||||
const ident = getIdentifier(sweepPath);
|
||||
if ((ident == null ? void 0 : ident.node) && refs.has(ident) && !isIdentifierReferenced(ident)) {
|
||||
++count;
|
||||
if (t.isAssignmentExpression(sweepPath.parentPath.node) || t.isVariableDeclarator(sweepPath.parentPath.node)) {
|
||||
sweepPath.parentPath.remove();
|
||||
} else {
|
||||
sweepPath.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
function sweepImport(sweepPath) {
|
||||
const local = sweepPath.get('local');
|
||||
if (refs.has(local) && !isIdentifierReferenced(local)) {
|
||||
++count;
|
||||
sweepPath.remove();
|
||||
if (sweepPath.parent.specifiers.length === 0) {
|
||||
sweepPath.parentPath.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
do {
|
||||
;
|
||||
path.scope.crawl();
|
||||
count = 0;
|
||||
path.traverse({
|
||||
// eslint-disable-next-line no-loop-func
|
||||
VariableDeclarator (variablePath) {
|
||||
if (variablePath.node.id.type === 'Identifier') {
|
||||
const local = variablePath.get('id');
|
||||
if (refs.has(local) && !isIdentifierReferenced(local)) {
|
||||
++count;
|
||||
variablePath.remove();
|
||||
}
|
||||
} else if (variablePath.node.id.type === 'ObjectPattern') {
|
||||
const pattern = variablePath.get('id');
|
||||
const beforeCount = count;
|
||||
const properties = pattern.get('properties');
|
||||
properties.forEach((p)=>{
|
||||
const local = p.get(p.node.type === 'ObjectProperty' ? 'value' : p.node.type === 'RestElement' ? 'argument' : function() {
|
||||
throw Object.defineProperty(new Error('invariant'), "__NEXT_ERROR_CODE", {
|
||||
value: "E400",
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
}());
|
||||
if (refs.has(local) && !isIdentifierReferenced(local)) {
|
||||
++count;
|
||||
p.remove();
|
||||
}
|
||||
});
|
||||
if (beforeCount !== count && pattern.get('properties').length < 1) {
|
||||
variablePath.remove();
|
||||
}
|
||||
} else if (variablePath.node.id.type === 'ArrayPattern') {
|
||||
const pattern = variablePath.get('id');
|
||||
const beforeCount = count;
|
||||
const elements = pattern.get('elements');
|
||||
elements.forEach((e)=>{
|
||||
var _e_node, _e_node1;
|
||||
let local;
|
||||
if (((_e_node = e.node) == null ? void 0 : _e_node.type) === 'Identifier') {
|
||||
local = e;
|
||||
} else if (((_e_node1 = e.node) == null ? void 0 : _e_node1.type) === 'RestElement') {
|
||||
local = e.get('argument');
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
if (refs.has(local) && !isIdentifierReferenced(local)) {
|
||||
++count;
|
||||
e.remove();
|
||||
}
|
||||
});
|
||||
if (beforeCount !== count && pattern.get('elements').length < 1) {
|
||||
variablePath.remove();
|
||||
}
|
||||
}
|
||||
},
|
||||
FunctionDeclaration: sweepFunction,
|
||||
FunctionExpression: sweepFunction,
|
||||
ArrowFunctionExpression: sweepFunction,
|
||||
ImportSpecifier: sweepImport,
|
||||
ImportDefaultSpecifier: sweepImport,
|
||||
ImportNamespaceSpecifier: sweepImport
|
||||
});
|
||||
}while (count);
|
||||
decorateSsgExport(t, path, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
//# sourceMappingURL=next-ssg-transform.js.map
|
||||
+1
File diff suppressed because one or more lines are too long
+50
@@ -0,0 +1,50 @@
|
||||
// matches any hook-like (the default)
|
||||
const isHook = /^use[A-Z]/;
|
||||
// matches only built-in hooks provided by React et al
|
||||
const isBuiltInHook = /^use(Callback|Context|DebugValue|Effect|ImperativeHandle|LayoutEffect|Memo|Reducer|Ref|State)$/;
|
||||
export default function({ types: t }) {
|
||||
const visitor = {
|
||||
CallExpression (path, state) {
|
||||
const onlyBuiltIns = state.opts.onlyBuiltIns;
|
||||
// if specified, options.lib is a list of libraries that provide hook functions
|
||||
const libs = state.opts.lib && (state.opts.lib === true ? [
|
||||
'react',
|
||||
'preact/hooks'
|
||||
] : [].concat(state.opts.lib));
|
||||
// skip function calls that are not the init of a variable declaration:
|
||||
if (!t.isVariableDeclarator(path.parent)) return;
|
||||
// skip function calls where the return value is not Array-destructured:
|
||||
if (!t.isArrayPattern(path.parent.id)) return;
|
||||
// name of the (hook) function being called:
|
||||
const hookName = path.node.callee.name;
|
||||
if (libs) {
|
||||
const binding = path.scope.getBinding(hookName);
|
||||
// not an import
|
||||
if (!binding || binding.kind !== 'module') return;
|
||||
const specifier = binding.path.parent.source.value;
|
||||
// not a match
|
||||
if (!libs.some((lib)=>lib === specifier)) return;
|
||||
}
|
||||
// only match function calls with names that look like a hook
|
||||
if (!(onlyBuiltIns ? isBuiltInHook : isHook).test(hookName)) return;
|
||||
path.parent.id = t.objectPattern(path.parent.id.elements.reduce((patterns, element, i)=>{
|
||||
if (element === null) {
|
||||
return patterns;
|
||||
}
|
||||
return patterns.concat(t.objectProperty(t.numericLiteral(i), // TODO: fix this
|
||||
element));
|
||||
}, []));
|
||||
}
|
||||
};
|
||||
return {
|
||||
name: 'optimize-hook-destructuring',
|
||||
visitor: {
|
||||
// this is a workaround to run before preset-env destroys destructured assignments
|
||||
Program (path, state) {
|
||||
path.traverse(visitor, state);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
//# sourceMappingURL=optimize-hook-destructuring.js.map
|
||||
Generated
Vendored
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../../../../../src/build/babel/plugins/optimize-hook-destructuring.ts"],"sourcesContent":["import type {\n NodePath,\n types as BabelTypes,\n} from 'next/dist/compiled/babel/core'\nimport type { PluginObj } from 'next/dist/compiled/babel/core'\n// matches any hook-like (the default)\nconst isHook = /^use[A-Z]/\n\n// matches only built-in hooks provided by React et al\nconst isBuiltInHook =\n /^use(Callback|Context|DebugValue|Effect|ImperativeHandle|LayoutEffect|Memo|Reducer|Ref|State)$/\n\nexport default function ({\n types: t,\n}: {\n types: typeof BabelTypes\n}): PluginObj<any> {\n const visitor = {\n CallExpression(path: NodePath<BabelTypes.CallExpression>, state: any) {\n const onlyBuiltIns = state.opts.onlyBuiltIns\n\n // if specified, options.lib is a list of libraries that provide hook functions\n const libs =\n state.opts.lib &&\n (state.opts.lib === true\n ? ['react', 'preact/hooks']\n : [].concat(state.opts.lib))\n\n // skip function calls that are not the init of a variable declaration:\n if (!t.isVariableDeclarator(path.parent)) return\n\n // skip function calls where the return value is not Array-destructured:\n if (!t.isArrayPattern(path.parent.id)) return\n\n // name of the (hook) function being called:\n const hookName = (path.node.callee as BabelTypes.Identifier).name\n\n if (libs) {\n const binding = path.scope.getBinding(hookName)\n // not an import\n if (!binding || binding.kind !== 'module') return\n\n const specifier = (binding.path.parent as BabelTypes.ImportDeclaration)\n .source.value\n // not a match\n if (!libs.some((lib: any) => lib === specifier)) return\n }\n\n // only match function calls with names that look like a hook\n if (!(onlyBuiltIns ? isBuiltInHook : isHook).test(hookName)) return\n\n path.parent.id = t.objectPattern(\n path.parent.id.elements.reduce<Array<BabelTypes.ObjectProperty>>(\n (patterns, element, i) => {\n if (element === null) {\n return patterns\n }\n\n return patterns.concat(\n t.objectProperty(\n t.numericLiteral(i),\n // TODO: fix this\n element as Exclude<\n typeof element,\n BabelTypes.MemberExpression | BabelTypes.TSParameterProperty\n >\n )\n )\n },\n []\n )\n )\n },\n }\n\n return {\n name: 'optimize-hook-destructuring',\n visitor: {\n // this is a workaround to run before preset-env destroys destructured assignments\n Program(path, state) {\n path.traverse(visitor, state)\n },\n },\n }\n}\n"],"names":["isHook","isBuiltInHook","types","t","visitor","CallExpression","path","state","onlyBuiltIns","opts","libs","lib","concat","isVariableDeclarator","parent","isArrayPattern","id","hookName","node","callee","name","binding","scope","getBinding","kind","specifier","source","value","some","test","objectPattern","elements","reduce","patterns","element","i","objectProperty","numericLiteral","Program","traverse"],"mappings":"AAKA,sCAAsC;AACtC,MAAMA,SAAS;AAEf,sDAAsD;AACtD,MAAMC,gBACJ;AAEF,eAAe,SAAU,EACvBC,OAAOC,CAAC,EAGT;IACC,MAAMC,UAAU;QACdC,gBAAeC,IAAyC,EAAEC,KAAU;YAClE,MAAMC,eAAeD,MAAME,IAAI,CAACD,YAAY;YAE5C,+EAA+E;YAC/E,MAAME,OACJH,MAAME,IAAI,CAACE,GAAG,IACbJ,CAAAA,MAAME,IAAI,CAACE,GAAG,KAAK,OAChB;gBAAC;gBAAS;aAAe,GACzB,EAAE,CAACC,MAAM,CAACL,MAAME,IAAI,CAACE,GAAG,CAAA;YAE9B,uEAAuE;YACvE,IAAI,CAACR,EAAEU,oBAAoB,CAACP,KAAKQ,MAAM,GAAG;YAE1C,wEAAwE;YACxE,IAAI,CAACX,EAAEY,cAAc,CAACT,KAAKQ,MAAM,CAACE,EAAE,GAAG;YAEvC,4CAA4C;YAC5C,MAAMC,WAAW,AAACX,KAAKY,IAAI,CAACC,MAAM,CAA2BC,IAAI;YAEjE,IAAIV,MAAM;gBACR,MAAMW,UAAUf,KAAKgB,KAAK,CAACC,UAAU,CAACN;gBACtC,gBAAgB;gBAChB,IAAI,CAACI,WAAWA,QAAQG,IAAI,KAAK,UAAU;gBAE3C,MAAMC,YAAY,AAACJ,QAAQf,IAAI,CAACQ,MAAM,CACnCY,MAAM,CAACC,KAAK;gBACf,cAAc;gBACd,IAAI,CAACjB,KAAKkB,IAAI,CAAC,CAACjB,MAAaA,QAAQc,YAAY;YACnD;YAEA,6DAA6D;YAC7D,IAAI,CAAC,AAACjB,CAAAA,eAAeP,gBAAgBD,MAAK,EAAG6B,IAAI,CAACZ,WAAW;YAE7DX,KAAKQ,MAAM,CAACE,EAAE,GAAGb,EAAE2B,aAAa,CAC9BxB,KAAKQ,MAAM,CAACE,EAAE,CAACe,QAAQ,CAACC,MAAM,CAC5B,CAACC,UAAUC,SAASC;gBAClB,IAAID,YAAY,MAAM;oBACpB,OAAOD;gBACT;gBAEA,OAAOA,SAASrB,MAAM,CACpBT,EAAEiC,cAAc,CACdjC,EAAEkC,cAAc,CAACF,IACjB,iBAAiB;gBACjBD;YAMN,GACA,EAAE;QAGR;IACF;IAEA,OAAO;QACLd,MAAM;QACNhB,SAAS;YACP,kFAAkF;YAClFkC,SAAQhC,IAAI,EAAEC,KAAK;gBACjBD,KAAKiC,QAAQ,CAACnC,SAASG;YACzB;QACF;IACF;AACF","ignoreList":[0]}
|
||||
+135
@@ -0,0 +1,135 @@
|
||||
/**
|
||||
COPYRIGHT (c) 2017-present James Kyle <me@thejameskyle.com>
|
||||
MIT License
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWAR
|
||||
*/ // This file is https://github.com/jamiebuilds/react-loadable/blob/master/src/babel.js
|
||||
// - Modified to also look for `next/dynamic`
|
||||
// - Modified to put `webpack` and `modules` under `loadableGenerated` to be
|
||||
// backwards compatible with next/dynamic which has a `modules` key
|
||||
// - Modified to support `dynamic(import('something'))` and
|
||||
// `dynamic(import('something'), options)
|
||||
// - Removed `Loadable.Map` support, `next/dynamic` uses overloaded arguments
|
||||
// instead of a separate API
|
||||
import { relative as relativePath } from 'path';
|
||||
export default function({ types: t }) {
|
||||
return {
|
||||
visitor: {
|
||||
ImportDeclaration (path, state) {
|
||||
let source = path.node.source.value;
|
||||
if (source !== 'next/dynamic') return;
|
||||
let defaultSpecifier = path.get('specifiers').find((specifier)=>{
|
||||
return specifier.isImportDefaultSpecifier();
|
||||
});
|
||||
if (!defaultSpecifier) return;
|
||||
const bindingName = defaultSpecifier.node.local.name;
|
||||
const binding = path.scope.getBinding(bindingName);
|
||||
if (!binding) {
|
||||
return;
|
||||
}
|
||||
binding.referencePaths.forEach((refPath)=>{
|
||||
var _state_file_opts_caller, _state_file_opts_caller1;
|
||||
let callExpression = refPath.parentPath;
|
||||
if (!(callExpression == null ? void 0 : callExpression.isCallExpression())) return;
|
||||
let args = callExpression.get('arguments');
|
||||
if (args.length > 2) {
|
||||
throw callExpression.buildCodeFrameError('next/dynamic only accepts 2 arguments');
|
||||
}
|
||||
if (!args[0]) {
|
||||
return;
|
||||
}
|
||||
let loader;
|
||||
let options;
|
||||
if (args[0].isObjectExpression()) {
|
||||
options = args[0];
|
||||
} else {
|
||||
if (!args[1]) {
|
||||
callExpression.node.arguments.push(t.objectExpression([]));
|
||||
}
|
||||
// This is needed as the code is modified above
|
||||
args = callExpression.get('arguments');
|
||||
loader = args[0];
|
||||
options = args[1];
|
||||
}
|
||||
if (!options.isObjectExpression()) return;
|
||||
const options_ = options;
|
||||
let properties = options_.get('properties');
|
||||
let propertiesMap = {};
|
||||
properties.forEach((property)=>{
|
||||
const key = property.get('key');
|
||||
propertiesMap[key.node.name] = property;
|
||||
});
|
||||
if (propertiesMap.loadableGenerated) {
|
||||
return;
|
||||
}
|
||||
if (propertiesMap.loader) {
|
||||
loader = propertiesMap.loader.get('value');
|
||||
}
|
||||
if (propertiesMap.modules) {
|
||||
loader = propertiesMap.modules.get('value');
|
||||
}
|
||||
if (!loader || Array.isArray(loader)) {
|
||||
return;
|
||||
}
|
||||
const dynamicImports = [];
|
||||
const dynamicKeys = [];
|
||||
if (propertiesMap.ssr) {
|
||||
const ssr = propertiesMap.ssr.get('value');
|
||||
const nodePath = Array.isArray(ssr) ? undefined : ssr;
|
||||
if (nodePath) {
|
||||
var _state_file_opts_caller2;
|
||||
const nonSSR = nodePath.node.type === 'BooleanLiteral' && nodePath.node.value === false;
|
||||
// If `ssr` is set to `false`, erase the loader for server side
|
||||
if (nonSSR && loader && ((_state_file_opts_caller2 = state.file.opts.caller) == null ? void 0 : _state_file_opts_caller2.isServer)) {
|
||||
loader.replaceWith(t.arrowFunctionExpression([], t.nullLiteral(), true));
|
||||
}
|
||||
}
|
||||
}
|
||||
loader.traverse({
|
||||
Import (importPath) {
|
||||
var _state_file_opts_caller;
|
||||
const importArguments = importPath.parentPath.get('arguments');
|
||||
if (!Array.isArray(importArguments)) return;
|
||||
const node = importArguments[0].node;
|
||||
dynamicImports.push(node);
|
||||
dynamicKeys.push(t.binaryExpression('+', t.stringLiteral((((_state_file_opts_caller = state.file.opts.caller) == null ? void 0 : _state_file_opts_caller.srcDir) ? relativePath(state.file.opts.caller.srcDir, state.file.opts.filename) : state.file.opts.filename) + ' -> '), node));
|
||||
}
|
||||
});
|
||||
if (!dynamicImports.length) return;
|
||||
options.node.properties.push(t.objectProperty(t.identifier('loadableGenerated'), t.objectExpression(((_state_file_opts_caller = state.file.opts.caller) == null ? void 0 : _state_file_opts_caller.isDev) || ((_state_file_opts_caller1 = state.file.opts.caller) == null ? void 0 : _state_file_opts_caller1.isServer) ? [
|
||||
t.objectProperty(t.identifier('modules'), t.arrayExpression(dynamicKeys))
|
||||
] : [
|
||||
t.objectProperty(t.identifier('webpack'), t.arrowFunctionExpression([], t.arrayExpression(dynamicImports.map((dynamicImport)=>{
|
||||
return t.callExpression(t.memberExpression(t.identifier('require'), t.identifier('resolveWeak')), [
|
||||
dynamicImport
|
||||
]);
|
||||
}))))
|
||||
])));
|
||||
// Turns `dynamic(import('something'))` into `dynamic(() => import('something'))` for backwards compat.
|
||||
// This is the replicate the behavior in versions below Next.js 7 where we magically handled not executing the `import()` too.
|
||||
// We'll deprecate this behavior and provide a codemod for it in 7.1.
|
||||
if (loader.isCallExpression()) {
|
||||
const arrowFunction = t.arrowFunctionExpression([], loader.node);
|
||||
loader.replaceWith(arrowFunction);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
//# sourceMappingURL=react-loadable-plugin.js.map
|
||||
+1
File diff suppressed because one or more lines are too long
+240
@@ -0,0 +1,240 @@
|
||||
import { dirname } from 'path';
|
||||
const isLoadIntentTest = process.env.NODE_ENV === 'test';
|
||||
const isLoadIntentDevelopment = process.env.NODE_ENV === 'development';
|
||||
// Resolve styled-jsx plugins
|
||||
function styledJsxOptions(options) {
|
||||
options = options || {};
|
||||
options.styleModule = 'styled-jsx/style';
|
||||
if (!Array.isArray(options.plugins)) {
|
||||
return options;
|
||||
}
|
||||
options.plugins = options.plugins.map((plugin)=>{
|
||||
if (Array.isArray(plugin)) {
|
||||
const [name, pluginOptions] = plugin;
|
||||
return [
|
||||
require.resolve(name),
|
||||
pluginOptions
|
||||
];
|
||||
}
|
||||
return require.resolve(plugin);
|
||||
});
|
||||
return options;
|
||||
}
|
||||
// Taken from https://github.com/babel/babel/commit/d60c5e1736543a6eac4b549553e107a9ba967051#diff-b4beead8ad9195361b4537601cc22532R158
|
||||
function supportsStaticESM(caller) {
|
||||
return !!(caller == null ? void 0 : caller.supportsStaticESM);
|
||||
}
|
||||
/**
|
||||
* HACK: A drop-in replacement for `@babel/preset-typescript` that only enables
|
||||
* `@babel/plugin-syntax-typescript` and does not transform the typescript.
|
||||
*
|
||||
* This is used for standalone mode, where Babel is being used alongside SWC
|
||||
* (i.e. Turbopack or with React Compiler on webpack).
|
||||
*
|
||||
* This should match the logic/behavior here:
|
||||
* https://github.com/babel/babel/blob/7f57d3a2e97b7e2800fb82cff9284a3591377971/packages/babel-preset-typescript/src/index.ts#L63
|
||||
*/ function presetTypescriptSyntaxOnly(_api, options) {
|
||||
const { allExtensions, ignoreExtensions, ...restOptions } = options;
|
||||
const disableExtensionDetect = allExtensions || ignoreExtensions;
|
||||
function getPlugins(isTSX, disallowAmbiguousJSXLike) {
|
||||
return [
|
||||
[
|
||||
require('next/dist/compiled/babel/plugin-syntax-typescript'),
|
||||
{
|
||||
isTSX,
|
||||
disallowAmbiguousJSXLike,
|
||||
...restOptions
|
||||
}
|
||||
]
|
||||
];
|
||||
}
|
||||
return {
|
||||
plugins: [],
|
||||
overrides: disableExtensionDetect ? [
|
||||
{
|
||||
plugins: getPlugins(options.isTSX, options.disallowAmbiguousJSXLike)
|
||||
}
|
||||
] : // Babel is being called with a filename.
|
||||
[
|
||||
{
|
||||
test: /\.ts$/,
|
||||
plugins: getPlugins(false, false)
|
||||
},
|
||||
{
|
||||
test: /\.mts$/,
|
||||
sourceType: 'module',
|
||||
plugins: getPlugins(false, true)
|
||||
},
|
||||
{
|
||||
test: /\.cts$/,
|
||||
sourceType: 'unambiguous',
|
||||
plugins: getPlugins(false, true)
|
||||
},
|
||||
{
|
||||
test: /\.tsx$/,
|
||||
plugins: getPlugins(true, false)
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
export default ((api, options = {})=>{
|
||||
var _options_presetreact, _options_presetreact1;
|
||||
const isStandalone = api.caller(// NOTE: `transformMode` may be undefined if the user configured `babel-loader` themselves. In
|
||||
// this case, we should assume we're in 'default' mode.
|
||||
(caller)=>!!caller && caller.transformMode === 'standalone');
|
||||
const isServer = api.caller((caller)=>!!caller && caller.isServer);
|
||||
// syntax plugins that are used in both standalone and default modes
|
||||
const sharedSyntaxPlugins = [
|
||||
require('next/dist/compiled/babel/plugin-syntax-dynamic-import'),
|
||||
[
|
||||
require('next/dist/compiled/babel/plugin-syntax-import-attributes'),
|
||||
{
|
||||
deprecatedAssertSyntax: true
|
||||
}
|
||||
],
|
||||
(isStandalone || isServer) && require('next/dist/compiled/babel/plugin-syntax-bigint')
|
||||
].filter(Boolean);
|
||||
if (isStandalone) {
|
||||
// Just enable a few syntax plugins, we'll let SWC handle any of the downleveling or
|
||||
// next.js-specific transforms.
|
||||
return {
|
||||
sourceType: 'unambiguous',
|
||||
presets: [
|
||||
[
|
||||
presetTypescriptSyntaxOnly,
|
||||
options['syntax-typescript'] ?? options['preset-typescript'] ?? {}
|
||||
]
|
||||
],
|
||||
plugins: [
|
||||
require('next/dist/compiled/babel/plugin-syntax-jsx'),
|
||||
...sharedSyntaxPlugins
|
||||
]
|
||||
};
|
||||
}
|
||||
const supportsESM = api.caller(supportsStaticESM);
|
||||
const isCallerDevelopment = api.caller((caller)=>caller == null ? void 0 : caller.isDev);
|
||||
// Look at external intent if used without a caller (e.g. via Jest):
|
||||
const isTest = isCallerDevelopment == null && isLoadIntentTest;
|
||||
// Look at external intent if used without a caller (e.g. Storybook):
|
||||
const isDevelopment = isCallerDevelopment === true || isCallerDevelopment == null && isLoadIntentDevelopment;
|
||||
// Default to production mode if not `test` nor `development`:
|
||||
const isProduction = !(isTest || isDevelopment);
|
||||
const isBabelLoader = api.caller((caller)=>!!caller && (caller.name === 'babel-loader' || caller.name === 'next-babel-turbo-loader'));
|
||||
const useJsxRuntime = ((_options_presetreact = options['preset-react']) == null ? void 0 : _options_presetreact.runtime) === 'automatic' || Boolean(api.caller((caller)=>!!caller && caller.hasJsxRuntime)) && ((_options_presetreact1 = options['preset-react']) == null ? void 0 : _options_presetreact1.runtime) !== 'classic';
|
||||
const presetEnvConfig = {
|
||||
// In the test environment `modules` is often needed to be set to true, babel figures that out by itself using the `'auto'` option
|
||||
// In production/development this option is set to `false` so that webpack can handle import/export with tree-shaking
|
||||
modules: 'auto',
|
||||
exclude: [
|
||||
'transform-typeof-symbol'
|
||||
],
|
||||
...options['preset-env']
|
||||
};
|
||||
// When transpiling for the server or tests, target the current Node version
|
||||
// if not explicitly specified:
|
||||
if ((isServer || isTest) && (!presetEnvConfig.targets || !(typeof presetEnvConfig.targets === 'object' && 'node' in presetEnvConfig.targets))) {
|
||||
presetEnvConfig.targets = {
|
||||
// Targets the current process' version of Node. This requires apps be
|
||||
// built and deployed on the same version of Node.
|
||||
// This is the same as using "current" but explicit
|
||||
node: process.versions.node
|
||||
};
|
||||
}
|
||||
const runtimeModuleName = isBabelLoader ? 'next/dist/compiled/@babel/runtime' : null;
|
||||
return {
|
||||
sourceType: 'unambiguous',
|
||||
presets: [
|
||||
[
|
||||
require('next/dist/compiled/babel/preset-env'),
|
||||
presetEnvConfig
|
||||
],
|
||||
[
|
||||
require('next/dist/compiled/babel/preset-react'),
|
||||
{
|
||||
// This adds @babel/plugin-transform-react-jsx-source and
|
||||
// @babel/plugin-transform-react-jsx-self automatically in development
|
||||
development: isDevelopment || isTest,
|
||||
...useJsxRuntime ? {
|
||||
runtime: 'automatic'
|
||||
} : {
|
||||
pragma: '__jsx'
|
||||
},
|
||||
...options['preset-react']
|
||||
}
|
||||
],
|
||||
[
|
||||
require('next/dist/compiled/babel/preset-typescript'),
|
||||
{
|
||||
allowNamespaces: true,
|
||||
...options['preset-typescript'] || options['syntax-typescript']
|
||||
}
|
||||
]
|
||||
],
|
||||
plugins: [
|
||||
...sharedSyntaxPlugins,
|
||||
!useJsxRuntime && [
|
||||
require('./plugins/jsx-pragma'),
|
||||
{
|
||||
// This produces the following injected import for modules containing JSX:
|
||||
// import React from 'react';
|
||||
// var __jsx = React.createElement;
|
||||
module: 'react',
|
||||
importAs: 'React',
|
||||
pragma: '__jsx',
|
||||
property: 'createElement'
|
||||
}
|
||||
],
|
||||
[
|
||||
require('./plugins/optimize-hook-destructuring'),
|
||||
{
|
||||
// only optimize hook functions imported from React/Preact
|
||||
lib: true
|
||||
}
|
||||
],
|
||||
require('./plugins/react-loadable-plugin'),
|
||||
// only enable this plugin if custom config for it was provided
|
||||
// otherwise we will only enable it if their browserslist triggers
|
||||
// preset-env to pull it in
|
||||
options['class-properties'] && [
|
||||
require('next/dist/compiled/babel/plugin-proposal-class-properties'),
|
||||
options['class-properties'] || {}
|
||||
],
|
||||
[
|
||||
require('next/dist/compiled/babel/plugin-proposal-object-rest-spread'),
|
||||
{
|
||||
useBuiltIns: true
|
||||
}
|
||||
],
|
||||
!isServer && [
|
||||
require('next/dist/compiled/babel/plugin-transform-runtime'),
|
||||
{
|
||||
corejs: false,
|
||||
helpers: true,
|
||||
regenerator: true,
|
||||
useESModules: supportsESM && presetEnvConfig.modules !== 'commonjs',
|
||||
absoluteRuntime: runtimeModuleName != null ? dirname(require.resolve(`${runtimeModuleName}/package.json`)) : undefined,
|
||||
// regenerator needs `moduleName` to be set in addition to
|
||||
// `absoluteRuntime`.
|
||||
moduleName: runtimeModuleName,
|
||||
...options['transform-runtime']
|
||||
}
|
||||
],
|
||||
[
|
||||
isTest && options['styled-jsx'] && options['styled-jsx']['babel-test'] ? require('styled-jsx/babel-test') : require('styled-jsx/babel'),
|
||||
styledJsxOptions(options['styled-jsx'])
|
||||
],
|
||||
isProduction && [
|
||||
require('next/dist/compiled/babel/plugin-transform-react-remove-prop-types'),
|
||||
{
|
||||
removeImport: true
|
||||
}
|
||||
],
|
||||
// Always compile numeric separator because the resulting number is
|
||||
// smaller.
|
||||
require('next/dist/compiled/babel/plugin-proposal-numeric-separator'),
|
||||
require('next/dist/compiled/babel/plugin-proposal-export-namespace-from')
|
||||
].filter(Boolean)
|
||||
};
|
||||
});
|
||||
|
||||
//# sourceMappingURL=preset.js.map
|
||||
+1
File diff suppressed because one or more lines are too long
+35
@@ -0,0 +1,35 @@
|
||||
// A layer for storing data that is used by plugins to communicate with each
|
||||
// other between different steps of the build process. This is only internal
|
||||
// to Next.js and will not be a part of the final build output.
|
||||
// These states don't need to be deeply merged.
|
||||
let pluginState = {};
|
||||
export function resumePluginState(resumedState) {
|
||||
Object.assign(pluginState, resumedState);
|
||||
}
|
||||
// This method gives you the plugin state with typed and mutable value fields
|
||||
// behind a proxy so we can lazily initialize the values **after** resuming the
|
||||
// plugin state.
|
||||
export function getProxiedPluginState(initialState) {
|
||||
return new Proxy(pluginState, {
|
||||
get (target, key) {
|
||||
if (typeof target[key] === 'undefined') {
|
||||
return target[key] = initialState[key];
|
||||
}
|
||||
return target[key];
|
||||
},
|
||||
set (target, key, value) {
|
||||
target[key] = value;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
export function getPluginState() {
|
||||
return pluginState;
|
||||
}
|
||||
// a global object to store context for the current build
|
||||
// this is used to pass data between different steps of the build without having
|
||||
// to pass it through function arguments.
|
||||
// Not exhaustive, but should be extended to as needed whilst refactoring
|
||||
export const NextBuildContext = {};
|
||||
|
||||
//# sourceMappingURL=build-context.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../../../src/build/build-context.ts"],"sourcesContent":["import type { LoadedEnvFiles } from '@next/env'\nimport type { Rewrite, Redirect } from '../lib/load-custom-routes'\nimport type { __ApiPreviewProps } from '../server/api-utils'\nimport type { NextConfigComplete } from '../server/config-shared'\nimport type { Span } from '../trace'\nimport type getBaseWebpackConfig from './webpack-config'\nimport type { TelemetryPluginState } from './webpack/plugins/telemetry-plugin/telemetry-plugin'\nimport type { Telemetry } from '../telemetry/storage'\n\n// A layer for storing data that is used by plugins to communicate with each\n// other between different steps of the build process. This is only internal\n// to Next.js and will not be a part of the final build output.\n// These states don't need to be deeply merged.\nlet pluginState: Record<string, any> = {}\nexport function resumePluginState(resumedState?: Record<string, any>) {\n Object.assign(pluginState, resumedState)\n}\n\n// This method gives you the plugin state with typed and mutable value fields\n// behind a proxy so we can lazily initialize the values **after** resuming the\n// plugin state.\nexport function getProxiedPluginState<State extends Record<string, any>>(\n initialState: State\n) {\n return new Proxy(pluginState, {\n get(target, key: string) {\n if (typeof target[key] === 'undefined') {\n return (target[key] = initialState[key])\n }\n return target[key]\n },\n set(target, key: string, value) {\n target[key] = value\n return true\n },\n }) as State\n}\n\nexport function getPluginState() {\n return pluginState\n}\n\nexport interface MappedPages {\n [page: string]: string\n}\n\n// a global object to store context for the current build\n// this is used to pass data between different steps of the build without having\n// to pass it through function arguments.\n// Not exhaustive, but should be extended to as needed whilst refactoring\nexport const NextBuildContext: Partial<{\n compilerIdx?: number\n pluginState: Record<string, any>\n // core fields\n dir: string\n distDir: string\n buildId: string\n encryptionKey: string\n config: NextConfigComplete\n appDir: string\n pagesDir: string\n rewrites: {\n fallback: Rewrite[]\n afterFiles: Rewrite[]\n beforeFiles: Rewrite[]\n }\n originalRewrites: {\n fallback: Rewrite[]\n afterFiles: Rewrite[]\n beforeFiles: Rewrite[]\n }\n hasRewrites: boolean\n originalRedirects: Redirect[]\n loadedEnvFiles: LoadedEnvFiles\n previewProps: __ApiPreviewProps\n mappedPages: MappedPages | undefined\n mappedAppPages: MappedPages | undefined\n mappedRootPaths: MappedPages\n hasInstrumentationHook: boolean\n\n // misc fields\n telemetry: Telemetry\n telemetryState: TelemetryPluginState\n nextBuildSpan: Span\n\n // cli fields\n reactProductionProfiling: boolean\n noMangling: boolean\n appDirOnly: boolean\n clientRouterFilters: Parameters<\n typeof getBaseWebpackConfig\n >[1]['clientRouterFilters']\n previewModeId: string\n fetchCacheKeyPrefix?: string\n allowedRevalidateHeaderKeys?: string[]\n isCompileMode?: boolean\n debugPrerender: boolean\n analyze: boolean\n debugBuildPaths?: {\n app: string[]\n pages: string[]\n }\n}> = {}\n"],"names":["pluginState","resumePluginState","resumedState","Object","assign","getProxiedPluginState","initialState","Proxy","get","target","key","set","value","getPluginState","NextBuildContext"],"mappings":"AASA,4EAA4E;AAC5E,4EAA4E;AAC5E,+DAA+D;AAC/D,+CAA+C;AAC/C,IAAIA,cAAmC,CAAC;AACxC,OAAO,SAASC,kBAAkBC,YAAkC;IAClEC,OAAOC,MAAM,CAACJ,aAAaE;AAC7B;AAEA,6EAA6E;AAC7E,+EAA+E;AAC/E,gBAAgB;AAChB,OAAO,SAASG,sBACdC,YAAmB;IAEnB,OAAO,IAAIC,MAAMP,aAAa;QAC5BQ,KAAIC,MAAM,EAAEC,GAAW;YACrB,IAAI,OAAOD,MAAM,CAACC,IAAI,KAAK,aAAa;gBACtC,OAAQD,MAAM,CAACC,IAAI,GAAGJ,YAAY,CAACI,IAAI;YACzC;YACA,OAAOD,MAAM,CAACC,IAAI;QACpB;QACAC,KAAIF,MAAM,EAAEC,GAAW,EAAEE,KAAK;YAC5BH,MAAM,CAACC,IAAI,GAAGE;YACd,OAAO;QACT;IACF;AACF;AAEA,OAAO,SAASC;IACd,OAAOb;AACT;AAMA,yDAAyD;AACzD,gFAAgF;AAChF,yCAAyC;AACzC,yEAAyE;AACzE,OAAO,MAAMc,mBAoDR,CAAC,EAAC","ignoreList":[0]}
|
||||
+470
@@ -0,0 +1,470 @@
|
||||
// Import cpu-profile to start profiling early if enabled
|
||||
import '../server/lib/cpu-profile';
|
||||
import { Span } from '../trace';
|
||||
import { TRACE_IGNORES, getFilesMapFromReasons } from './webpack/plugins/next-trace-entrypoints-plugin';
|
||||
import path from 'path';
|
||||
import fs from 'fs/promises';
|
||||
import { nonNullable } from '../lib/non-nullable';
|
||||
import * as ciEnvironment from '../server/ci-info';
|
||||
import debugOriginal from 'next/dist/compiled/debug';
|
||||
import picomatch from 'next/dist/compiled/picomatch';
|
||||
import { defaultOverrides } from '../server/require-hook';
|
||||
import { nodeFileTrace } from 'next/dist/compiled/@vercel/nft';
|
||||
import { normalizePagePath } from '../shared/lib/page-path/normalize-page-path';
|
||||
import { normalizeAppPath } from '../shared/lib/router/utils/app-paths';
|
||||
import isError from '../lib/is-error';
|
||||
const debug = debugOriginal('next:build:build-traces');
|
||||
export const makeIgnoreFn = (root, ignores)=>{
|
||||
// pre compile the ignore globs
|
||||
const isMatch = picomatch(ignores, {
|
||||
contains: true,
|
||||
dot: true
|
||||
});
|
||||
return (pathname)=>{
|
||||
if (path.isAbsolute(pathname) && !pathname.startsWith(root)) {
|
||||
return true;
|
||||
}
|
||||
return isMatch(pathname);
|
||||
};
|
||||
};
|
||||
function shouldIgnore(file, serverIgnoreFn, reasons, cachedIgnoreFiles, children = new Set()) {
|
||||
if (cachedIgnoreFiles.has(file)) {
|
||||
return cachedIgnoreFiles.get(file);
|
||||
}
|
||||
if (serverIgnoreFn(file)) {
|
||||
cachedIgnoreFiles.set(file, true);
|
||||
return true;
|
||||
}
|
||||
children.add(file);
|
||||
const reason = reasons.get(file);
|
||||
if (!reason || reason.parents.size === 0 || reason.type.includes('initial')) {
|
||||
cachedIgnoreFiles.set(file, false);
|
||||
return false;
|
||||
}
|
||||
// if all parents are ignored the child file
|
||||
// should be ignored as well
|
||||
let allParentsIgnored = true;
|
||||
for (const parent of reason.parents.values()){
|
||||
if (!children.has(parent)) {
|
||||
children.add(parent);
|
||||
if (!shouldIgnore(parent, serverIgnoreFn, reasons, cachedIgnoreFiles, children)) {
|
||||
allParentsIgnored = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
cachedIgnoreFiles.set(file, allParentsIgnored);
|
||||
return allParentsIgnored;
|
||||
}
|
||||
export async function collectBuildTraces({ dir, config, distDir, edgeRuntimeRoutes, staticPages, nextBuildSpan = new Span({
|
||||
name: 'build'
|
||||
}), buildTraceContext, outputFileTracingRoot }) {
|
||||
const startTime = Date.now();
|
||||
debug('starting build traces');
|
||||
const { outputFileTracingIncludes = {}, outputFileTracingExcludes = {} } = config;
|
||||
const excludeGlobKeys = Object.keys(outputFileTracingExcludes);
|
||||
const includeGlobKeys = Object.keys(outputFileTracingIncludes);
|
||||
await nextBuildSpan.traceChild('node-file-trace-build', {
|
||||
isTurbotrace: 'false'
|
||||
}).traceAsyncFn(async ()=>{
|
||||
const nextServerTraceOutput = path.join(distDir, 'next-server.js.nft.json');
|
||||
const nextMinimalTraceOutput = path.join(distDir, 'next-minimal-server.js.nft.json');
|
||||
const root = outputFileTracingRoot;
|
||||
// Under standalone mode, we need to trace the extra IPC server and
|
||||
// worker files.
|
||||
const isStandalone = config.output === 'standalone';
|
||||
const sharedEntriesSet = Object.keys(defaultOverrides).map((value)=>require.resolve(value, {
|
||||
paths: [
|
||||
require.resolve('next/dist/server/require-hook')
|
||||
]
|
||||
}));
|
||||
const { cacheHandler, cacheHandlers } = config;
|
||||
// ensure we trace any dependencies needed for custom
|
||||
// incremental cache handler
|
||||
if (cacheHandler) {
|
||||
sharedEntriesSet.push(require.resolve(path.isAbsolute(cacheHandler) ? cacheHandler : path.join(dir, cacheHandler)));
|
||||
}
|
||||
// Under standalone mode, we need to ensure that the cache entry debug
|
||||
// handler is traced so it can be copied. This is only used for testing,
|
||||
// and is not used in production.
|
||||
if (process.env.__NEXT_TEST_MODE && process.env.NEXT_PRIVATE_DEBUG_CACHE_ENTRY_HANDLERS) {
|
||||
sharedEntriesSet.push(require.resolve(path.isAbsolute(process.env.NEXT_PRIVATE_DEBUG_CACHE_ENTRY_HANDLERS) ? process.env.NEXT_PRIVATE_DEBUG_CACHE_ENTRY_HANDLERS : path.join(dir, process.env.NEXT_PRIVATE_DEBUG_CACHE_ENTRY_HANDLERS)));
|
||||
}
|
||||
if (cacheHandlers) {
|
||||
for (const handlerPath of Object.values(cacheHandlers)){
|
||||
if (handlerPath) {
|
||||
sharedEntriesSet.push(require.resolve(path.isAbsolute(handlerPath) ? handlerPath : path.join(dir, handlerPath)));
|
||||
}
|
||||
}
|
||||
}
|
||||
const serverEntries = [
|
||||
...sharedEntriesSet,
|
||||
...isStandalone ? [
|
||||
require.resolve('next/dist/server/lib/start-server'),
|
||||
require.resolve('next/dist/server/next'),
|
||||
require.resolve('next/dist/server/require-hook')
|
||||
] : [],
|
||||
require.resolve('next/dist/server/next-server')
|
||||
].filter(Boolean);
|
||||
const minimalServerEntries = [
|
||||
...sharedEntriesSet,
|
||||
require.resolve('next/dist/compiled/next-server/server.runtime.prod')
|
||||
].filter(Boolean);
|
||||
const additionalIgnores = new Set();
|
||||
for (const glob of excludeGlobKeys){
|
||||
if (picomatch(glob)('next-server')) {
|
||||
outputFileTracingExcludes[glob].forEach((exclude)=>{
|
||||
additionalIgnores.add(exclude);
|
||||
});
|
||||
}
|
||||
}
|
||||
const sharedIgnores = [
|
||||
'**/next/dist/compiled/next-server/**/*.dev.js',
|
||||
...isStandalone ? [] : [
|
||||
'**/next/dist/compiled/jest-worker/**/*'
|
||||
],
|
||||
'**/next/dist/compiled/webpack/*',
|
||||
'**/node_modules/webpack5/**/*',
|
||||
'**/next/dist/server/lib/route-resolver*',
|
||||
'next/dist/compiled/semver/semver/**/*.js',
|
||||
...ciEnvironment.hasNextSupport ? [
|
||||
// only ignore image-optimizer code when
|
||||
// this is being handled outside of next-server
|
||||
'**/next/dist/server/image-optimizer.js'
|
||||
] : [],
|
||||
...isStandalone ? [] : TRACE_IGNORES,
|
||||
...additionalIgnores
|
||||
];
|
||||
const sharedIgnoresFn = makeIgnoreFn(root, sharedIgnores);
|
||||
const serverIgnores = [
|
||||
...sharedIgnores,
|
||||
'**/node_modules/react{,-dom,-dom-server-turbopack}/**/*.development.js',
|
||||
'**/*.d.ts',
|
||||
'**/*.map',
|
||||
'**/next/dist/pages/**/*',
|
||||
...ciEnvironment.hasNextSupport ? [
|
||||
'**/node_modules/sharp/**/*',
|
||||
'**/@img/sharp-libvips*/**/*'
|
||||
] : []
|
||||
].filter(nonNullable);
|
||||
const serverIgnoreFn = makeIgnoreFn(root, serverIgnores);
|
||||
const minimalServerIgnores = [
|
||||
...serverIgnores,
|
||||
'**/next/dist/compiled/edge-runtime/**/*',
|
||||
'**/next/dist/server/web/sandbox/**/*',
|
||||
'**/next/dist/server/post-process.js'
|
||||
];
|
||||
const minimalServerIgnoreFn = makeIgnoreFn(root, minimalServerIgnores);
|
||||
const routesIgnores = [
|
||||
...sharedIgnores,
|
||||
// server chunks are provided via next-trace-entrypoints-plugin plugin
|
||||
// as otherwise all chunks are traced here and included for all pages
|
||||
// whether they are needed or not
|
||||
'**/.next/server/chunks/**',
|
||||
'**/next/dist/server/post-process.js'
|
||||
].filter(nonNullable);
|
||||
const routeIgnoreFn = makeIgnoreFn(root, routesIgnores);
|
||||
const serverTracedFiles = new Set();
|
||||
const minimalServerTracedFiles = new Set();
|
||||
function addToTracedFiles(base, file, dest) {
|
||||
dest.add(path.relative(distDir, path.join(base, file)).replace(/\\/g, '/'));
|
||||
}
|
||||
if (isStandalone) {
|
||||
addToTracedFiles('', require.resolve('next/dist/compiled/jest-worker/processChild'), serverTracedFiles);
|
||||
addToTracedFiles('', require.resolve('next/dist/compiled/jest-worker/threadChild'), serverTracedFiles);
|
||||
}
|
||||
{
|
||||
var _buildTraceContext_chunksTrace;
|
||||
const chunksToTrace = [
|
||||
...(buildTraceContext == null ? void 0 : (_buildTraceContext_chunksTrace = buildTraceContext.chunksTrace) == null ? void 0 : _buildTraceContext_chunksTrace.action.input) || [],
|
||||
...serverEntries,
|
||||
...minimalServerEntries
|
||||
];
|
||||
const result = await nodeFileTrace(chunksToTrace, {
|
||||
base: outputFileTracingRoot,
|
||||
processCwd: dir,
|
||||
mixedModules: true,
|
||||
async readFile (p) {
|
||||
try {
|
||||
return await fs.readFile(p, 'utf8');
|
||||
} catch (e) {
|
||||
if (isError(e) && (e.code === 'ENOENT' || e.code === 'EISDIR')) {
|
||||
// since tracing runs in parallel with static generation server
|
||||
// files might be removed from that step so tolerate ENOENT
|
||||
// errors gracefully
|
||||
return '';
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
},
|
||||
async readlink (p) {
|
||||
try {
|
||||
return await fs.readlink(p);
|
||||
} catch (e) {
|
||||
if (isError(e) && (e.code === 'EINVAL' || e.code === 'ENOENT' || e.code === 'UNKNOWN')) {
|
||||
return null;
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
},
|
||||
async stat (p) {
|
||||
try {
|
||||
return await fs.stat(p);
|
||||
} catch (e) {
|
||||
if (isError(e) && (e.code === 'ENOENT' || e.code === 'ENOTDIR')) {
|
||||
return null;
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
},
|
||||
// handle shared ignores at top-level as it
|
||||
// avoids over-tracing when we don't need to
|
||||
// and speeds up total trace time
|
||||
ignore (p) {
|
||||
if (sharedIgnoresFn(p)) {
|
||||
return true;
|
||||
}
|
||||
// if a chunk is attempting to be traced that isn't
|
||||
// in our initial list we need to ignore it to prevent
|
||||
// over tracing as webpack needs to be the source of
|
||||
// truth for which chunks should be included for each entry
|
||||
if (p.includes('.next/server/chunks') && !chunksToTrace.includes(path.join(outputFileTracingRoot, p))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
const reasons = result.reasons;
|
||||
const fileList = result.fileList;
|
||||
for (const file of result.esmFileList){
|
||||
fileList.add(file);
|
||||
}
|
||||
const parentFilesMap = getFilesMapFromReasons(fileList, reasons);
|
||||
const cachedLookupIgnore = new Map();
|
||||
const cachedLookupIgnoreMinimal = new Map();
|
||||
for (const [entries, tracedFiles] of [
|
||||
[
|
||||
serverEntries,
|
||||
serverTracedFiles
|
||||
],
|
||||
[
|
||||
minimalServerEntries,
|
||||
minimalServerTracedFiles
|
||||
]
|
||||
]){
|
||||
for (const file of entries){
|
||||
var _parentFilesMap_get;
|
||||
const curFiles = [
|
||||
...((_parentFilesMap_get = parentFilesMap.get(path.relative(outputFileTracingRoot, file))) == null ? void 0 : _parentFilesMap_get.keys()) || []
|
||||
];
|
||||
tracedFiles.add(path.relative(distDir, file).replace(/\\/g, '/'));
|
||||
for (const curFile of curFiles || []){
|
||||
const filePath = path.join(outputFileTracingRoot, curFile);
|
||||
if (!shouldIgnore(curFile, tracedFiles === minimalServerTracedFiles ? minimalServerIgnoreFn : serverIgnoreFn, reasons, tracedFiles === minimalServerTracedFiles ? cachedLookupIgnoreMinimal : cachedLookupIgnore)) {
|
||||
tracedFiles.add(path.relative(distDir, filePath).replace(/\\/g, '/'));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
const { entryNameFilesMap } = (buildTraceContext == null ? void 0 : buildTraceContext.chunksTrace) || {};
|
||||
const cachedLookupIgnoreRoutes = new Map();
|
||||
await Promise.all([
|
||||
...entryNameFilesMap ? Object.entries(entryNameFilesMap) : new Map()
|
||||
].map(async ([entryName, entryNameFiles])=>{
|
||||
const isApp = entryName.startsWith('app/');
|
||||
const isPages = entryName.startsWith('pages/');
|
||||
let route = entryName;
|
||||
if (isApp) {
|
||||
route = normalizeAppPath(route.substring('app'.length));
|
||||
}
|
||||
if (isPages) {
|
||||
route = normalizePagePath(route.substring('pages'.length));
|
||||
}
|
||||
// we don't need to trace for automatically statically optimized
|
||||
// pages as they don't have server bundles, note there is
|
||||
// the caveat with flying shuttle mode as it needs this for
|
||||
// detecting changed entries
|
||||
if (staticPages.includes(route)) {
|
||||
return;
|
||||
}
|
||||
const entryOutputPath = path.join(distDir, 'server', `${entryName}.js`);
|
||||
const traceOutputPath = `${entryOutputPath}.nft.json`;
|
||||
const existingTrace = JSON.parse(await fs.readFile(traceOutputPath, 'utf8'));
|
||||
const traceOutputDir = path.dirname(traceOutputPath);
|
||||
const curTracedFiles = new Set();
|
||||
for (const file of [
|
||||
...entryNameFiles,
|
||||
entryOutputPath
|
||||
]){
|
||||
var _parentFilesMap_get;
|
||||
const curFiles = [
|
||||
...((_parentFilesMap_get = parentFilesMap.get(path.relative(outputFileTracingRoot, file))) == null ? void 0 : _parentFilesMap_get.keys()) || []
|
||||
];
|
||||
for (const curFile of curFiles || []){
|
||||
if (!shouldIgnore(curFile, routeIgnoreFn, reasons, cachedLookupIgnoreRoutes)) {
|
||||
const filePath = path.join(outputFileTracingRoot, curFile);
|
||||
const outputFile = path.relative(traceOutputDir, filePath).replace(/\\/g, '/');
|
||||
curTracedFiles.add(outputFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const file of existingTrace.files || []){
|
||||
curTracedFiles.add(file);
|
||||
}
|
||||
await fs.writeFile(traceOutputPath, JSON.stringify({
|
||||
...existingTrace,
|
||||
files: [
|
||||
...curTracedFiles
|
||||
].sort()
|
||||
}));
|
||||
}));
|
||||
}
|
||||
const moduleTypes = [
|
||||
'app-page',
|
||||
'pages'
|
||||
];
|
||||
for (const type of moduleTypes){
|
||||
const modulePath = require.resolve(`next/dist/server/route-modules/${type}/module.compiled`);
|
||||
const relativeModulePath = path.relative(root, modulePath);
|
||||
const contextDir = path.join(path.dirname(modulePath), 'vendored', 'contexts');
|
||||
for (const item of (await fs.readdir(contextDir))){
|
||||
const itemPath = path.relative(root, path.join(contextDir, item));
|
||||
if (!serverIgnoreFn(itemPath)) {
|
||||
addToTracedFiles(root, itemPath, serverTracedFiles);
|
||||
addToTracedFiles(root, itemPath, minimalServerTracedFiles);
|
||||
}
|
||||
}
|
||||
addToTracedFiles(root, relativeModulePath, serverTracedFiles);
|
||||
addToTracedFiles(root, relativeModulePath, minimalServerTracedFiles);
|
||||
}
|
||||
const serverTracedFilesSorted = Array.from(serverTracedFiles);
|
||||
serverTracedFilesSorted.sort();
|
||||
const minimalServerTracedFilesSorted = Array.from(minimalServerTracedFiles);
|
||||
minimalServerTracedFilesSorted.sort();
|
||||
await Promise.all([
|
||||
fs.writeFile(nextServerTraceOutput, JSON.stringify({
|
||||
version: 1,
|
||||
files: serverTracedFilesSorted
|
||||
})),
|
||||
fs.writeFile(nextMinimalTraceOutput, JSON.stringify({
|
||||
version: 1,
|
||||
files: minimalServerTracedFilesSorted
|
||||
}))
|
||||
]);
|
||||
});
|
||||
// apply outputFileTracingIncludes/outputFileTracingExcludes after runTurbotrace
|
||||
const includeExcludeSpan = nextBuildSpan.traceChild('apply-include-excludes');
|
||||
await includeExcludeSpan.traceAsyncFn(async ()=>{
|
||||
const globOrig = require('next/dist/compiled/glob');
|
||||
const glob = (pattern)=>{
|
||||
return new Promise((resolve, reject)=>{
|
||||
globOrig(pattern, {
|
||||
cwd: dir,
|
||||
nodir: true,
|
||||
dot: true
|
||||
}, (err, files)=>{
|
||||
if (err) {
|
||||
return reject(err);
|
||||
}
|
||||
resolve(files);
|
||||
});
|
||||
});
|
||||
};
|
||||
const { entryNameFilesMap } = (buildTraceContext == null ? void 0 : buildTraceContext.chunksTrace) || {};
|
||||
await Promise.all([
|
||||
...entryNameFilesMap ? Object.entries(entryNameFilesMap) : new Map()
|
||||
].map(async ([entryName])=>{
|
||||
const isApp = entryName.startsWith('app/');
|
||||
const isPages = entryName.startsWith('pages/');
|
||||
let route = entryName;
|
||||
if (isApp) {
|
||||
route = normalizeAppPath(entryName);
|
||||
}
|
||||
if (isPages) {
|
||||
route = normalizePagePath(entryName);
|
||||
}
|
||||
if (staticPages.includes(route)) {
|
||||
return;
|
||||
}
|
||||
// edge routes have no trace files
|
||||
if (edgeRuntimeRoutes.hasOwnProperty(route)) {
|
||||
return;
|
||||
}
|
||||
const combinedIncludes = new Set();
|
||||
const combinedExcludes = new Set();
|
||||
for (const curGlob of includeGlobKeys){
|
||||
const isMatch = picomatch(curGlob, {
|
||||
dot: true,
|
||||
contains: true
|
||||
});
|
||||
if (isMatch(route)) {
|
||||
for (const include of outputFileTracingIncludes[curGlob]){
|
||||
combinedIncludes.add(include.replace(/\\/g, '/'));
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const curGlob of excludeGlobKeys){
|
||||
const isMatch = picomatch(curGlob, {
|
||||
dot: true,
|
||||
contains: true
|
||||
});
|
||||
if (isMatch(route)) {
|
||||
for (const exclude of outputFileTracingExcludes[curGlob]){
|
||||
combinedExcludes.add(exclude);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!(combinedIncludes == null ? void 0 : combinedIncludes.size) && !(combinedExcludes == null ? void 0 : combinedExcludes.size)) {
|
||||
return;
|
||||
}
|
||||
const traceFile = path.join(distDir, `server`, `${entryName}.js.nft.json`);
|
||||
const pageDir = path.dirname(traceFile);
|
||||
const traceContent = JSON.parse(await fs.readFile(traceFile, 'utf8'));
|
||||
const includes = [];
|
||||
const resolvedTraceIncludes = new Map();
|
||||
if (combinedIncludes == null ? void 0 : combinedIncludes.size) {
|
||||
await Promise.all([
|
||||
...combinedIncludes
|
||||
].map(async (includeGlob)=>{
|
||||
const results = await glob(includeGlob);
|
||||
const resolvedInclude = resolvedTraceIncludes.get(includeGlob) || [
|
||||
...results.map((file)=>{
|
||||
return path.relative(pageDir, path.join(dir, file));
|
||||
})
|
||||
];
|
||||
includes.push(...resolvedInclude);
|
||||
resolvedTraceIncludes.set(includeGlob, resolvedInclude);
|
||||
}));
|
||||
}
|
||||
const combined = new Set([
|
||||
...traceContent.files,
|
||||
...includes
|
||||
]);
|
||||
if (combinedExcludes == null ? void 0 : combinedExcludes.size) {
|
||||
const resolvedGlobs = [
|
||||
...combinedExcludes
|
||||
].map((exclude)=>path.join(dir, exclude));
|
||||
// pre compile before forEach
|
||||
const isMatch = picomatch(resolvedGlobs, {
|
||||
dot: true,
|
||||
contains: true
|
||||
});
|
||||
combined.forEach((file)=>{
|
||||
if (isMatch(path.join(pageDir, file))) {
|
||||
combined.delete(file);
|
||||
}
|
||||
});
|
||||
}
|
||||
// overwrite trace file with custom includes/excludes
|
||||
await fs.writeFile(traceFile, JSON.stringify({
|
||||
version: traceContent.version,
|
||||
files: [
|
||||
...combined
|
||||
]
|
||||
}));
|
||||
}));
|
||||
});
|
||||
debug(`finished build tracing ${Date.now() - startTime}ms`);
|
||||
}
|
||||
|
||||
//# sourceMappingURL=collect-build-traces.js.map
|
||||
+1
File diff suppressed because one or more lines are too long
+73
@@ -0,0 +1,73 @@
|
||||
import getWebpackBundler from '../shared/lib/get-webpack-bundler';
|
||||
function generateStats(result, stat) {
|
||||
const { errors, warnings } = stat.toJson({
|
||||
preset: 'errors-warnings',
|
||||
moduleTrace: true
|
||||
});
|
||||
if (errors && errors.length > 0) {
|
||||
result.errors.push(...errors);
|
||||
}
|
||||
if (warnings && warnings.length > 0) {
|
||||
result.warnings.push(...warnings);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
// Webpack 5 requires the compiler to be closed (to save caches)
|
||||
// Webpack 4 does not have this close method so in order to be backwards compatible we check if it exists
|
||||
function closeCompiler(compiler) {
|
||||
return new Promise((resolve, reject)=>{
|
||||
// @ts-ignore Close only exists on the compiler in webpack 5
|
||||
return compiler.close((err)=>err ? reject(err) : resolve());
|
||||
});
|
||||
}
|
||||
export function runCompiler(config, { runWebpackSpan, inputFileSystem }) {
|
||||
return new Promise((resolve, reject)=>{
|
||||
const compiler = getWebpackBundler()(config);
|
||||
// Ensure we use the previous inputFileSystem
|
||||
if (inputFileSystem) {
|
||||
compiler.inputFileSystem = inputFileSystem;
|
||||
}
|
||||
compiler.fsStartTime = Date.now();
|
||||
compiler.run((err, stats)=>{
|
||||
const webpackCloseSpan = runWebpackSpan.traceChild('webpack-close', {
|
||||
name: config.name || 'unknown'
|
||||
});
|
||||
webpackCloseSpan.traceAsyncFn(()=>closeCompiler(compiler)).then(()=>{
|
||||
if (err) {
|
||||
const reason = err.stack ?? err.toString();
|
||||
if (reason) {
|
||||
return resolve([
|
||||
{
|
||||
errors: [
|
||||
{
|
||||
message: reason,
|
||||
details: err.details
|
||||
}
|
||||
],
|
||||
warnings: [],
|
||||
stats
|
||||
},
|
||||
compiler.inputFileSystem
|
||||
]);
|
||||
}
|
||||
return reject(err);
|
||||
} else if (!stats) throw Object.defineProperty(new Error('No Stats from webpack'), "__NEXT_ERROR_CODE", {
|
||||
value: "E370",
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
const result = webpackCloseSpan.traceChild('webpack-generate-error-stats').traceFn(()=>generateStats({
|
||||
errors: [],
|
||||
warnings: [],
|
||||
stats
|
||||
}, stats));
|
||||
return resolve([
|
||||
result,
|
||||
compiler.inputFileSystem
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
//# sourceMappingURL=compiler.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../../../src/build/compiler.ts"],"sourcesContent":["import type { webpack } from 'next/dist/compiled/webpack/webpack'\nimport type { Span } from '../trace'\nimport getWebpackBundler from '../shared/lib/get-webpack-bundler'\n\nexport type CompilerResult = {\n errors: webpack.StatsError[]\n warnings: webpack.StatsError[]\n stats: webpack.Stats | undefined\n}\n\nfunction generateStats(\n result: CompilerResult,\n stat: webpack.Stats\n): CompilerResult {\n const { errors, warnings } = stat.toJson({\n preset: 'errors-warnings',\n moduleTrace: true,\n })\n if (errors && errors.length > 0) {\n result.errors.push(...errors)\n }\n\n if (warnings && warnings.length > 0) {\n result.warnings.push(...warnings)\n }\n\n return result\n}\n\n// Webpack 5 requires the compiler to be closed (to save caches)\n// Webpack 4 does not have this close method so in order to be backwards compatible we check if it exists\nfunction closeCompiler(compiler: webpack.Compiler | webpack.MultiCompiler) {\n return new Promise<void>((resolve, reject) => {\n // @ts-ignore Close only exists on the compiler in webpack 5\n return compiler.close((err: any) => (err ? reject(err) : resolve()))\n })\n}\n\nexport function runCompiler(\n config: webpack.Configuration,\n {\n runWebpackSpan,\n inputFileSystem,\n }: {\n runWebpackSpan: Span\n inputFileSystem?: webpack.Compiler['inputFileSystem']\n }\n): Promise<\n [\n result: CompilerResult,\n inputFileSystem?: webpack.Compiler['inputFileSystem'],\n ]\n> {\n return new Promise((resolve, reject) => {\n const compiler = getWebpackBundler()(config)\n\n // Ensure we use the previous inputFileSystem\n if (inputFileSystem) {\n compiler.inputFileSystem = inputFileSystem\n }\n compiler.fsStartTime = Date.now()\n compiler.run((err, stats) => {\n const webpackCloseSpan = runWebpackSpan.traceChild('webpack-close', {\n name: config.name || 'unknown',\n })\n webpackCloseSpan\n .traceAsyncFn(() => closeCompiler(compiler))\n .then(() => {\n if (err) {\n const reason = err.stack ?? err.toString()\n if (reason) {\n return resolve([\n {\n errors: [{ message: reason, details: (err as any).details }],\n warnings: [],\n stats,\n },\n compiler.inputFileSystem,\n ])\n }\n return reject(err)\n } else if (!stats) throw new Error('No Stats from webpack')\n\n const result = webpackCloseSpan\n .traceChild('webpack-generate-error-stats')\n .traceFn(() =>\n generateStats({ errors: [], warnings: [], stats }, stats)\n )\n return resolve([result, compiler.inputFileSystem])\n })\n })\n })\n}\n"],"names":["getWebpackBundler","generateStats","result","stat","errors","warnings","toJson","preset","moduleTrace","length","push","closeCompiler","compiler","Promise","resolve","reject","close","err","runCompiler","config","runWebpackSpan","inputFileSystem","fsStartTime","Date","now","run","stats","webpackCloseSpan","traceChild","name","traceAsyncFn","then","reason","stack","toString","message","details","Error","traceFn"],"mappings":"AAEA,OAAOA,uBAAuB,oCAAmC;AAQjE,SAASC,cACPC,MAAsB,EACtBC,IAAmB;IAEnB,MAAM,EAAEC,MAAM,EAAEC,QAAQ,EAAE,GAAGF,KAAKG,MAAM,CAAC;QACvCC,QAAQ;QACRC,aAAa;IACf;IACA,IAAIJ,UAAUA,OAAOK,MAAM,GAAG,GAAG;QAC/BP,OAAOE,MAAM,CAACM,IAAI,IAAIN;IACxB;IAEA,IAAIC,YAAYA,SAASI,MAAM,GAAG,GAAG;QACnCP,OAAOG,QAAQ,CAACK,IAAI,IAAIL;IAC1B;IAEA,OAAOH;AACT;AAEA,gEAAgE;AAChE,yGAAyG;AACzG,SAASS,cAAcC,QAAkD;IACvE,OAAO,IAAIC,QAAc,CAACC,SAASC;QACjC,4DAA4D;QAC5D,OAAOH,SAASI,KAAK,CAAC,CAACC,MAAcA,MAAMF,OAAOE,OAAOH;IAC3D;AACF;AAEA,OAAO,SAASI,YACdC,MAA6B,EAC7B,EACEC,cAAc,EACdC,eAAe,EAIhB;IAOD,OAAO,IAAIR,QAAQ,CAACC,SAASC;QAC3B,MAAMH,WAAWZ,oBAAoBmB;QAErC,6CAA6C;QAC7C,IAAIE,iBAAiB;YACnBT,SAASS,eAAe,GAAGA;QAC7B;QACAT,SAASU,WAAW,GAAGC,KAAKC,GAAG;QAC/BZ,SAASa,GAAG,CAAC,CAACR,KAAKS;YACjB,MAAMC,mBAAmBP,eAAeQ,UAAU,CAAC,iBAAiB;gBAClEC,MAAMV,OAAOU,IAAI,IAAI;YACvB;YACAF,iBACGG,YAAY,CAAC,IAAMnB,cAAcC,WACjCmB,IAAI,CAAC;gBACJ,IAAId,KAAK;oBACP,MAAMe,SAASf,IAAIgB,KAAK,IAAIhB,IAAIiB,QAAQ;oBACxC,IAAIF,QAAQ;wBACV,OAAOlB,QAAQ;4BACb;gCACEV,QAAQ;oCAAC;wCAAE+B,SAASH;wCAAQI,SAAS,AAACnB,IAAYmB,OAAO;oCAAC;iCAAE;gCAC5D/B,UAAU,EAAE;gCACZqB;4BACF;4BACAd,SAASS,eAAe;yBACzB;oBACH;oBACA,OAAON,OAAOE;gBAChB,OAAO,IAAI,CAACS,OAAO,MAAM,qBAAkC,CAAlC,IAAIW,MAAM,0BAAV,qBAAA;2BAAA;gCAAA;kCAAA;gBAAiC;gBAE1D,MAAMnC,SAASyB,iBACZC,UAAU,CAAC,gCACXU,OAAO,CAAC,IACPrC,cAAc;wBAAEG,QAAQ,EAAE;wBAAEC,UAAU,EAAE;wBAAEqB;oBAAM,GAAGA;gBAEvD,OAAOZ,QAAQ;oBAACZ;oBAAQU,SAASS,eAAe;iBAAC;YACnD;QACJ;IACF;AACF","ignoreList":[0]}
|
||||
+356
@@ -0,0 +1,356 @@
|
||||
import path from 'path';
|
||||
import * as React from 'react';
|
||||
import { DOT_NEXT_ALIAS, PAGES_DIR_ALIAS, ROOT_DIR_ALIAS, APP_DIR_ALIAS, RSC_ACTION_PROXY_ALIAS, RSC_ACTION_CLIENT_WRAPPER_ALIAS, RSC_ACTION_VALIDATE_ALIAS, RSC_ACTION_ENCRYPTION_ALIAS, RSC_CACHE_WRAPPER_ALIAS, RSC_DYNAMIC_IMPORT_WRAPPER_ALIAS } from '../lib/constants';
|
||||
import { defaultOverrides } from '../server/require-hook';
|
||||
import { hasExternalOtelApiPackage } from './webpack-config';
|
||||
import { NEXT_PROJECT_ROOT } from './next-dir-paths';
|
||||
import { shouldUseReactServerCondition } from './utils';
|
||||
const isReact19 = typeof React.use === 'function';
|
||||
export function createWebpackAliases({ distDir, isClient, isEdgeServer, dev, config, pagesDir, appDir, dir, reactProductionProfiling }) {
|
||||
const pageExtensions = config.pageExtensions;
|
||||
const customAppAliases = {};
|
||||
const customDocumentAliases = {};
|
||||
// tell webpack where to look for _app and _document
|
||||
// using aliases to allow falling back to the default
|
||||
// version when removed or not present
|
||||
if (dev) {
|
||||
const nextDistPath = 'next/dist/' + (isEdgeServer ? 'esm/' : '');
|
||||
customAppAliases[`${PAGES_DIR_ALIAS}/_app`] = [
|
||||
...pagesDir ? pageExtensions.reduce((prev, ext)=>{
|
||||
prev.push(path.join(pagesDir, `_app.${ext}`));
|
||||
return prev;
|
||||
}, []) : [],
|
||||
`${nextDistPath}pages/_app.js`
|
||||
];
|
||||
customAppAliases[`${PAGES_DIR_ALIAS}/_error`] = [
|
||||
...pagesDir ? pageExtensions.reduce((prev, ext)=>{
|
||||
prev.push(path.join(pagesDir, `_error.${ext}`));
|
||||
return prev;
|
||||
}, []) : [],
|
||||
`${nextDistPath}pages/_error.js`
|
||||
];
|
||||
customDocumentAliases[`${PAGES_DIR_ALIAS}/_document`] = [
|
||||
...pagesDir ? pageExtensions.reduce((prev, ext)=>{
|
||||
prev.push(path.join(pagesDir, `_document.${ext}`));
|
||||
return prev;
|
||||
}, []) : [],
|
||||
`${nextDistPath}pages/_document.js`
|
||||
];
|
||||
}
|
||||
return {
|
||||
'@vercel/og$': 'next/dist/server/og/image-response',
|
||||
// Avoid bundling both entrypoints in React 19 when we just need one.
|
||||
// Also avoids bundler warnings in React 18 where react-dom/server.edge doesn't exist.
|
||||
'next/dist/server/ReactDOMServerPages': isReact19 ? 'react-dom/server.edge' : 'react-dom/server.browser',
|
||||
// Alias next/dist imports to next/dist/esm assets,
|
||||
// let this alias hit before `next` alias.
|
||||
...isEdgeServer ? {
|
||||
'next/dist/api': 'next/dist/esm/api',
|
||||
'next/dist/build': 'next/dist/esm/build',
|
||||
'next/dist/client': 'next/dist/esm/client',
|
||||
'next/dist/shared': 'next/dist/esm/shared',
|
||||
'next/dist/pages': 'next/dist/esm/pages',
|
||||
'next/dist/lib': 'next/dist/esm/lib',
|
||||
'next/dist/server': 'next/dist/esm/server',
|
||||
...createNextApiEsmAliases()
|
||||
} : undefined,
|
||||
// For RSC server bundle
|
||||
...!hasExternalOtelApiPackage() && {
|
||||
'@opentelemetry/api': 'next/dist/compiled/@opentelemetry/api'
|
||||
},
|
||||
...config.images.loaderFile ? {
|
||||
'next/dist/shared/lib/image-loader': config.images.loaderFile,
|
||||
...isEdgeServer && {
|
||||
'next/dist/esm/shared/lib/image-loader': config.images.loaderFile
|
||||
}
|
||||
} : undefined,
|
||||
'styled-jsx/style$': defaultOverrides['styled-jsx/style'],
|
||||
'styled-jsx$': defaultOverrides['styled-jsx'],
|
||||
'next/dist/compiled/next-devtools': isClient ? 'next/dist/compiled/next-devtools' : 'next/dist/next-devtools/dev-overlay.shim.js',
|
||||
...customAppAliases,
|
||||
...customDocumentAliases,
|
||||
...pagesDir ? {
|
||||
[PAGES_DIR_ALIAS]: pagesDir
|
||||
} : {},
|
||||
...appDir ? {
|
||||
[APP_DIR_ALIAS]: appDir
|
||||
} : {},
|
||||
[ROOT_DIR_ALIAS]: dir,
|
||||
...isClient ? {
|
||||
'private-next-instrumentation-client': [
|
||||
path.join(dir, 'src', 'instrumentation-client'),
|
||||
path.join(dir, 'instrumentation-client'),
|
||||
'private-next-empty-module'
|
||||
],
|
||||
// disable typechecker, webpack5 allows aliases to be set to false to create a no-op module
|
||||
'private-next-empty-module': false
|
||||
} : {},
|
||||
[DOT_NEXT_ALIAS]: distDir,
|
||||
...isClient || isEdgeServer ? getOptimizedModuleAliases() : {},
|
||||
...reactProductionProfiling ? getReactProfilingInProduction() : {},
|
||||
[RSC_ACTION_VALIDATE_ALIAS]: 'next/dist/build/webpack/loaders/next-flight-loader/action-validate',
|
||||
[RSC_ACTION_CLIENT_WRAPPER_ALIAS]: 'next/dist/build/webpack/loaders/next-flight-loader/action-client-wrapper',
|
||||
[RSC_ACTION_PROXY_ALIAS]: 'next/dist/build/webpack/loaders/next-flight-loader/server-reference',
|
||||
[RSC_ACTION_ENCRYPTION_ALIAS]: 'next/dist/server/app-render/encryption',
|
||||
[RSC_CACHE_WRAPPER_ALIAS]: 'next/dist/build/webpack/loaders/next-flight-loader/cache-wrapper',
|
||||
[RSC_DYNAMIC_IMPORT_WRAPPER_ALIAS]: 'next/dist/build/webpack/loaders/next-flight-loader/track-dynamic-import',
|
||||
'@swc/helpers/_': path.join(path.dirname(require.resolve('@swc/helpers/package.json')), '_'),
|
||||
setimmediate: 'next/dist/compiled/setimmediate'
|
||||
};
|
||||
}
|
||||
export function createServerOnlyClientOnlyAliases(isServer) {
|
||||
return isServer ? {
|
||||
'server-only$': 'next/dist/compiled/server-only/empty',
|
||||
'client-only$': 'next/dist/compiled/client-only/error',
|
||||
'next/dist/compiled/server-only$': 'next/dist/compiled/server-only/empty',
|
||||
'next/dist/compiled/client-only$': 'next/dist/compiled/client-only/error'
|
||||
} : {
|
||||
'server-only$': 'next/dist/compiled/server-only/index',
|
||||
'client-only$': 'next/dist/compiled/client-only/index',
|
||||
'next/dist/compiled/client-only$': 'next/dist/compiled/client-only/index',
|
||||
'next/dist/compiled/server-only': 'next/dist/compiled/server-only/index'
|
||||
};
|
||||
}
|
||||
export function createNextApiEsmAliases() {
|
||||
const mapping = {
|
||||
error: 'next/dist/api/error',
|
||||
head: 'next/dist/api/head',
|
||||
image: 'next/dist/api/image',
|
||||
constants: 'next/dist/api/constants',
|
||||
router: 'next/dist/api/router',
|
||||
dynamic: 'next/dist/api/dynamic',
|
||||
script: 'next/dist/api/script',
|
||||
link: 'next/dist/api/link',
|
||||
form: 'next/dist/api/form',
|
||||
navigation: 'next/dist/api/navigation',
|
||||
headers: 'next/dist/api/headers',
|
||||
og: 'next/dist/api/og',
|
||||
server: 'next/dist/api/server',
|
||||
// pages api
|
||||
document: 'next/dist/api/document',
|
||||
app: 'next/dist/api/app'
|
||||
};
|
||||
const aliasMap = {};
|
||||
// Handle fully specified imports like `next/image.js`
|
||||
for (const [key, value] of Object.entries(mapping)){
|
||||
const nextApiFilePath = path.join(NEXT_PROJECT_ROOT, key);
|
||||
aliasMap[nextApiFilePath + '.js'] = value;
|
||||
}
|
||||
return aliasMap;
|
||||
}
|
||||
export function createAppRouterApiAliases(isServerOnlyLayer) {
|
||||
const mapping = {
|
||||
head: 'next/dist/client/components/noop-head',
|
||||
dynamic: 'next/dist/api/app-dynamic',
|
||||
link: 'next/dist/client/app-dir/link',
|
||||
form: 'next/dist/client/app-dir/form'
|
||||
};
|
||||
if (isServerOnlyLayer) {
|
||||
mapping['error'] = 'next/dist/api/error.react-server';
|
||||
mapping['navigation'] = 'next/dist/api/navigation.react-server';
|
||||
mapping['link'] = 'next/dist/client/app-dir/link.react-server';
|
||||
}
|
||||
const aliasMap = {};
|
||||
for (const [key, value] of Object.entries(mapping)){
|
||||
const nextApiFilePath = path.join(NEXT_PROJECT_ROOT, key);
|
||||
aliasMap[nextApiFilePath + '.js'] = value;
|
||||
}
|
||||
return aliasMap;
|
||||
}
|
||||
export function createVendoredReactAliases(bundledReactChannel, { layer, isBrowser, isEdgeServer, reactProductionProfiling }) {
|
||||
const environmentCondition = isBrowser ? 'browser' : isEdgeServer ? 'edge' : 'nodejs';
|
||||
const reactCondition = shouldUseReactServerCondition(layer) ? 'server' : 'client';
|
||||
// ✅ Correct alias
|
||||
// ❌ Incorrect alias i.e. importing this entrypoint should throw an error.
|
||||
// ❔ Alias that may produce correct code in certain conditions.Keep until react-markup is available.
|
||||
let reactAlias;
|
||||
if (environmentCondition === 'browser' && reactCondition === 'client') {
|
||||
// prettier-ignore
|
||||
reactAlias = {
|
||||
// file:///./../compiled/react/package.json
|
||||
react$: /* ✅ */ `next/dist/compiled/react${bundledReactChannel}`,
|
||||
'react/compiler-runtime$': /* ✅ */ `next/dist/compiled/react${bundledReactChannel}/compiler-runtime`,
|
||||
'react/jsx-dev-runtime$': /* ✅ */ `next/dist/compiled/react${bundledReactChannel}/jsx-dev-runtime`,
|
||||
'react/jsx-runtime$': /* ✅ */ `next/dist/compiled/react${bundledReactChannel}/jsx-runtime`,
|
||||
// file:///./../compiled/react-dom/package.json
|
||||
'react-dom$': /* ✅ */ `next/dist/compiled/react-dom${bundledReactChannel}`,
|
||||
'react-dom/client$': /* ✅ */ `next/dist/compiled/react-dom${bundledReactChannel}/client`,
|
||||
'react-dom/server$': /* ✅ */ `next/dist/compiled/react-dom${bundledReactChannel}/server.browser`,
|
||||
'react-dom/server.browser$': /* ✅ */ `next/dist/compiled/react-dom${bundledReactChannel}/server.browser`,
|
||||
// optimizations to ignore the legacy build of react-dom/server in `server.edge` build
|
||||
'react-dom/server.edge$': /* ❌ */ `next/dist/build/webpack/alias/react-dom-server${bundledReactChannel}.js`,
|
||||
'react-dom/static$': /* ✅ */ `next/dist/compiled/react-dom${bundledReactChannel}/static.browser`,
|
||||
'react-dom/static.browser$': /* ✅ */ `next/dist/compiled/react-dom${bundledReactChannel}/static.browser`,
|
||||
'react-dom/static.edge$': /* ✅ */ `next/dist/compiled/react-dom${bundledReactChannel}/static.edge`,
|
||||
// file:///./../compiled/react-server-dom-webpack/package.json
|
||||
'react-server-dom-webpack/client$': /* ✅ */ `next/dist/compiled/react-server-dom-webpack${bundledReactChannel}/client.browser`,
|
||||
'react-server-dom-webpack/server$': /* ❌ */ `next/dist/compiled/react-server-dom-webpack${bundledReactChannel}/server.browser`,
|
||||
'react-server-dom-webpack/server.node$': /* ❌ */ `next/dist/compiled/react-server-dom-webpack${bundledReactChannel}/server.node`,
|
||||
'react-server-dom-webpack/static$': /* ❌ */ `next/dist/compiled/react-server-dom-webpack${bundledReactChannel}/static.browser`
|
||||
};
|
||||
} else if (environmentCondition === 'browser' && reactCondition === 'server') {
|
||||
// prettier-ignore
|
||||
reactAlias = {
|
||||
// file:///./../compiled/react/package.json
|
||||
react$: /* ❌ */ `next/dist/compiled/react${bundledReactChannel}`,
|
||||
'react/compiler-runtime$': /* ❌ */ `next/dist/compiled/react${bundledReactChannel}/compiler-runtime`,
|
||||
'react/jsx-dev-runtime$': /* ❌ */ `next/dist/compiled/react${bundledReactChannel}/jsx-dev-runtime`,
|
||||
'react/jsx-runtime$': /* ❌ */ `next/dist/compiled/react${bundledReactChannel}/jsx-runtime`,
|
||||
// file:///./../compiled/react-dom/package.json
|
||||
'react-dom$': /* ❌ */ `next/dist/compiled/react-dom${bundledReactChannel}`,
|
||||
'react-dom/client$': /* ❌ */ `next/dist/compiled/react-dom${bundledReactChannel}/client`,
|
||||
'react-dom/server$': /* ❌ */ `next/dist/compiled/react-dom${bundledReactChannel}/server.browser`,
|
||||
'react-dom/server.browser$': /* ❌ */ `next/dist/compiled/react-dom${bundledReactChannel}/server.browser`,
|
||||
// optimizations to ignore the legacy build of react-dom/server in `server.edge` build
|
||||
'react-dom/server.edge$': /* ❌ */ `next/dist/build/webpack/alias/react-dom-server${bundledReactChannel}.js`,
|
||||
'react-dom/static$': /* ❌ */ `next/dist/compiled/react-dom${bundledReactChannel}/static.browser`,
|
||||
'react-dom/static.browser$': /* ❌ */ `next/dist/compiled/react-dom${bundledReactChannel}/static.browser`,
|
||||
'react-dom/static.edge$': /* ❌ */ `next/dist/compiled/react-dom${bundledReactChannel}/static.edge`,
|
||||
// file:///./../compiled/react-server-dom-webpack/package.json
|
||||
'react-server-dom-webpack/client$': /* ✅ */ `next/dist/compiled/react-server-dom-webpack${bundledReactChannel}/client.browser`,
|
||||
'react-server-dom-webpack/server$': /* ✅ */ `next/dist/compiled/react-server-dom-webpack${bundledReactChannel}/server.browser`,
|
||||
'react-server-dom-webpack/server.node$': /* ❌ */ `next/dist/compiled/react-server-dom-webpack${bundledReactChannel}/server.node`,
|
||||
'react-server-dom-webpack/static$': /* ✅ */ `next/dist/compiled/react-server-dom-webpack${bundledReactChannel}/static.browser`
|
||||
};
|
||||
} else if (environmentCondition === 'nodejs' && reactCondition === 'client') {
|
||||
// prettier-ignore
|
||||
reactAlias = {
|
||||
// file:///./../compiled/react/package.json
|
||||
react$: /* ✅ */ `next/dist/server/route-modules/app-page/vendored/ssr/react`,
|
||||
'react/compiler-runtime$': /* ✅ */ `next/dist/server/route-modules/app-page/vendored/ssr/react-compiler-runtime`,
|
||||
'react/jsx-dev-runtime$': /* ✅ */ `next/dist/server/route-modules/app-page/vendored/ssr/react-jsx-dev-runtime`,
|
||||
'react/jsx-runtime$': /* ✅ */ `next/dist/server/route-modules/app-page/vendored/ssr/react-jsx-runtime`,
|
||||
// file:///./../compiled/react-dom/package.json
|
||||
'react-dom$': /* ✅ */ `next/dist/server/route-modules/app-page/vendored/ssr/react-dom`,
|
||||
'react-dom/client$': /* ❔ */ `next/dist/compiled/react-dom${bundledReactChannel}/client`,
|
||||
'react-dom/server$': /* ❔ */ `next/dist/compiled/react-dom${bundledReactChannel}/server.node`,
|
||||
'react-dom/server.browser$': /* ❔ */ `next/dist/compiled/react-dom${bundledReactChannel}/server.browser`,
|
||||
// optimizations to ignore the legacy build of react-dom/server in `server.edge` build
|
||||
'react-dom/server.edge$': /* ✅ */ `next/dist/build/webpack/alias/react-dom-server${bundledReactChannel}.js`,
|
||||
'react-dom/static$': /* ❔ */ `next/dist/compiled/react-dom${bundledReactChannel}/static.node`,
|
||||
'react-dom/static.browser$': /* ❔ */ `next/dist/compiled/react-dom${bundledReactChannel}/static.browser`,
|
||||
'react-dom/static.edge$': /* ❔ */ `next/dist/compiled/react-dom${bundledReactChannel}/static.edge`,
|
||||
// file:///./../compiled/react-server-dom-webpack/package.json
|
||||
'react-server-dom-webpack/client$': /* ✅ */ `next/dist/server/route-modules/app-page/vendored/ssr/react-server-dom-webpack-client`,
|
||||
'react-server-dom-webpack/server$': /* ❌ */ `next/dist/compiled/react-server-dom-webpack${bundledReactChannel}/server.node`,
|
||||
'react-server-dom-webpack/server.node$': /* ❌ */ `next/dist/compiled/react-server-dom-webpack${bundledReactChannel}/server.node`,
|
||||
'react-server-dom-webpack/static$': /* ❌ */ `next/dist/compiled/react-server-dom-webpack${bundledReactChannel}/static.node`
|
||||
};
|
||||
} else if (environmentCondition === 'nodejs' && reactCondition === 'server') {
|
||||
// prettier-ignore
|
||||
reactAlias = {
|
||||
// file:///./../compiled/react/package.json
|
||||
react$: /* ✅ */ `next/dist/server/route-modules/app-page/vendored/rsc/react`,
|
||||
'react/compiler-runtime$': /* ✅ */ `next/dist/server/route-modules/app-page/vendored/rsc/react-compiler-runtime`,
|
||||
'react/jsx-dev-runtime$': /* ✅ */ `next/dist/server/route-modules/app-page/vendored/rsc/react-jsx-dev-runtime`,
|
||||
'react/jsx-runtime$': /* ✅ */ `next/dist/server/route-modules/app-page/vendored/rsc/react-jsx-runtime`,
|
||||
// file:///./../compiled/react-dom/package.json
|
||||
'react-dom$': /* ✅ */ `next/dist/server/route-modules/app-page/vendored/rsc/react-dom`,
|
||||
'react-dom/client$': /* ❌ */ `next/dist/compiled/react-dom${bundledReactChannel}/client`,
|
||||
'react-dom/server$': /* ❌ */ `next/dist/compiled/react-dom${bundledReactChannel}/server.node`,
|
||||
'react-dom/server.browser$': /* ❌ */ `next/dist/compiled/react-dom${bundledReactChannel}/server.browser`,
|
||||
// optimizations to ignore the legacy build of react-dom/server in `server.edge` build
|
||||
'react-dom/server.edge$': /* ❌ */ `next/dist/build/webpack/alias/react-dom-server${bundledReactChannel}.js`,
|
||||
'react-dom/static$': /* ❌ */ `next/dist/compiled/react-dom${bundledReactChannel}/static.node`,
|
||||
'react-dom/static.browser$': /* ❌ */ `next/dist/compiled/react-dom${bundledReactChannel}/static.browser`,
|
||||
'react-dom/static.edge$': /* ❌ */ `next/dist/compiled/react-dom${bundledReactChannel}/static.edge`,
|
||||
// file:///./../compiled/react-server-dom-webpack/package.json
|
||||
'react-server-dom-webpack/client$': /* ❔ */ `next/dist/compiled/react-server-dom-webpack${bundledReactChannel}/client.node`,
|
||||
'react-server-dom-webpack/server$': /* ✅ */ `next/dist/server/route-modules/app-page/vendored/rsc/react-server-dom-webpack-server`,
|
||||
'react-server-dom-webpack/server.node$': /* ✅ */ `next/dist/server/route-modules/app-page/vendored/rsc/react-server-dom-webpack-server`,
|
||||
'react-server-dom-webpack/static$': /* ✅ */ `next/dist/server/route-modules/app-page/vendored/rsc/react-server-dom-webpack-static`
|
||||
};
|
||||
} else if (environmentCondition === 'edge' && reactCondition === 'client') {
|
||||
// prettier-ignore
|
||||
reactAlias = {
|
||||
// file:///./../compiled/react/package.json
|
||||
react$: /* ✅ */ `next/dist/compiled/react${bundledReactChannel}`,
|
||||
'react/compiler-runtime$': /* ✅ */ `next/dist/compiled/react${bundledReactChannel}/compiler-runtime`,
|
||||
'react/jsx-dev-runtime$': /* ✅ */ `next/dist/compiled/react${bundledReactChannel}/jsx-dev-runtime`,
|
||||
'react/jsx-runtime$': /* ✅ */ `next/dist/compiled/react${bundledReactChannel}/jsx-runtime`,
|
||||
// file:///./../compiled/react-dom/package.json
|
||||
'react-dom$': /* ✅ */ `next/dist/compiled/react-dom${bundledReactChannel}`,
|
||||
'react-dom/client$': /* ✅ */ `next/dist/compiled/react-dom${bundledReactChannel}/client`,
|
||||
'react-dom/server$': /* ✅ */ `next/dist/build/webpack/alias/react-dom-server${bundledReactChannel}.js`,
|
||||
'react-dom/server.browser$': /* ✅ */ `next/dist/compiled/react-dom${bundledReactChannel}/server.browser`,
|
||||
// optimizations to ignore the legacy build of react-dom/server in `server.edge` build
|
||||
'react-dom/server.edge$': /* ✅ */ `next/dist/build/webpack/alias/react-dom-server${bundledReactChannel}.js`,
|
||||
'react-dom/static$': /* ✅ */ `next/dist/compiled/react-dom${bundledReactChannel}/static.edge`,
|
||||
'react-dom/static.browser$': /* ✅ */ `next/dist/compiled/react-dom${bundledReactChannel}/static.browser`,
|
||||
'react-dom/static.edge$': /* ✅ */ `next/dist/compiled/react-dom${bundledReactChannel}/static.edge`,
|
||||
// file:///./../compiled/react-server-dom-webpack/package.json
|
||||
'react-server-dom-webpack/client$': /* ✅ */ `next/dist/compiled/react-server-dom-webpack${bundledReactChannel}/client.edge`,
|
||||
'react-server-dom-webpack/server$': /* ❌ */ `next/dist/compiled/react-server-dom-webpack${bundledReactChannel}/server.edge`,
|
||||
'react-server-dom-webpack/server.node$': /* ❌ */ `next/dist/compiled/react-server-dom-webpack${bundledReactChannel}/server.node`,
|
||||
'react-server-dom-webpack/static$': /* ❌ */ `next/dist/compiled/react-server-dom-webpack${bundledReactChannel}/static.edge`
|
||||
};
|
||||
} else if (environmentCondition === 'edge' && reactCondition === 'server') {
|
||||
// prettier-ignore
|
||||
reactAlias = {
|
||||
// file:///./../compiled/react/package.json
|
||||
react$: /* ✅ */ `next/dist/compiled/react${bundledReactChannel}/react.react-server`,
|
||||
'react/compiler-runtime$': /* ❌ */ `next/dist/compiled/react${bundledReactChannel}/compiler-runtime`,
|
||||
'react/jsx-dev-runtime$': /* ✅ */ `next/dist/compiled/react${bundledReactChannel}/jsx-dev-runtime.react-server`,
|
||||
'react/jsx-runtime$': /* ✅ */ `next/dist/compiled/react${bundledReactChannel}/jsx-runtime.react-server`,
|
||||
// file:///./../compiled/react-dom/package.json
|
||||
'react-dom$': /* ✅ */ `next/dist/compiled/react-dom${bundledReactChannel}/react-dom.react-server`,
|
||||
'react-dom/client$': /* ❌ */ `next/dist/compiled/react-dom${bundledReactChannel}/client`,
|
||||
'react-dom/server$': /* ❌ */ `next/dist/build/webpack/alias/react-dom-server${bundledReactChannel}.js`,
|
||||
'react-dom/server.browser$': /* ❌ */ `next/dist/compiled/react-dom${bundledReactChannel}/server.browser`,
|
||||
// optimizations to ignore the legacy build of react-dom/server in `server.edge` build
|
||||
'react-dom/server.edge$': /* ❌ */ `next/dist/build/webpack/alias/react-dom-server${bundledReactChannel}.js`,
|
||||
'react-dom/static$': /* ❌ */ `next/dist/compiled/react-dom${bundledReactChannel}/static.edge`,
|
||||
'react-dom/static.browser$': /* ❌ */ `next/dist/compiled/react-dom${bundledReactChannel}/static.browser`,
|
||||
'react-dom/static.edge$': /* ❌ */ `next/dist/compiled/react-dom${bundledReactChannel}/static.edge`,
|
||||
// file:///./../compiled/react-server-dom-webpack/package.json
|
||||
'react-server-dom-webpack/client$': /* ❔ */ `next/dist/compiled/react-server-dom-webpack${bundledReactChannel}/client.edge`,
|
||||
'react-server-dom-webpack/server$': /* ✅ */ `next/dist/compiled/react-server-dom-webpack${bundledReactChannel}/server.edge`,
|
||||
'react-server-dom-webpack/server.node$': /* ✅ */ `next/dist/compiled/react-server-dom-webpack${bundledReactChannel}/server.node`,
|
||||
'react-server-dom-webpack/static$': /* ✅ */ `next/dist/compiled/react-server-dom-webpack${bundledReactChannel}/static.edge`
|
||||
};
|
||||
// prettier-ignore
|
||||
reactAlias[`next/dist/compiled/react${bundledReactChannel}$`] = reactAlias[`react$`];
|
||||
// prettier-ignore
|
||||
reactAlias[`next/dist/compiled/react${bundledReactChannel}/compiler-runtime$`] = reactAlias[`react/compiler-runtime$`];
|
||||
// prettier-ignore
|
||||
reactAlias[`next/dist/compiled/react${bundledReactChannel}/jsx-dev-runtime$`] = reactAlias[`react/jsx-dev-runtime$`];
|
||||
// prettier-ignore
|
||||
reactAlias[`next/dist/compiled/react${bundledReactChannel}/jsx-runtime$`] = reactAlias[`react/jsx-runtime$`];
|
||||
// prettier-ignore
|
||||
reactAlias[`next/dist/compiled/react-dom${bundledReactChannel}$`] = reactAlias[`react-dom$`];
|
||||
} else {
|
||||
throw Object.defineProperty(new Error(`Unsupported environment condition "${environmentCondition}" and react condition "${reactCondition}". This is a bug in Next.js.`), "__NEXT_ERROR_CODE", {
|
||||
value: "E717",
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
}
|
||||
if (reactProductionProfiling) {
|
||||
reactAlias['react-dom/client$'] = `next/dist/compiled/react-dom${bundledReactChannel}/profiling`;
|
||||
}
|
||||
const alias = reactAlias;
|
||||
alias['@vercel/turbopack-ecmascript-runtime/browser/dev/hmr-client/hmr-client.ts'] = `next/dist/client/dev/noop-turbopack-hmr`;
|
||||
return alias;
|
||||
}
|
||||
// Insert aliases for Next.js stubs of fetch, object-assign, and url
|
||||
// Keep in sync with insert_optimized_module_aliases in import_map.rs
|
||||
export function getOptimizedModuleAliases() {
|
||||
return {
|
||||
unfetch: require.resolve('next/dist/build/polyfills/fetch/index.js'),
|
||||
'isomorphic-unfetch': require.resolve('next/dist/build/polyfills/fetch/index.js'),
|
||||
'whatwg-fetch': require.resolve('next/dist/build/polyfills/fetch/whatwg-fetch.js'),
|
||||
'object-assign': require.resolve('next/dist/build/polyfills/object-assign.js'),
|
||||
'object.assign/auto': require.resolve('next/dist/build/polyfills/object.assign/auto.js'),
|
||||
'object.assign/implementation': require.resolve('next/dist/build/polyfills/object.assign/implementation.js'),
|
||||
'object.assign/polyfill': require.resolve('next/dist/build/polyfills/object.assign/polyfill.js'),
|
||||
'object.assign/shim': require.resolve('next/dist/build/polyfills/object.assign/shim.js'),
|
||||
url: require.resolve('next/dist/compiled/native-url')
|
||||
};
|
||||
}
|
||||
function getReactProfilingInProduction() {
|
||||
return {
|
||||
'react-dom/client$': 'react-dom/profiling'
|
||||
};
|
||||
}
|
||||
|
||||
//# sourceMappingURL=create-compiler-aliases.js.map
|
||||
+1
File diff suppressed because one or more lines are too long
+240
@@ -0,0 +1,240 @@
|
||||
import path from 'node:path';
|
||||
import { needsExperimentalReact } from '../lib/needs-experimental-react';
|
||||
import { checkIsAppPPREnabled } from '../server/lib/experimental/ppr';
|
||||
import { getNextConfigEnv, getNextPublicEnvironmentVariables } from '../lib/static-env';
|
||||
const DEFINE_ENV_EXPRESSION = Symbol('DEFINE_ENV_EXPRESSION');
|
||||
/**
|
||||
* Serializes the DefineEnv config so that it can be inserted into the code by Webpack/Turbopack, JSON stringifies each value.
|
||||
*/ function serializeDefineEnv(defineEnv) {
|
||||
const defineEnvStringified = Object.fromEntries(Object.entries(defineEnv).map(([key, value])=>[
|
||||
key,
|
||||
typeof value === 'object' && DEFINE_ENV_EXPRESSION in value ? value[DEFINE_ENV_EXPRESSION] : JSON.stringify(value)
|
||||
]));
|
||||
return defineEnvStringified;
|
||||
}
|
||||
function getImageConfig(config, dev) {
|
||||
var _config_images, _config_images1, _config_images2;
|
||||
return {
|
||||
'process.env.__NEXT_IMAGE_OPTS': {
|
||||
deviceSizes: config.images.deviceSizes,
|
||||
imageSizes: config.images.imageSizes,
|
||||
qualities: config.images.qualities,
|
||||
path: config.images.path,
|
||||
loader: config.images.loader,
|
||||
dangerouslyAllowSVG: config.images.dangerouslyAllowSVG,
|
||||
unoptimized: config == null ? void 0 : (_config_images = config.images) == null ? void 0 : _config_images.unoptimized,
|
||||
...dev ? {
|
||||
// additional config in dev to allow validating on the client
|
||||
domains: config.images.domains,
|
||||
remotePatterns: (_config_images1 = config.images) == null ? void 0 : _config_images1.remotePatterns,
|
||||
localPatterns: (_config_images2 = config.images) == null ? void 0 : _config_images2.localPatterns,
|
||||
output: config.output
|
||||
} : {}
|
||||
}
|
||||
};
|
||||
}
|
||||
export function getDefineEnv({ isTurbopack, clientRouterFilters, config, dev, distDir, projectPath, fetchCacheKeyPrefix, hasRewrites, isClient, isEdgeServer, isNodeServer, middlewareMatchers, omitNonDeterministic, rewrites }) {
|
||||
var _config_experimental, _config_experimental1, _config_experimental_staleTimes, _config_experimental_staleTimes1, _config_experimental_staleTimes2, _config_experimental_staleTimes3, _config_i18n, _config_compiler;
|
||||
const nextPublicEnv = getNextPublicEnvironmentVariables();
|
||||
const nextConfigEnv = getNextConfigEnv(config);
|
||||
const isPPREnabled = checkIsAppPPREnabled(config.experimental.ppr);
|
||||
const isCacheComponentsEnabled = !!config.cacheComponents;
|
||||
const isUseCacheEnabled = !!config.experimental.useCache;
|
||||
const defineEnv = {
|
||||
// internal field to identify the plugin config
|
||||
__NEXT_DEFINE_ENV: true,
|
||||
...nextPublicEnv,
|
||||
...nextConfigEnv,
|
||||
...!isEdgeServer ? {} : {
|
||||
EdgeRuntime: /**
|
||||
* Cloud providers can set this environment variable to allow users
|
||||
* and library authors to have different implementations based on
|
||||
* the runtime they are running with, if it's not using `edge-runtime`
|
||||
*/ process.env.NEXT_EDGE_RUNTIME_PROVIDER ?? 'edge-runtime',
|
||||
// process should be only { env: {...} } for edge runtime.
|
||||
// For ignore avoid warn on `process.emit` usage but directly omit it.
|
||||
'process.emit': false
|
||||
},
|
||||
'process.turbopack': isTurbopack,
|
||||
'process.env.TURBOPACK': isTurbopack,
|
||||
'process.env.__NEXT_BUNDLER': isTurbopack ? 'Turbopack' : process.env.NEXT_RSPACK ? 'Rspack' : 'Webpack',
|
||||
// TODO: enforce `NODE_ENV` on `process.env`, and add a test:
|
||||
'process.env.NODE_ENV': dev || config.experimental.allowDevelopmentBuild ? 'development' : 'production',
|
||||
'process.env.__NEXT_DEV_SERVER': dev ? '1' : '',
|
||||
'process.env.NEXT_RUNTIME': isEdgeServer ? 'edge' : isNodeServer ? 'nodejs' : '',
|
||||
'process.env.NEXT_MINIMAL': '',
|
||||
'process.env.__NEXT_APP_NAV_FAIL_HANDLING': Boolean(config.experimental.appNavFailHandling),
|
||||
'process.env.__NEXT_APP_NEW_SCROLL_HANDLER': Boolean(config.experimental.appNewScrollHandler),
|
||||
'process.env.__NEXT_PPR': isPPREnabled,
|
||||
'process.env.__NEXT_CACHE_COMPONENTS': isCacheComponentsEnabled,
|
||||
'process.env.__NEXT_EXPERIMENTAL_CACHED_NAVIGATIONS': Boolean(config.experimental.cachedNavigations),
|
||||
'process.env.__NEXT_INSTANT_NAV_TOGGLE': !!config.experimental.instantNavigationDevToolsToggle,
|
||||
'process.env.__NEXT_USE_CACHE': isUseCacheEnabled,
|
||||
'process.env.NEXT_IMMUTABLE_ASSET_TOKEN': config.experimental.immutableAssetToken || '',
|
||||
...((_config_experimental = config.experimental) == null ? void 0 : _config_experimental.useSkewCookie) || !config.deploymentId ? {
|
||||
'process.env.NEXT_DEPLOYMENT_ID': false
|
||||
} : isClient ? isTurbopack ? {
|
||||
// This is set at runtime by packages/next/src/client/register-deployment-id-global.ts
|
||||
'process.env.NEXT_DEPLOYMENT_ID': {
|
||||
[DEFINE_ENV_EXPRESSION]: 'globalThis.NEXT_DEPLOYMENT_ID'
|
||||
}
|
||||
} : {
|
||||
// For Webpack, we currently don't use the non-inlining globalThis.NEXT_DEPLOYMENT_ID
|
||||
// approach because we cannot forward this global variable to web workers easily.
|
||||
'process.env.NEXT_DEPLOYMENT_ID': config.deploymentId || false
|
||||
} : ((_config_experimental1 = config.experimental) == null ? void 0 : _config_experimental1.runtimeServerDeploymentId) ? {
|
||||
} : {
|
||||
'process.env.NEXT_DEPLOYMENT_ID': config.deploymentId || false
|
||||
},
|
||||
// Propagates the `__NEXT_EXPERIMENTAL_STATIC_SHELL_DEBUGGING` environment
|
||||
// variable to the client.
|
||||
'process.env.__NEXT_EXPERIMENTAL_STATIC_SHELL_DEBUGGING': process.env.__NEXT_EXPERIMENTAL_STATIC_SHELL_DEBUGGING || false,
|
||||
'process.env.__NEXT_FETCH_CACHE_KEY_PREFIX': fetchCacheKeyPrefix ?? '',
|
||||
...isTurbopack ? {} : {
|
||||
'process.env.__NEXT_MIDDLEWARE_MATCHERS': middlewareMatchers ?? []
|
||||
},
|
||||
'process.env.__NEXT_MANUAL_CLIENT_BASE_PATH': config.experimental.manualClientBasePath ?? false,
|
||||
'process.env.__NEXT_CLIENT_ROUTER_DYNAMIC_STALETIME': JSON.stringify(isNaN(Number((_config_experimental_staleTimes = config.experimental.staleTimes) == null ? void 0 : _config_experimental_staleTimes.dynamic)) ? 0 : (_config_experimental_staleTimes1 = config.experimental.staleTimes) == null ? void 0 : _config_experimental_staleTimes1.dynamic),
|
||||
'process.env.__NEXT_CLIENT_ROUTER_STATIC_STALETIME': JSON.stringify(isNaN(Number((_config_experimental_staleTimes2 = config.experimental.staleTimes) == null ? void 0 : _config_experimental_staleTimes2.static)) ? 5 * 60 // 5 minutes
|
||||
: (_config_experimental_staleTimes3 = config.experimental.staleTimes) == null ? void 0 : _config_experimental_staleTimes3.static),
|
||||
'process.env.__NEXT_CLIENT_ROUTER_FILTER_ENABLED': config.experimental.clientRouterFilter ?? true,
|
||||
'process.env.__NEXT_CLIENT_ROUTER_S_FILTER': (clientRouterFilters == null ? void 0 : clientRouterFilters.staticFilter) ?? false,
|
||||
'process.env.__NEXT_CLIENT_ROUTER_D_FILTER': (clientRouterFilters == null ? void 0 : clientRouterFilters.dynamicFilter) ?? false,
|
||||
'process.env.__NEXT_CLIENT_VALIDATE_RSC_REQUEST_HEADERS': Boolean(config.experimental.validateRSCRequestHeaders),
|
||||
'process.env.__NEXT_DYNAMIC_ON_HOVER': Boolean(config.experimental.dynamicOnHover),
|
||||
'process.env.__NEXT_PREFETCH_INLINING': Boolean(config.experimental.prefetchInlining),
|
||||
'process.env.__NEXT_OPTIMISTIC_CLIENT_CACHE': config.experimental.optimisticClientCache ?? true,
|
||||
'process.env.__NEXT_MIDDLEWARE_PREFETCH': config.experimental.proxyPrefetch ?? 'flexible',
|
||||
'process.env.__NEXT_CROSS_ORIGIN': config.crossOrigin,
|
||||
'process.browser': isClient,
|
||||
'process.env.__NEXT_TEST_MODE': process.env.__NEXT_TEST_MODE ?? false,
|
||||
// This is used in client/dev-error-overlay/hot-dev-client.js to replace the dist directory
|
||||
...dev && (isClient ?? isEdgeServer) ? {
|
||||
'process.env.__NEXT_DIST_DIR': distDir
|
||||
} : {},
|
||||
// This is used in devtools to strip the project path in edge runtime,
|
||||
// as there's only a dummy `dir` value (`.`) as edge runtime doesn't have concept of file system.
|
||||
...dev && isEdgeServer ? {
|
||||
'process.env.__NEXT_EDGE_PROJECT_DIR': isTurbopack ? path.relative(process.cwd(), projectPath) : projectPath
|
||||
} : {},
|
||||
'process.env.__NEXT_BASE_PATH': config.basePath,
|
||||
'process.env.__NEXT_CASE_SENSITIVE_ROUTES': Boolean(config.experimental.caseSensitiveRoutes),
|
||||
'process.env.__NEXT_REWRITES': rewrites,
|
||||
'process.env.__NEXT_TRAILING_SLASH': config.trailingSlash,
|
||||
'process.env.__NEXT_DEV_INDICATOR': config.devIndicators !== false,
|
||||
'process.env.__NEXT_DEV_INDICATOR_POSITION': config.devIndicators === false ? 'bottom-left' // This will not be used as the indicator is disabled.
|
||||
: config.devIndicators.position ?? 'bottom-left',
|
||||
'process.env.__NEXT_STRICT_MODE': config.reactStrictMode === null ? false : config.reactStrictMode,
|
||||
'process.env.__NEXT_STRICT_MODE_APP': // When next.config.js does not have reactStrictMode it's enabled by default.
|
||||
config.reactStrictMode === null ? true : config.reactStrictMode,
|
||||
'process.env.__NEXT_OPTIMIZE_CSS': (config.experimental.optimizeCss && !dev) ?? false,
|
||||
'process.env.__NEXT_SCRIPT_WORKERS': (config.experimental.nextScriptWorkers && !dev) ?? false,
|
||||
'process.env.__NEXT_SCROLL_RESTORATION': config.experimental.scrollRestoration ?? false,
|
||||
...getImageConfig(config, dev),
|
||||
'process.env.__NEXT_ROUTER_BASEPATH': config.basePath,
|
||||
'process.env.__NEXT_HAS_REWRITES': hasRewrites,
|
||||
'process.env.__NEXT_CONFIG_OUTPUT': config.output,
|
||||
'process.env.__NEXT_I18N_SUPPORT': !!config.i18n,
|
||||
'process.env.__NEXT_I18N_DOMAINS': ((_config_i18n = config.i18n) == null ? void 0 : _config_i18n.domains) ?? false,
|
||||
'process.env.__NEXT_I18N_CONFIG': config.i18n || '',
|
||||
'process.env.__NEXT_NO_MIDDLEWARE_URL_NORMALIZE': config.skipProxyUrlNormalize,
|
||||
'process.env.__NEXT_EXTERNAL_MIDDLEWARE_REWRITE_RESOLVE': config.experimental.externalProxyRewritesResolve ?? false,
|
||||
'process.env.__NEXT_MANUAL_TRAILING_SLASH': config.skipTrailingSlashRedirect,
|
||||
'process.env.__NEXT_HAS_WEB_VITALS_ATTRIBUTION': (config.experimental.webVitalsAttribution && config.experimental.webVitalsAttribution.length > 0) ?? false,
|
||||
'process.env.__NEXT_WEB_VITALS_ATTRIBUTION': config.experimental.webVitalsAttribution ?? false,
|
||||
'process.env.__NEXT_LINK_NO_TOUCH_START': config.experimental.linkNoTouchStart ?? false,
|
||||
'process.env.__NEXT_ASSET_PREFIX': config.assetPrefix,
|
||||
'process.env.__NEXT_EXPERIMENTAL_AUTH_INTERRUPTS': !!config.experimental.authInterrupts,
|
||||
'process.env.__NEXT_TELEMETRY_DISABLED': Boolean(process.env.NEXT_TELEMETRY_DISABLED),
|
||||
...isNodeServer || isEdgeServer ? {
|
||||
// Fix bad-actors in the npm ecosystem (e.g. `node-formidable`)
|
||||
// This is typically found in unmaintained modules from the
|
||||
// pre-webpack era (common in server-side code)
|
||||
'global.GENTLY': false
|
||||
} : undefined,
|
||||
...isNodeServer || isEdgeServer ? {
|
||||
'process.env.__NEXT_EXPERIMENTAL_REACT': needsExperimentalReact(config)
|
||||
} : undefined,
|
||||
'process.env.__NEXT_MULTI_ZONE_DRAFT_MODE': config.experimental.multiZoneDraftMode ?? false,
|
||||
'process.env.__NEXT_TRUST_HOST_HEADER': config.experimental.trustHostHeader ?? false,
|
||||
'process.env.__NEXT_ALLOWED_REVALIDATE_HEADERS': config.experimental.allowedRevalidateHeaderKeys ?? [],
|
||||
...isNodeServer || isEdgeServer ? {
|
||||
'process.env.__NEXT_RELATIVE_DIST_DIR': config.distDir,
|
||||
'process.env.__NEXT_RELATIVE_PROJECT_DIR': path.relative(process.cwd(), projectPath)
|
||||
} : {},
|
||||
'process.env.__NEXT_BROWSER_DEBUG_INFO_IN_TERMINAL': JSON.stringify(config.logging && config.logging.browserToTerminal || false),
|
||||
'process.env.__NEXT_MCP_SERVER': !!config.experimental.mcpServer,
|
||||
// The devtools need to know whether or not to show an option to clear the
|
||||
// bundler cache. This option may be removed later once Turbopack's
|
||||
// filesystem cache feature is more stable.
|
||||
//
|
||||
// This environment value is currently best-effort:
|
||||
// - It's possible to disable the webpack filesystem cache, but it's
|
||||
// unlikely for a user to do that.
|
||||
// - Rspack's filesystem cache is unstable and requires a different
|
||||
// configuration than webpack to enable (which we don't do).
|
||||
//
|
||||
// In the worst case we'll show an option to clear the cache, but it'll be a
|
||||
// no-op that just restarts the development server.
|
||||
'process.env.__NEXT_BUNDLER_HAS_PERSISTENT_CACHE': !isTurbopack || (config.experimental.turbopackFileSystemCacheForDev ?? false),
|
||||
'process.env.__NEXT_REACT_DEBUG_CHANNEL': config.experimental.reactDebugChannel ?? false,
|
||||
'process.env.__NEXT_TRANSITION_INDICATOR': config.experimental.transitionIndicator ?? false,
|
||||
'process.env.__NEXT_GESTURE_TRANSITION': config.experimental.gestureTransition ?? false,
|
||||
'process.env.__NEXT_OPTIMISTIC_ROUTING': config.experimental.optimisticRouting ?? false,
|
||||
'process.env.__NEXT_VARY_PARAMS': config.experimental.varyParams ?? false,
|
||||
'process.env.__NEXT_EXPOSE_TESTING_API': dev || config.experimental.exposeTestingApiInProductionBuild === true,
|
||||
'process.env.__NEXT_CACHE_LIFE': config.cacheLife,
|
||||
'process.env.__NEXT_CLIENT_PARAM_PARSING_ORIGINS': config.experimental.clientParamParsingOrigins || []
|
||||
};
|
||||
const userDefines = ((_config_compiler = config.compiler) == null ? void 0 : _config_compiler.define) ?? {};
|
||||
for(const key in userDefines){
|
||||
if (defineEnv.hasOwnProperty(key)) {
|
||||
throw Object.defineProperty(new Error(`The \`compiler.define\` option is configured to replace the \`${key}\` variable. This variable is either part of a Next.js built-in or is already configured.`), "__NEXT_ERROR_CODE", {
|
||||
value: "E688",
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
}
|
||||
defineEnv[key] = userDefines[key];
|
||||
}
|
||||
if (isNodeServer || isEdgeServer) {
|
||||
var _config_compiler1;
|
||||
const userDefinesServer = ((_config_compiler1 = config.compiler) == null ? void 0 : _config_compiler1.defineServer) ?? {};
|
||||
for(const key in userDefinesServer){
|
||||
if (defineEnv.hasOwnProperty(key)) {
|
||||
throw Object.defineProperty(new Error(`The \`compiler.defineServer\` option is configured to replace the \`${key}\` variable. This variable is either part of a Next.js built-in or is already configured.`), "__NEXT_ERROR_CODE", {
|
||||
value: "E689",
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
}
|
||||
defineEnv[key] = userDefinesServer[key];
|
||||
}
|
||||
}
|
||||
const serializedDefineEnv = serializeDefineEnv(defineEnv);
|
||||
// we delay inlining these values until after the build
|
||||
// with flying shuttle enabled so we can update them
|
||||
// without invalidating entries
|
||||
if (!dev && omitNonDeterministic) {
|
||||
// client uses window. instead of leaving process.env
|
||||
// in case process isn't polyfilled on client already
|
||||
// since by this point it won't be added by webpack
|
||||
const safeKey = (key)=>isClient ? `window.${key.split('.').pop()}` : key;
|
||||
for(const key in nextPublicEnv){
|
||||
serializedDefineEnv[key] = safeKey(key);
|
||||
}
|
||||
for(const key in nextConfigEnv){
|
||||
serializedDefineEnv[key] = safeKey(key);
|
||||
}
|
||||
if (!config.experimental.runtimeServerDeploymentId) {
|
||||
for (const key of [
|
||||
'process.env.NEXT_DEPLOYMENT_ID'
|
||||
]){
|
||||
serializedDefineEnv[key] = safeKey(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
return serializedDefineEnv;
|
||||
}
|
||||
|
||||
//# sourceMappingURL=define-env.js.map
|
||||
+1
File diff suppressed because one or more lines are too long
+97
@@ -0,0 +1,97 @@
|
||||
// Time thresholds in seconds
|
||||
const SECONDS_IN_MINUTE = 60;
|
||||
const MINUTES_THRESHOLD_SECONDS = 120 // 2 minutes
|
||||
;
|
||||
const SECONDS_THRESHOLD_HIGH = 40;
|
||||
const SECONDS_THRESHOLD_LOW = 2;
|
||||
const MILLISECONDS_PER_SECOND = 1000;
|
||||
// Time thresholds and conversion factors for nanoseconds
|
||||
const NANOSECONDS_PER_SECOND = 1000000000;
|
||||
const NANOSECONDS_PER_MILLISECOND = 1000000;
|
||||
const NANOSECONDS_PER_MICROSECOND = 1000;
|
||||
const NANOSECONDS_IN_MINUTE = 60000000000 // 60 * 1_000_000_000
|
||||
;
|
||||
const MINUTES_THRESHOLD_NANOSECONDS = 120000000000 // 2 minutes in nanoseconds
|
||||
;
|
||||
const SECONDS_THRESHOLD_HIGH_NANOSECONDS = 40000000000 // 40 seconds in nanoseconds
|
||||
;
|
||||
const SECONDS_THRESHOLD_LOW_NANOSECONDS = 2000000000 // 2 seconds in nanoseconds
|
||||
;
|
||||
const MILLISECONDS_THRESHOLD_NANOSECONDS = 2000000 // 2 milliseconds in nanoseconds
|
||||
;
|
||||
/**
|
||||
* Converts a duration in seconds to a human-readable string format.
|
||||
* Formats duration based on magnitude for optimal readability:
|
||||
* - >= 2 minutes: show in minutes with 1 decimal place (e.g., "2.5min")
|
||||
* - >= 40 seconds: show in whole seconds (e.g., "45s")
|
||||
* - >= 2 seconds: show in seconds with 1 decimal place (e.g., "3.2s")
|
||||
* - < 2 seconds: show in whole milliseconds (e.g., "1500ms")
|
||||
*
|
||||
* @deprecated Use durationToStringWithNanoseconds instead, collect time in nanoseconds using process.hrtime.bigint().
|
||||
* @param compilerDuration - Duration in seconds as a number
|
||||
* @returns Formatted duration string with appropriate unit and precision
|
||||
*/ export function durationToString(compilerDuration) {
|
||||
if (compilerDuration > MINUTES_THRESHOLD_SECONDS) {
|
||||
return `${(compilerDuration / SECONDS_IN_MINUTE).toFixed(1)}min`;
|
||||
} else if (compilerDuration > SECONDS_THRESHOLD_HIGH) {
|
||||
return `${compilerDuration.toFixed(0)}s`;
|
||||
} else if (compilerDuration > SECONDS_THRESHOLD_LOW) {
|
||||
return `${compilerDuration.toFixed(1)}s`;
|
||||
} else {
|
||||
return `${(compilerDuration * MILLISECONDS_PER_SECOND).toFixed(0)}ms`;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Converts a nanosecond duration to a human-readable string format.
|
||||
* Formats duration based on magnitude for optimal readability:
|
||||
* - >= 2 minutes: show in minutes with 1 decimal place (e.g., "2.5min")
|
||||
* - >= 40 seconds: show in whole seconds (e.g., "45s")
|
||||
* - >= 2 seconds: show in seconds with 1 decimal place (e.g., "3.2s")
|
||||
* - >= 2 milliseconds: show in whole milliseconds (e.g., "250ms")
|
||||
* - < 2 milliseconds: show in whole microseconds (e.g., "500µs")
|
||||
*
|
||||
* @param durationBigInt - Duration in nanoseconds as a BigInt
|
||||
* @returns Formatted duration string with appropriate unit and precision
|
||||
*/ function durationToStringWithNanoseconds(durationBigInt) {
|
||||
const duration = Number(durationBigInt);
|
||||
if (duration >= MINUTES_THRESHOLD_NANOSECONDS) {
|
||||
return `${(duration / NANOSECONDS_IN_MINUTE).toFixed(1)}min`;
|
||||
} else if (duration >= SECONDS_THRESHOLD_HIGH_NANOSECONDS) {
|
||||
return `${(duration / NANOSECONDS_PER_SECOND).toFixed(0)}s`;
|
||||
} else if (duration >= SECONDS_THRESHOLD_LOW_NANOSECONDS) {
|
||||
return `${(duration / NANOSECONDS_PER_SECOND).toFixed(1)}s`;
|
||||
} else if (duration >= MILLISECONDS_THRESHOLD_NANOSECONDS) {
|
||||
return `${(duration / NANOSECONDS_PER_MILLISECOND).toFixed(0)}ms`;
|
||||
} else {
|
||||
return `${(duration / NANOSECONDS_PER_MICROSECOND).toFixed(0)}µs`;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Converts a high-resolution time tuple to seconds.
|
||||
*
|
||||
* @param hrtime - High-resolution time tuple of [seconds, nanoseconds]
|
||||
* @returns Duration in seconds as a floating-point number
|
||||
*/ export function hrtimeToSeconds(hrtime) {
|
||||
// hrtime is a tuple of [seconds, nanoseconds]
|
||||
return hrtime[0] + hrtime[1] / NANOSECONDS_PER_SECOND;
|
||||
}
|
||||
/**
|
||||
* Converts a BigInt nanosecond duration to a human-readable string format.
|
||||
* This is the preferred method for formatting high-precision durations.
|
||||
*
|
||||
* @param hrtime - Duration in nanoseconds as a BigInt (typically from process.hrtime.bigint())
|
||||
* @returns Formatted duration string with appropriate unit and precision
|
||||
*/ export function hrtimeBigIntDurationToString(hrtime) {
|
||||
return durationToStringWithNanoseconds(hrtime);
|
||||
}
|
||||
/**
|
||||
* Converts a high-resolution time tuple to a human-readable string format.
|
||||
*
|
||||
* @deprecated Use hrtimeBigIntDurationToString with process.hrtime.bigint() for better precision.
|
||||
* @param hrtime - High-resolution time tuple of [seconds, nanoseconds]
|
||||
* @returns Formatted duration string with appropriate unit and precision
|
||||
*/ export function hrtimeDurationToString(hrtime) {
|
||||
return durationToString(hrtimeToSeconds(hrtime));
|
||||
}
|
||||
|
||||
//# sourceMappingURL=duration-to-string.js.map
|
||||
+1
File diff suppressed because one or more lines are too long
+510
@@ -0,0 +1,510 @@
|
||||
import { posix, join, normalize } from 'path';
|
||||
import { stringify } from 'querystring';
|
||||
import { PAGES_DIR_ALIAS, ROOT_DIR_ALIAS, APP_DIR_ALIAS, WEBPACK_LAYERS, INSTRUMENTATION_HOOK_FILENAME } from '../lib/constants';
|
||||
import { isAPIRoute } from '../lib/is-api-route';
|
||||
import { isEdgeRuntime } from '../lib/is-edge-runtime';
|
||||
import { APP_CLIENT_INTERNALS, RSC_MODULE_TYPES } from '../shared/lib/constants';
|
||||
import { CLIENT_STATIC_FILES_RUNTIME_MAIN, CLIENT_STATIC_FILES_RUNTIME_MAIN_APP, CLIENT_STATIC_FILES_RUNTIME_POLYFILLS, CLIENT_STATIC_FILES_RUNTIME_REACT_REFRESH, COMPILER_NAMES, EDGE_RUNTIME_WEBPACK } from '../shared/lib/constants';
|
||||
import { isMiddlewareFile, isMiddlewareFilename, isProxyFile, isInstrumentationHookFile, isInstrumentationHookFilename } from './utils';
|
||||
import { normalizePagePath } from '../shared/lib/page-path/normalize-page-path';
|
||||
import { normalizeAppPath, compareAppPaths } from '../shared/lib/router/utils/app-paths';
|
||||
import { encodeMatchers } from './webpack/loaders/next-middleware-loader';
|
||||
import { isAppRouteRoute } from '../lib/is-app-route-route';
|
||||
import { getRouteLoaderEntry } from './webpack/loaders/next-route-loader';
|
||||
import { isInternalComponent, isNonRoutePagesPage } from '../lib/is-internal-component';
|
||||
import { RouteKind } from '../server/route-kind';
|
||||
import { encodeToBase64 } from './webpack/loaders/utils';
|
||||
import { normalizeCatchAllRoutes } from './normalize-catchall-routes';
|
||||
import { PAGE_TYPES } from '../lib/page-types';
|
||||
import { getStaticInfoIncludingLayouts } from './get-static-info-including-layouts';
|
||||
import { getPageFromPath } from './route-discovery';
|
||||
export function getPageFilePath({ absolutePagePath, pagesDir, appDir, rootDir }) {
|
||||
if (absolutePagePath.startsWith(PAGES_DIR_ALIAS) && pagesDir) {
|
||||
return absolutePagePath.replace(PAGES_DIR_ALIAS, pagesDir);
|
||||
}
|
||||
if (absolutePagePath.startsWith(APP_DIR_ALIAS) && appDir) {
|
||||
return absolutePagePath.replace(APP_DIR_ALIAS, appDir);
|
||||
}
|
||||
if (absolutePagePath.startsWith(ROOT_DIR_ALIAS)) {
|
||||
return absolutePagePath.replace(ROOT_DIR_ALIAS, rootDir);
|
||||
}
|
||||
return require.resolve(absolutePagePath);
|
||||
}
|
||||
/**
|
||||
* Checks if a page path matches any of the deferred entry patterns.
|
||||
* @param page - The page path (e.g., '/about', '/api/hello')
|
||||
* @param deferredEntries - Array of path patterns to match against
|
||||
* @returns true if the page matches a deferred entry pattern
|
||||
*/ export function isDeferredEntry(page, deferredEntries) {
|
||||
if (!deferredEntries || deferredEntries.length === 0) {
|
||||
return false;
|
||||
}
|
||||
// Normalize the page path
|
||||
const normalizedPage = page.startsWith('/') ? page : `/${page}`;
|
||||
for (const pattern of deferredEntries){
|
||||
// Normalize the pattern
|
||||
const normalizedPattern = pattern.startsWith('/') ? pattern : `/${pattern}`;
|
||||
// Check for exact match or prefix match for directories
|
||||
if (normalizedPage === normalizedPattern) {
|
||||
return true;
|
||||
}
|
||||
// Check if the page is under the deferred directory
|
||||
if (normalizedPage.startsWith(normalizedPattern + '/')) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
export function getEdgeServerEntry(opts) {
|
||||
var _opts_config_experimental_sri;
|
||||
const cacheHandler = opts.config.cacheHandler || undefined;
|
||||
if (opts.pagesType === 'app' && isAppRouteRoute(opts.page) && opts.appDirLoader) {
|
||||
const loaderParams = {
|
||||
absolutePagePath: opts.absolutePagePath,
|
||||
page: opts.page,
|
||||
appDirLoader: Buffer.from(opts.appDirLoader || '').toString('base64'),
|
||||
preferredRegion: opts.preferredRegion,
|
||||
middlewareConfig: Buffer.from(JSON.stringify(opts.middlewareConfig || {})).toString('base64'),
|
||||
cacheHandlers: JSON.stringify(opts.config.cacheHandlers || {}),
|
||||
...cacheHandler ? {
|
||||
cacheHandler
|
||||
} : {}
|
||||
};
|
||||
return {
|
||||
import: `next-edge-app-route-loader?${stringify(loaderParams)}!`,
|
||||
layer: WEBPACK_LAYERS.reactServerComponents
|
||||
};
|
||||
}
|
||||
if (isMiddlewareFile(opts.page)) {
|
||||
var _opts_middleware;
|
||||
const loaderParams = {
|
||||
absolutePagePath: opts.absolutePagePath,
|
||||
page: opts.page,
|
||||
rootDir: opts.rootDir,
|
||||
matchers: ((_opts_middleware = opts.middleware) == null ? void 0 : _opts_middleware.matchers) ? encodeMatchers(opts.middleware.matchers) : '',
|
||||
preferredRegion: opts.preferredRegion,
|
||||
middlewareConfig: Buffer.from(JSON.stringify(opts.middlewareConfig || {})).toString('base64'),
|
||||
...cacheHandler ? {
|
||||
cacheHandler
|
||||
} : {}
|
||||
};
|
||||
return {
|
||||
import: `next-middleware-loader?${stringify(loaderParams)}!`,
|
||||
layer: WEBPACK_LAYERS.middleware,
|
||||
filename: opts.isDev ? 'middleware.js' : undefined
|
||||
};
|
||||
}
|
||||
if (isAPIRoute(opts.page)) {
|
||||
const loaderParams = {
|
||||
absolutePagePath: opts.absolutePagePath,
|
||||
page: opts.page,
|
||||
rootDir: opts.rootDir,
|
||||
preferredRegion: opts.preferredRegion,
|
||||
middlewareConfig: Buffer.from(JSON.stringify(opts.middlewareConfig || {})).toString('base64'),
|
||||
...cacheHandler ? {
|
||||
cacheHandler
|
||||
} : {}
|
||||
};
|
||||
return {
|
||||
import: `next-edge-function-loader?${stringify(loaderParams)}!`,
|
||||
layer: WEBPACK_LAYERS.apiEdge
|
||||
};
|
||||
}
|
||||
const loaderParams = {
|
||||
absolute500Path: opts.pages['/500'] || '',
|
||||
absoluteAppPath: opts.pages['/_app'],
|
||||
absoluteDocumentPath: opts.pages['/_document'],
|
||||
absoluteErrorPath: opts.pages['/_error'],
|
||||
absolutePagePath: opts.absolutePagePath,
|
||||
dev: opts.isDev,
|
||||
isServerComponent: opts.isServerComponent,
|
||||
page: opts.page,
|
||||
pagesType: opts.pagesType,
|
||||
appDirLoader: Buffer.from(opts.appDirLoader || '').toString('base64'),
|
||||
sriEnabled: !opts.isDev && !!((_opts_config_experimental_sri = opts.config.experimental.sri) == null ? void 0 : _opts_config_experimental_sri.algorithm),
|
||||
preferredRegion: opts.preferredRegion,
|
||||
middlewareConfig: Buffer.from(JSON.stringify(opts.middlewareConfig || {})).toString('base64'),
|
||||
serverActions: opts.config.experimental.serverActions,
|
||||
cacheHandlers: JSON.stringify(opts.config.cacheHandlers || {}),
|
||||
...cacheHandler ? {
|
||||
cacheHandler
|
||||
} : {}
|
||||
};
|
||||
return {
|
||||
import: `next-edge-ssr-loader?${JSON.stringify(loaderParams)}!`,
|
||||
// The Edge bundle includes the server in its entrypoint, so it has to
|
||||
// be in the SSR layer — we later convert the page request to the RSC layer
|
||||
// via a webpack rule.
|
||||
layer: opts.appDirLoader ? WEBPACK_LAYERS.serverSideRendering : undefined
|
||||
};
|
||||
}
|
||||
export function getInstrumentationEntry(opts) {
|
||||
// the '../' is needed to make sure the file is not chunked
|
||||
const filename = `${opts.isEdgeServer ? 'edge-' : opts.isDev ? '' : '../'}${INSTRUMENTATION_HOOK_FILENAME}.js`;
|
||||
return {
|
||||
import: opts.absolutePagePath,
|
||||
filename,
|
||||
layer: WEBPACK_LAYERS.instrument
|
||||
};
|
||||
}
|
||||
export function getAppLoader() {
|
||||
return process.env.BUILTIN_APP_LOADER ? `builtin:next-app-loader` : 'next-app-loader';
|
||||
}
|
||||
export function getAppEntry(opts) {
|
||||
if (process.env.NEXT_RSPACK && process.env.BUILTIN_APP_LOADER) {
|
||||
;
|
||||
opts.projectRoot = normalize(join(__dirname, '../../..'));
|
||||
}
|
||||
return {
|
||||
import: `${getAppLoader()}?${stringify(opts)}!`,
|
||||
layer: WEBPACK_LAYERS.reactServerComponents
|
||||
};
|
||||
}
|
||||
export function getClientEntry(opts) {
|
||||
const loaderOptions = {
|
||||
absolutePagePath: opts.absolutePagePath,
|
||||
page: opts.page
|
||||
};
|
||||
const pageLoader = `next-client-pages-loader?${stringify(loaderOptions)}!`;
|
||||
// Make sure next/router is a dependency of _app or else chunk splitting
|
||||
// might cause the router to not be able to load causing hydration
|
||||
// to fail
|
||||
return opts.page === '/_app' ? [
|
||||
pageLoader,
|
||||
require.resolve('../client/router')
|
||||
] : pageLoader;
|
||||
}
|
||||
export function runDependingOnPageType(params) {
|
||||
if (params.pageType === PAGE_TYPES.ROOT && isInstrumentationHookFile(params.page)) {
|
||||
params.onServer();
|
||||
params.onEdgeServer();
|
||||
return;
|
||||
}
|
||||
if (isProxyFile(params.page)) {
|
||||
params.onServer();
|
||||
return;
|
||||
}
|
||||
if (isMiddlewareFile(params.page)) {
|
||||
if (params.pageRuntime === 'nodejs') {
|
||||
params.onServer();
|
||||
return;
|
||||
} else {
|
||||
params.onEdgeServer();
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (isAPIRoute(params.page)) {
|
||||
if (isEdgeRuntime(params.pageRuntime)) {
|
||||
params.onEdgeServer();
|
||||
return;
|
||||
}
|
||||
params.onServer();
|
||||
return;
|
||||
}
|
||||
if (params.page === '/_document') {
|
||||
params.onServer();
|
||||
return;
|
||||
}
|
||||
if (params.page === '/_app' || params.page === '/_error' || params.page === '/404' || params.page === '/500') {
|
||||
params.onClient();
|
||||
params.onServer();
|
||||
return;
|
||||
}
|
||||
if (isEdgeRuntime(params.pageRuntime)) {
|
||||
params.onClient();
|
||||
params.onEdgeServer();
|
||||
return;
|
||||
}
|
||||
params.onClient();
|
||||
params.onServer();
|
||||
return;
|
||||
}
|
||||
export async function createEntrypoints(params) {
|
||||
const { config, pages, pagesDir, isDev, rootDir, rootPaths, appDir, appPaths, pageExtensions, deferredEntriesFilter } = params;
|
||||
const deferredEntries = config.experimental.deferredEntries;
|
||||
const edgeServer = {};
|
||||
const server = {};
|
||||
const client = {};
|
||||
let middlewareMatchers = undefined;
|
||||
let appPathsPerRoute = {};
|
||||
if (appDir && appPaths) {
|
||||
for(const pathname in appPaths){
|
||||
const normalizedPath = normalizeAppPath(pathname);
|
||||
const actualPath = appPaths[pathname];
|
||||
if (!appPathsPerRoute[normalizedPath]) {
|
||||
appPathsPerRoute[normalizedPath] = [];
|
||||
}
|
||||
appPathsPerRoute[normalizedPath].push(// TODO-APP: refactor to pass the page path from createPagesMapping instead.
|
||||
getPageFromPath(actualPath, pageExtensions).replace(APP_DIR_ALIAS, ''));
|
||||
}
|
||||
// TODO: find a better place to do this
|
||||
normalizeCatchAllRoutes(appPathsPerRoute);
|
||||
// Make sure to sort parallel routes to make the result deterministic.
|
||||
appPathsPerRoute = Object.fromEntries(Object.entries(appPathsPerRoute).map(([k, v])=>[
|
||||
k,
|
||||
v.sort(compareAppPaths)
|
||||
]));
|
||||
}
|
||||
const getEntryHandler = (mappings, pagesType)=>async (page)=>{
|
||||
// Apply deferred entries filter if specified
|
||||
if (deferredEntriesFilter) {
|
||||
const isDeferred = isDeferredEntry(page, deferredEntries);
|
||||
if (deferredEntriesFilter === 'exclude' && isDeferred) {
|
||||
// Skip deferred entries when excluding them
|
||||
return;
|
||||
}
|
||||
if (deferredEntriesFilter === 'only' && !isDeferred) {
|
||||
// Skip non-deferred entries when only including deferred ones
|
||||
return;
|
||||
}
|
||||
}
|
||||
const bundleFile = normalizePagePath(page);
|
||||
const clientBundlePath = posix.join(pagesType, bundleFile);
|
||||
const serverBundlePath = pagesType === PAGE_TYPES.PAGES ? posix.join('pages', bundleFile) : pagesType === PAGE_TYPES.APP ? posix.join('app', bundleFile) : bundleFile.slice(1);
|
||||
const absolutePagePath = mappings[page];
|
||||
// Handle paths that have aliases
|
||||
const pageFilePath = getPageFilePath({
|
||||
absolutePagePath,
|
||||
pagesDir,
|
||||
appDir,
|
||||
rootDir
|
||||
});
|
||||
const isInsideAppDir = !!appDir && (absolutePagePath.startsWith(APP_DIR_ALIAS) || absolutePagePath.startsWith(appDir));
|
||||
const staticInfo = await getStaticInfoIncludingLayouts({
|
||||
isInsideAppDir,
|
||||
pageExtensions,
|
||||
pageFilePath,
|
||||
appDir,
|
||||
config,
|
||||
isDev,
|
||||
page
|
||||
});
|
||||
// TODO(timneutkens): remove this
|
||||
const isServerComponent = isInsideAppDir && staticInfo.rsc !== RSC_MODULE_TYPES.client;
|
||||
if (isMiddlewareFile(page)) {
|
||||
var _staticInfo_middleware;
|
||||
middlewareMatchers = ((_staticInfo_middleware = staticInfo.middleware) == null ? void 0 : _staticInfo_middleware.matchers) ?? [
|
||||
{
|
||||
regexp: '.*',
|
||||
originalSource: '/:path*'
|
||||
}
|
||||
];
|
||||
}
|
||||
const isInstrumentation = isInstrumentationHookFile(page) && pagesType === PAGE_TYPES.ROOT;
|
||||
runDependingOnPageType({
|
||||
page,
|
||||
pageRuntime: staticInfo.runtime,
|
||||
pageType: pagesType,
|
||||
onClient: ()=>{
|
||||
if (isServerComponent || isInsideAppDir) {
|
||||
// We skip the initial entries for server component pages and let the
|
||||
// server compiler inject them instead.
|
||||
} else {
|
||||
client[clientBundlePath] = getClientEntry({
|
||||
absolutePagePath,
|
||||
page
|
||||
});
|
||||
}
|
||||
},
|
||||
onServer: ()=>{
|
||||
if (pagesType === 'app' && appDir) {
|
||||
const matchedAppPaths = appPathsPerRoute[normalizeAppPath(page)];
|
||||
server[serverBundlePath] = getAppEntry({
|
||||
page,
|
||||
name: serverBundlePath,
|
||||
pagePath: absolutePagePath,
|
||||
appDir,
|
||||
appPaths: matchedAppPaths,
|
||||
allNormalizedAppPaths: Object.keys(appPathsPerRoute),
|
||||
pageExtensions,
|
||||
basePath: config.basePath,
|
||||
assetPrefix: config.assetPrefix,
|
||||
nextConfigOutput: config.output,
|
||||
preferredRegion: staticInfo.preferredRegion,
|
||||
middlewareConfig: encodeToBase64(staticInfo.middleware || {}),
|
||||
isGlobalNotFoundEnabled: config.experimental.globalNotFound ? true : undefined
|
||||
});
|
||||
} else if (isInstrumentation) {
|
||||
server[serverBundlePath.replace('src/', '')] = getInstrumentationEntry({
|
||||
absolutePagePath,
|
||||
isEdgeServer: false,
|
||||
isDev: false
|
||||
});
|
||||
} else if (isMiddlewareFile(page)) {
|
||||
server[serverBundlePath.replace('src/', '')] = getEdgeServerEntry({
|
||||
...params,
|
||||
rootDir,
|
||||
absolutePagePath: absolutePagePath,
|
||||
bundlePath: clientBundlePath,
|
||||
isDev: false,
|
||||
isServerComponent,
|
||||
page,
|
||||
middleware: staticInfo == null ? void 0 : staticInfo.middleware,
|
||||
pagesType,
|
||||
preferredRegion: staticInfo.preferredRegion,
|
||||
middlewareConfig: staticInfo.middleware
|
||||
});
|
||||
} else if (isAPIRoute(page)) {
|
||||
server[serverBundlePath] = [
|
||||
getRouteLoaderEntry({
|
||||
kind: RouteKind.PAGES_API,
|
||||
page,
|
||||
absolutePagePath,
|
||||
preferredRegion: staticInfo.preferredRegion,
|
||||
middlewareConfig: staticInfo.middleware || {}
|
||||
})
|
||||
];
|
||||
} else if (!isMiddlewareFile(page) && !isInternalComponent(absolutePagePath) && !isNonRoutePagesPage(page)) {
|
||||
server[serverBundlePath] = [
|
||||
getRouteLoaderEntry({
|
||||
kind: RouteKind.PAGES,
|
||||
page,
|
||||
pages,
|
||||
absolutePagePath,
|
||||
preferredRegion: staticInfo.preferredRegion,
|
||||
middlewareConfig: staticInfo.middleware ?? {}
|
||||
})
|
||||
];
|
||||
} else {
|
||||
server[serverBundlePath] = [
|
||||
absolutePagePath
|
||||
];
|
||||
}
|
||||
},
|
||||
onEdgeServer: ()=>{
|
||||
let appDirLoader = '';
|
||||
if (isInstrumentation) {
|
||||
edgeServer[serverBundlePath.replace('src/', '')] = getInstrumentationEntry({
|
||||
absolutePagePath,
|
||||
isEdgeServer: true,
|
||||
isDev: false
|
||||
});
|
||||
} else {
|
||||
if (pagesType === 'app') {
|
||||
const matchedAppPaths = appPathsPerRoute[normalizeAppPath(page)];
|
||||
appDirLoader = getAppEntry({
|
||||
name: serverBundlePath,
|
||||
page,
|
||||
pagePath: absolutePagePath,
|
||||
appDir: appDir,
|
||||
appPaths: matchedAppPaths,
|
||||
allNormalizedAppPaths: Object.keys(appPathsPerRoute),
|
||||
pageExtensions,
|
||||
basePath: config.basePath,
|
||||
assetPrefix: config.assetPrefix,
|
||||
nextConfigOutput: config.output,
|
||||
// This isn't used with edge as it needs to be set on the entry module, which will be the `edgeServerEntry` instead.
|
||||
// Still passing it here for consistency.
|
||||
preferredRegion: staticInfo.preferredRegion,
|
||||
middlewareConfig: Buffer.from(JSON.stringify(staticInfo.middleware || {})).toString('base64'),
|
||||
isGlobalNotFoundEnabled: config.experimental.globalNotFound ? true : undefined
|
||||
}).import;
|
||||
}
|
||||
edgeServer[serverBundlePath] = getEdgeServerEntry({
|
||||
...params,
|
||||
rootDir,
|
||||
absolutePagePath: absolutePagePath,
|
||||
bundlePath: clientBundlePath,
|
||||
isDev: false,
|
||||
isServerComponent,
|
||||
page,
|
||||
middleware: staticInfo == null ? void 0 : staticInfo.middleware,
|
||||
pagesType,
|
||||
appDirLoader,
|
||||
preferredRegion: staticInfo.preferredRegion,
|
||||
middlewareConfig: staticInfo.middleware
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
const promises = [];
|
||||
if (appPaths) {
|
||||
const entryHandler = getEntryHandler(appPaths, PAGE_TYPES.APP);
|
||||
promises.push(Promise.all(Object.keys(appPaths).map(entryHandler)));
|
||||
}
|
||||
if (rootPaths) {
|
||||
promises.push(Promise.all(Object.keys(rootPaths).map(getEntryHandler(rootPaths, PAGE_TYPES.ROOT))));
|
||||
}
|
||||
promises.push(Promise.all(Object.keys(pages).map(getEntryHandler(pages, PAGE_TYPES.PAGES))));
|
||||
await Promise.all(promises);
|
||||
// Optimization: If there's only one instrumentation hook in edge compiler, which means there's no edge server entry.
|
||||
// We remove the edge instrumentation entry from edge compiler as it can be pure server side.
|
||||
if (edgeServer.instrumentation && Object.keys(edgeServer).length === 1) {
|
||||
delete edgeServer.instrumentation;
|
||||
}
|
||||
return {
|
||||
client,
|
||||
server,
|
||||
edgeServer,
|
||||
middlewareMatchers
|
||||
};
|
||||
}
|
||||
export function finalizeEntrypoint({ name, compilerType, value, isServerComponent, hasAppDir }) {
|
||||
const entry = typeof value !== 'object' || Array.isArray(value) ? {
|
||||
import: value
|
||||
} : value;
|
||||
const isApi = name.startsWith('pages/api/');
|
||||
const isInstrumentation = isInstrumentationHookFilename(name);
|
||||
switch(compilerType){
|
||||
case COMPILER_NAMES.server:
|
||||
{
|
||||
const layer = isApi ? WEBPACK_LAYERS.apiNode : isInstrumentation ? WEBPACK_LAYERS.instrument : isServerComponent ? WEBPACK_LAYERS.reactServerComponents : name.startsWith('pages/') ? WEBPACK_LAYERS.pagesDirNode : undefined;
|
||||
return {
|
||||
publicPath: isApi ? '' : undefined,
|
||||
runtime: isApi ? 'webpack-api-runtime' : 'webpack-runtime',
|
||||
layer,
|
||||
...entry
|
||||
};
|
||||
}
|
||||
case COMPILER_NAMES.edgeServer:
|
||||
{
|
||||
return {
|
||||
layer: isApi ? WEBPACK_LAYERS.apiEdge : isMiddlewareFilename(name) || isInstrumentation ? WEBPACK_LAYERS.middleware : name.startsWith('pages/') ? WEBPACK_LAYERS.pagesDirEdge : undefined,
|
||||
library: {
|
||||
name: [
|
||||
'_ENTRIES',
|
||||
`middleware_[name]`
|
||||
],
|
||||
type: 'assign'
|
||||
},
|
||||
runtime: EDGE_RUNTIME_WEBPACK,
|
||||
asyncChunks: false,
|
||||
...entry
|
||||
};
|
||||
}
|
||||
case COMPILER_NAMES.client:
|
||||
{
|
||||
const isAppLayer = hasAppDir && (name === CLIENT_STATIC_FILES_RUNTIME_MAIN_APP || name === APP_CLIENT_INTERNALS || name.startsWith('app/'));
|
||||
if (// Client special cases
|
||||
name !== CLIENT_STATIC_FILES_RUNTIME_POLYFILLS && name !== CLIENT_STATIC_FILES_RUNTIME_MAIN && name !== CLIENT_STATIC_FILES_RUNTIME_MAIN_APP && name !== CLIENT_STATIC_FILES_RUNTIME_REACT_REFRESH) {
|
||||
if (isAppLayer) {
|
||||
return {
|
||||
dependOn: CLIENT_STATIC_FILES_RUNTIME_MAIN_APP,
|
||||
layer: WEBPACK_LAYERS.appPagesBrowser,
|
||||
...entry
|
||||
};
|
||||
}
|
||||
return {
|
||||
dependOn: name.startsWith('pages/') && name !== 'pages/_app' ? 'pages/_app' : CLIENT_STATIC_FILES_RUNTIME_MAIN,
|
||||
layer: WEBPACK_LAYERS.pagesDirBrowser,
|
||||
...entry
|
||||
};
|
||||
}
|
||||
if (isAppLayer) {
|
||||
return {
|
||||
layer: WEBPACK_LAYERS.appPagesBrowser,
|
||||
...entry
|
||||
};
|
||||
}
|
||||
return {
|
||||
layer: WEBPACK_LAYERS.pagesDirBrowser,
|
||||
...entry
|
||||
};
|
||||
}
|
||||
default:
|
||||
return compilerType;
|
||||
}
|
||||
}
|
||||
|
||||
//# sourceMappingURL=entries.js.map
|
||||
+1
File diff suppressed because one or more lines are too long
+54
@@ -0,0 +1,54 @@
|
||||
import { normalizeAppPath } from '../shared/lib/router/utils/app-paths';
|
||||
import { isParallelRouteSegment } from '../shared/lib/segment';
|
||||
/**
|
||||
* Extract slot info from a page path if it contains a parallel route
|
||||
*/ export function extractSlotFromPath(pagePath) {
|
||||
const segments = pagePath.split('/');
|
||||
for(let i = segments.length - 1; i >= 0; i--){
|
||||
const segment = segments[i];
|
||||
if (isParallelRouteSegment(segment)) {
|
||||
return {
|
||||
name: segment.slice(1),
|
||||
parent: normalizeAppPath(segments.slice(0, i).join('/'))
|
||||
};
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
/**
|
||||
* Add a slot to the slots array if it doesn't already exist
|
||||
*/ export function addSlotIfNew(slots, pagePath) {
|
||||
const slot = extractSlotFromPath(pagePath);
|
||||
if (!slot) return false;
|
||||
if (slots.some((s)=>s.name === slot.name && s.parent === slot.parent)) return false;
|
||||
slots.push(slot);
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Extract slots from a route mapping object
|
||||
*/ export function extractSlotsFromRoutes(routes, skipRoutes) {
|
||||
const slots = [];
|
||||
for (const [route] of Object.entries(routes)){
|
||||
if (skipRoutes == null ? void 0 : skipRoutes.has(route)) continue;
|
||||
addSlotIfNew(slots, route);
|
||||
}
|
||||
return slots;
|
||||
}
|
||||
/**
|
||||
* Combine and deduplicate slot arrays
|
||||
*/ export function combineSlots(...slotArrays) {
|
||||
const slotSet = new Set();
|
||||
const result = [];
|
||||
for (const slots of slotArrays){
|
||||
for (const slot of slots){
|
||||
const key = `${slot.name}:${slot.parent}`;
|
||||
if (!slotSet.has(key)) {
|
||||
slotSet.add(key);
|
||||
result.push(slot);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//# sourceMappingURL=file-classifier.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../../../src/build/file-classifier.ts"],"sourcesContent":["import { normalizeAppPath } from '../shared/lib/router/utils/app-paths'\nimport { isParallelRouteSegment } from '../shared/lib/segment'\n\n// Slot information for parallel routes\nexport type SlotInfo = { name: string; parent: string }\n\n// Route information for route manifests\nexport type RouteInfo = { route: string; filePath: string }\n\n/**\n * Extract slot info from a page path if it contains a parallel route\n */\nexport function extractSlotFromPath(pagePath: string): SlotInfo | undefined {\n const segments = pagePath.split('/')\n for (let i = segments.length - 1; i >= 0; i--) {\n const segment = segments[i]\n if (isParallelRouteSegment(segment)) {\n return {\n name: segment.slice(1),\n parent: normalizeAppPath(segments.slice(0, i).join('/')),\n }\n }\n }\n return undefined\n}\n\n/**\n * Add a slot to the slots array if it doesn't already exist\n */\nexport function addSlotIfNew(slots: SlotInfo[], pagePath: string): boolean {\n const slot = extractSlotFromPath(pagePath)\n if (!slot) return false\n if (slots.some((s) => s.name === slot.name && s.parent === slot.parent))\n return false\n slots.push(slot)\n return true\n}\n\n/**\n * Extract slots from a route mapping object\n */\nexport function extractSlotsFromRoutes(\n routes: { [page: string]: string },\n skipRoutes?: Set<string>\n): SlotInfo[] {\n const slots: SlotInfo[] = []\n for (const [route] of Object.entries(routes)) {\n if (skipRoutes?.has(route)) continue\n addSlotIfNew(slots, route)\n }\n return slots\n}\n\n/**\n * Combine and deduplicate slot arrays\n */\nexport function combineSlots(...slotArrays: SlotInfo[][]): SlotInfo[] {\n const slotSet = new Set<string>()\n const result: SlotInfo[] = []\n for (const slots of slotArrays) {\n for (const slot of slots) {\n const key = `${slot.name}:${slot.parent}`\n if (!slotSet.has(key)) {\n slotSet.add(key)\n result.push(slot)\n }\n }\n }\n return result\n}\n"],"names":["normalizeAppPath","isParallelRouteSegment","extractSlotFromPath","pagePath","segments","split","i","length","segment","name","slice","parent","join","undefined","addSlotIfNew","slots","slot","some","s","push","extractSlotsFromRoutes","routes","skipRoutes","route","Object","entries","has","combineSlots","slotArrays","slotSet","Set","result","key","add"],"mappings":"AAAA,SAASA,gBAAgB,QAAQ,uCAAsC;AACvE,SAASC,sBAAsB,QAAQ,wBAAuB;AAQ9D;;CAEC,GACD,OAAO,SAASC,oBAAoBC,QAAgB;IAClD,MAAMC,WAAWD,SAASE,KAAK,CAAC;IAChC,IAAK,IAAIC,IAAIF,SAASG,MAAM,GAAG,GAAGD,KAAK,GAAGA,IAAK;QAC7C,MAAME,UAAUJ,QAAQ,CAACE,EAAE;QAC3B,IAAIL,uBAAuBO,UAAU;YACnC,OAAO;gBACLC,MAAMD,QAAQE,KAAK,CAAC;gBACpBC,QAAQX,iBAAiBI,SAASM,KAAK,CAAC,GAAGJ,GAAGM,IAAI,CAAC;YACrD;QACF;IACF;IACA,OAAOC;AACT;AAEA;;CAEC,GACD,OAAO,SAASC,aAAaC,KAAiB,EAAEZ,QAAgB;IAC9D,MAAMa,OAAOd,oBAAoBC;IACjC,IAAI,CAACa,MAAM,OAAO;IAClB,IAAID,MAAME,IAAI,CAAC,CAACC,IAAMA,EAAET,IAAI,KAAKO,KAAKP,IAAI,IAAIS,EAAEP,MAAM,KAAKK,KAAKL,MAAM,GACpE,OAAO;IACTI,MAAMI,IAAI,CAACH;IACX,OAAO;AACT;AAEA;;CAEC,GACD,OAAO,SAASI,uBACdC,MAAkC,EAClCC,UAAwB;IAExB,MAAMP,QAAoB,EAAE;IAC5B,KAAK,MAAM,CAACQ,MAAM,IAAIC,OAAOC,OAAO,CAACJ,QAAS;QAC5C,IAAIC,8BAAAA,WAAYI,GAAG,CAACH,QAAQ;QAC5BT,aAAaC,OAAOQ;IACtB;IACA,OAAOR;AACT;AAEA;;CAEC,GACD,OAAO,SAASY,aAAa,GAAGC,UAAwB;IACtD,MAAMC,UAAU,IAAIC;IACpB,MAAMC,SAAqB,EAAE;IAC7B,KAAK,MAAMhB,SAASa,WAAY;QAC9B,KAAK,MAAMZ,QAAQD,MAAO;YACxB,MAAMiB,MAAM,GAAGhB,KAAKP,IAAI,CAAC,CAAC,EAAEO,KAAKL,MAAM,EAAE;YACzC,IAAI,CAACkB,QAAQH,GAAG,CAACM,MAAM;gBACrBH,QAAQI,GAAG,CAACD;gBACZD,OAAOZ,IAAI,CAACH;YACd;QACF;IACF;IACA,OAAOe;AACT","ignoreList":[0]}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
export async function generateBuildId(generate, fallback) {
|
||||
let buildId = await generate();
|
||||
// If there's no buildId defined we'll fall back
|
||||
if (buildId === null) {
|
||||
// We also create a new buildId if it contains the word `ad` to avoid false
|
||||
// positives with ad blockers
|
||||
while(!buildId || /ad/i.test(buildId)){
|
||||
buildId = fallback();
|
||||
}
|
||||
}
|
||||
if (typeof buildId !== 'string') {
|
||||
throw Object.defineProperty(new Error('generateBuildId did not return a string. https://nextjs.org/docs/messages/generatebuildid-not-a-string'), "__NEXT_ERROR_CODE", {
|
||||
value: "E455",
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
}
|
||||
return buildId.trim();
|
||||
}
|
||||
|
||||
//# sourceMappingURL=generate-build-id.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../../../src/build/generate-build-id.ts"],"sourcesContent":["export async function generateBuildId(\n generate: () => string | null | Promise<string | null>,\n fallback: () => string\n): Promise<string> {\n let buildId = await generate()\n // If there's no buildId defined we'll fall back\n if (buildId === null) {\n // We also create a new buildId if it contains the word `ad` to avoid false\n // positives with ad blockers\n while (!buildId || /ad/i.test(buildId)) {\n buildId = fallback()\n }\n }\n\n if (typeof buildId !== 'string') {\n throw new Error(\n 'generateBuildId did not return a string. https://nextjs.org/docs/messages/generatebuildid-not-a-string'\n )\n }\n\n return buildId.trim()\n}\n"],"names":["generateBuildId","generate","fallback","buildId","test","Error","trim"],"mappings":"AAAA,OAAO,eAAeA,gBACpBC,QAAsD,EACtDC,QAAsB;IAEtB,IAAIC,UAAU,MAAMF;IACpB,gDAAgD;IAChD,IAAIE,YAAY,MAAM;QACpB,2EAA2E;QAC3E,6BAA6B;QAC7B,MAAO,CAACA,WAAW,MAAMC,IAAI,CAACD,SAAU;YACtCA,UAAUD;QACZ;IACF;IAEA,IAAI,OAAOC,YAAY,UAAU;QAC/B,MAAM,qBAEL,CAFK,IAAIE,MACR,2GADI,qBAAA;mBAAA;wBAAA;0BAAA;QAEN;IACF;IAEA,OAAOF,QAAQG,IAAI;AACrB","ignoreList":[0]}
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
import { RSC_HEADER, NEXT_ROUTER_STATE_TREE_HEADER, NEXT_ROUTER_PREFETCH_HEADER, NEXT_DID_POSTPONE_HEADER, RSC_CONTENT_TYPE_HEADER, NEXT_ROUTER_SEGMENT_PREFETCH_HEADER, NEXT_REWRITTEN_PATH_HEADER, NEXT_REWRITTEN_QUERY_HEADER } from '../client/components/app-router-headers';
|
||||
import { RSC_SUFFIX, RSC_SEGMENT_SUFFIX, RSC_SEGMENTS_DIR_SUFFIX, NEXT_RESUME_HEADER } from '../lib/constants';
|
||||
import { isDynamicRoute } from '../shared/lib/router/utils';
|
||||
import { buildCustomRoute } from '../lib/build-custom-route';
|
||||
import { isReservedPage, pageToRoute } from './utils';
|
||||
import { sortPages } from '../shared/lib/router/utils/sortable-routes';
|
||||
/**
|
||||
* Generates the routes manifest from the given page keys and configuration.
|
||||
* This function extracts the route manifest generation logic to be reusable
|
||||
* across different build contexts (webpack build, turbopack build, analyze, etc.)
|
||||
*/ export function generateRoutesManifest(options) {
|
||||
const { pageKeys, config, redirects, headers, onMatchHeaders, rewrites, restrictedRedirectPaths, isAppPPREnabled, appType, deploymentId } = options;
|
||||
const sortedRoutes = sortPages([
|
||||
...pageKeys.pages,
|
||||
...pageKeys.app ?? []
|
||||
]);
|
||||
const staticRoutes = [];
|
||||
const dynamicRoutes = [];
|
||||
/**
|
||||
* A map of all the pages to their sourcePage value. This is only used for
|
||||
* routes that have PPR enabled and clientSegmentEnabled is true.
|
||||
*/ const sourcePages = new Map();
|
||||
for (const route of sortedRoutes){
|
||||
if (isDynamicRoute(route)) {
|
||||
dynamicRoutes.push(pageToRoute(route, // This property is only relevant when PPR is enabled.
|
||||
undefined));
|
||||
} else if (!isReservedPage(route) || // don't consider /api reserved here
|
||||
route.match(/^\/(api(\/|$))/)) {
|
||||
staticRoutes.push(pageToRoute(route));
|
||||
}
|
||||
}
|
||||
const routesManifest = {
|
||||
version: 3,
|
||||
pages404: true,
|
||||
appType,
|
||||
caseSensitive: !!config.experimental.caseSensitiveRoutes,
|
||||
basePath: config.basePath,
|
||||
redirects: redirects.map((r)=>buildCustomRoute('redirect', r, restrictedRedirectPaths)),
|
||||
headers: headers.map((r)=>buildCustomRoute('header', r)),
|
||||
onMatchHeaders: onMatchHeaders.map((r)=>buildCustomRoute('header', r)),
|
||||
rewrites: {
|
||||
beforeFiles: rewrites.beforeFiles.map((r)=>buildCustomRoute('rewrite', r)),
|
||||
afterFiles: rewrites.afterFiles.map((r)=>buildCustomRoute('rewrite', r)),
|
||||
fallback: rewrites.fallback.map((r)=>buildCustomRoute('rewrite', r))
|
||||
},
|
||||
dynamicRoutes,
|
||||
staticRoutes,
|
||||
dataRoutes: [],
|
||||
i18n: config.i18n || undefined,
|
||||
rsc: {
|
||||
header: RSC_HEADER,
|
||||
// This vary header is used as a default. It is technically re-assigned in `base-server`,
|
||||
// and may include an additional Vary option for `Next-URL`.
|
||||
varyHeader: `${RSC_HEADER}, ${NEXT_ROUTER_STATE_TREE_HEADER}, ${NEXT_ROUTER_PREFETCH_HEADER}, ${NEXT_ROUTER_SEGMENT_PREFETCH_HEADER}`,
|
||||
prefetchHeader: NEXT_ROUTER_PREFETCH_HEADER,
|
||||
didPostponeHeader: NEXT_DID_POSTPONE_HEADER,
|
||||
contentTypeHeader: RSC_CONTENT_TYPE_HEADER,
|
||||
suffix: RSC_SUFFIX,
|
||||
prefetchSegmentHeader: NEXT_ROUTER_SEGMENT_PREFETCH_HEADER,
|
||||
prefetchSegmentSuffix: RSC_SEGMENT_SUFFIX,
|
||||
prefetchSegmentDirSuffix: RSC_SEGMENTS_DIR_SUFFIX,
|
||||
clientParamParsing: config.cacheComponents ?? false,
|
||||
clientParamParsingOrigins: config.experimental.clientParamParsingOrigins,
|
||||
dynamicRSCPrerender: isAppPPREnabled && config.cacheComponents === true
|
||||
},
|
||||
rewriteHeaders: {
|
||||
pathHeader: NEXT_REWRITTEN_PATH_HEADER,
|
||||
queryHeader: NEXT_REWRITTEN_QUERY_HEADER
|
||||
},
|
||||
skipProxyUrlNormalize: config.skipProxyUrlNormalize,
|
||||
deploymentId: deploymentId || undefined,
|
||||
ppr: isAppPPREnabled ? {
|
||||
chain: {
|
||||
headers: {
|
||||
[NEXT_RESUME_HEADER]: '1'
|
||||
}
|
||||
}
|
||||
} : undefined
|
||||
};
|
||||
return {
|
||||
routesManifest,
|
||||
dynamicRoutes,
|
||||
sourcePages
|
||||
};
|
||||
}
|
||||
|
||||
//# sourceMappingURL=generate-routes-manifest.js.map
|
||||
+1
File diff suppressed because one or more lines are too long
+25
@@ -0,0 +1,25 @@
|
||||
import { join } from 'path';
|
||||
import { existsSync } from 'fs';
|
||||
const BABEL_CONFIG_FILES = [
|
||||
'.babelrc',
|
||||
'.babelrc.json',
|
||||
'.babelrc.js',
|
||||
'.babelrc.mjs',
|
||||
'.babelrc.cjs',
|
||||
'babel.config.js',
|
||||
'babel.config.json',
|
||||
'babel.config.mjs',
|
||||
'babel.config.cjs'
|
||||
];
|
||||
export function getBabelConfigFile(dir) {
|
||||
for (const filename of BABEL_CONFIG_FILES){
|
||||
const configFilePath = join(dir, filename);
|
||||
const exists = existsSync(configFilePath);
|
||||
if (!exists) {
|
||||
continue;
|
||||
}
|
||||
return configFilePath;
|
||||
}
|
||||
}
|
||||
|
||||
//# sourceMappingURL=get-babel-config-file.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../../../src/build/get-babel-config-file.ts"],"sourcesContent":["import { join } from 'path'\nimport { existsSync } from 'fs'\n\nconst BABEL_CONFIG_FILES = [\n '.babelrc',\n '.babelrc.json',\n '.babelrc.js',\n '.babelrc.mjs',\n '.babelrc.cjs',\n 'babel.config.js',\n 'babel.config.json',\n 'babel.config.mjs',\n 'babel.config.cjs',\n]\n\nexport function getBabelConfigFile(dir: string): string | undefined {\n for (const filename of BABEL_CONFIG_FILES) {\n const configFilePath = join(dir, filename)\n const exists = existsSync(configFilePath)\n if (!exists) {\n continue\n }\n return configFilePath\n }\n}\n"],"names":["join","existsSync","BABEL_CONFIG_FILES","getBabelConfigFile","dir","filename","configFilePath","exists"],"mappings":"AAAA,SAASA,IAAI,QAAQ,OAAM;AAC3B,SAASC,UAAU,QAAQ,KAAI;AAE/B,MAAMC,qBAAqB;IACzB;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;CACD;AAED,OAAO,SAASC,mBAAmBC,GAAW;IAC5C,KAAK,MAAMC,YAAYH,mBAAoB;QACzC,MAAMI,iBAAiBN,KAAKI,KAAKC;QACjC,MAAME,SAASN,WAAWK;QAC1B,IAAI,CAACC,QAAQ;YACX;QACF;QACA,OAAOD;IACT;AACF","ignoreList":[0]}
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
import path from 'path';
|
||||
function getReactCompiler() {
|
||||
try {
|
||||
return require.resolve('babel-plugin-react-compiler');
|
||||
} catch {
|
||||
throw Object.defineProperty(new Error('Failed to load the `babel-plugin-react-compiler`. It is required to use the React Compiler. Please install it.'), "__NEXT_ERROR_CODE", {
|
||||
value: "E78",
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
}
|
||||
}
|
||||
const getReactCompilerPlugins = (maybeOptions, isServer, isDev)=>{
|
||||
if (!maybeOptions || isServer) {
|
||||
return undefined;
|
||||
}
|
||||
const environment = {
|
||||
enableNameAnonymousFunctions: isDev
|
||||
};
|
||||
const options = typeof maybeOptions === 'boolean' ? {} : maybeOptions;
|
||||
const compilerOptions = {
|
||||
...options,
|
||||
environment
|
||||
};
|
||||
return [
|
||||
[
|
||||
getReactCompiler(),
|
||||
compilerOptions
|
||||
]
|
||||
];
|
||||
};
|
||||
const getBabelLoader = (useSWCLoader, babelConfigFile, isServer, distDir, pagesDir, cwd, srcDir, dev, isClient, reactCompilerOptions, reactCompilerExclude)=>{
|
||||
if (!useSWCLoader) {
|
||||
// Make sure these options are kept in sync with
|
||||
// `packages/next/src/build/get-babel-loader-config.ts`
|
||||
const options = {
|
||||
transformMode: 'default',
|
||||
configFile: babelConfigFile,
|
||||
isServer,
|
||||
distDir,
|
||||
pagesDir,
|
||||
cwd,
|
||||
srcDir: path.dirname(srcDir),
|
||||
development: dev,
|
||||
hasReactRefresh: dev && isClient,
|
||||
hasJsxRuntime: true,
|
||||
reactCompilerPlugins: getReactCompilerPlugins(reactCompilerOptions, isServer, dev),
|
||||
reactCompilerExclude
|
||||
};
|
||||
return {
|
||||
loader: require.resolve('./babel/loader/index'),
|
||||
options
|
||||
};
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
/**
|
||||
* Get a separate babel loader for the react compiler, only used if Babel is not
|
||||
* configured through e.g. .babelrc. If user have babel config, this should be configured in the babel loader itself.
|
||||
* Note from react compiler:
|
||||
* > For best results, compiler must run as the first plugin in your Babel pipeline so it receives input as close to the original source as possible.
|
||||
*/ const getReactCompilerLoader = (reactCompilerOptions, cwd, isServer, reactCompilerExclude, isDev)=>{
|
||||
const reactCompilerPlugins = getReactCompilerPlugins(reactCompilerOptions, isServer, isDev);
|
||||
if (!reactCompilerPlugins) {
|
||||
return undefined;
|
||||
}
|
||||
const babelLoaderOptions = {
|
||||
transformMode: 'standalone',
|
||||
cwd,
|
||||
reactCompilerPlugins,
|
||||
isServer
|
||||
};
|
||||
if (reactCompilerExclude) {
|
||||
babelLoaderOptions.reactCompilerExclude = reactCompilerExclude;
|
||||
}
|
||||
return {
|
||||
loader: require.resolve('./babel/loader/index'),
|
||||
options: babelLoaderOptions
|
||||
};
|
||||
};
|
||||
export { getBabelLoader, getReactCompilerLoader };
|
||||
|
||||
//# sourceMappingURL=get-babel-loader-config.js.map
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user