main repo

This commit is contained in:
Basilosaurusrex
2025-11-24 18:09:40 +01:00
parent b636ee5e70
commit f027651f9b
34146 changed files with 4436636 additions and 0 deletions

View File

@@ -0,0 +1,51 @@
import { webpack, sources } from "next/dist/compiled/webpack/webpack";
import { APP_BUILD_MANIFEST, CLIENT_STATIC_FILES_RUNTIME_MAIN_APP, SYSTEM_ENTRYPOINTS } from "../../../shared/lib/constants";
import { getEntrypointFiles } from "./build-manifest-plugin";
import getAppRouteFromEntrypoint from "../../../server/get-app-route-from-entrypoint";
const PLUGIN_NAME = "AppBuildManifestPlugin";
export class AppBuildManifestPlugin {
constructor(options){
this.dev = options.dev;
}
apply(compiler) {
compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation, { normalModuleFactory })=>{
compilation.dependencyFactories.set(webpack.dependencies.ModuleDependency, normalModuleFactory);
compilation.dependencyTemplates.set(webpack.dependencies.ModuleDependency, new webpack.dependencies.NullDependency.Template());
});
compiler.hooks.make.tap(PLUGIN_NAME, (compilation)=>{
compilation.hooks.processAssets.tap({
name: PLUGIN_NAME,
stage: webpack.Compilation.PROCESS_ASSETS_STAGE_ADDITIONS
}, (assets)=>this.createAsset(assets, compilation));
});
}
createAsset(assets, compilation) {
const manifest = {
pages: {}
};
const mainFiles = new Set(getEntrypointFiles(compilation.entrypoints.get(CLIENT_STATIC_FILES_RUNTIME_MAIN_APP)));
for (const entrypoint of compilation.entrypoints.values()){
if (!entrypoint.name) {
continue;
}
if (SYSTEM_ENTRYPOINTS.has(entrypoint.name)) {
continue;
}
const pagePath = getAppRouteFromEntrypoint(entrypoint.name);
if (!pagePath) {
continue;
}
const filesForPage = getEntrypointFiles(entrypoint);
manifest.pages[pagePath] = [
...new Set([
...mainFiles,
...filesForPage
])
];
}
const json = JSON.stringify(manifest, null, 2);
assets[APP_BUILD_MANIFEST] = new sources.RawSource(json);
}
}
//# sourceMappingURL=app-build-manifest-plugin.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../src/build/webpack/plugins/app-build-manifest-plugin.ts"],"names":["webpack","sources","APP_BUILD_MANIFEST","CLIENT_STATIC_FILES_RUNTIME_MAIN_APP","SYSTEM_ENTRYPOINTS","getEntrypointFiles","getAppRouteFromEntrypoint","PLUGIN_NAME","AppBuildManifestPlugin","constructor","options","dev","apply","compiler","hooks","compilation","tap","normalModuleFactory","dependencyFactories","set","dependencies","ModuleDependency","dependencyTemplates","NullDependency","Template","make","processAssets","name","stage","Compilation","PROCESS_ASSETS_STAGE_ADDITIONS","assets","createAsset","manifest","pages","mainFiles","Set","entrypoints","get","entrypoint","values","has","pagePath","filesForPage","json","JSON","stringify","RawSource"],"mappings":"AAAA,SAASA,OAAO,EAAEC,OAAO,QAAQ,qCAAoC;AACrE,SACEC,kBAAkB,EAClBC,oCAAoC,EACpCC,kBAAkB,QACb,gCAA+B;AACtC,SAASC,kBAAkB,QAAQ,0BAAyB;AAC5D,OAAOC,+BAA+B,gDAA+C;AAUrF,MAAMC,cAAc;AAEpB,OAAO,MAAMC;IAGXC,YAAYC,OAAgB,CAAE;QAC5B,IAAI,CAACC,GAAG,GAAGD,QAAQC,GAAG;IACxB;IAEOC,MAAMC,QAAa,EAAE;QAC1BA,SAASC,KAAK,CAACC,WAAW,CAACC,GAAG,CAC5BT,aACA,CAACQ,aAAkB,EAAEE,mBAAmB,EAAO;YAC7CF,YAAYG,mBAAmB,CAACC,GAAG,CACjCnB,QAAQoB,YAAY,CAACC,gBAAgB,EACrCJ;YAEFF,YAAYO,mBAAmB,CAACH,GAAG,CACjCnB,QAAQoB,YAAY,CAACC,gBAAgB,EACrC,IAAIrB,QAAQoB,YAAY,CAACG,cAAc,CAACC,QAAQ;QAEpD;QAGFX,SAASC,KAAK,CAACW,IAAI,CAACT,GAAG,CAACT,aAAa,CAACQ;YACpCA,YAAYD,KAAK,CAACY,aAAa,CAACV,GAAG,CACjC;gBACEW,MAAMpB;gBACNqB,OAAO5B,QAAQ6B,WAAW,CAACC,8BAA8B;YAC3D,GACA,CAACC,SAAgB,IAAI,CAACC,WAAW,CAACD,QAAQhB;QAE9C;IACF;IAEQiB,YAAYD,MAAW,EAAEhB,WAAgC,EAAE;QACjE,MAAMkB,WAA6B;YACjCC,OAAO,CAAC;QACV;QAEA,MAAMC,YAAY,IAAIC,IACpB/B,mBACEU,YAAYsB,WAAW,CAACC,GAAG,CAACnC;QAIhC,KAAK,MAAMoC,cAAcxB,YAAYsB,WAAW,CAACG,MAAM,GAAI;YACzD,IAAI,CAACD,WAAWZ,IAAI,EAAE;gBACpB;YACF;YAEA,IAAIvB,mBAAmBqC,GAAG,CAACF,WAAWZ,IAAI,GAAG;gBAC3C;YACF;YAEA,MAAMe,WAAWpC,0BAA0BiC,WAAWZ,IAAI;YAC1D,IAAI,CAACe,UAAU;gBACb;YACF;YAEA,MAAMC,eAAetC,mBAAmBkC;YACxCN,SAASC,KAAK,CAACQ,SAAS,GAAG;mBAAI,IAAIN,IAAI;uBAAID;uBAAcQ;iBAAa;aAAE;QAC1E;QAEA,MAAMC,OAAOC,KAAKC,SAAS,CAACb,UAAU,MAAM;QAE5CF,MAAM,CAAC7B,mBAAmB,GAAG,IAAID,QAAQ8C,SAAS,CAACH;IACrD;AACF"}

View File

@@ -0,0 +1,181 @@
import devalue from "next/dist/compiled/devalue";
import { webpack, sources } from "next/dist/compiled/webpack/webpack";
import { BUILD_MANIFEST, MIDDLEWARE_BUILD_MANIFEST, CLIENT_STATIC_FILES_PATH, CLIENT_STATIC_FILES_RUNTIME_MAIN, CLIENT_STATIC_FILES_RUNTIME_MAIN_APP, CLIENT_STATIC_FILES_RUNTIME_POLYFILLS_SYMBOL, CLIENT_STATIC_FILES_RUNTIME_REACT_REFRESH, CLIENT_STATIC_FILES_RUNTIME_AMP, SYSTEM_ENTRYPOINTS } from "../../../shared/lib/constants";
import getRouteFromEntrypoint from "../../../server/get-route-from-entrypoint";
import { ampFirstEntryNamesMap } from "./next-drop-client-page-plugin";
import { getSortedRoutes } from "../../../shared/lib/router/utils";
import { spans } from "./profiling-plugin";
// Add the runtime ssg manifest file as a lazy-loaded file dependency.
// We also stub this file out for development mode (when it is not
// generated).
export const srcEmptySsgManifest = `self.__SSG_MANIFEST=new Set;self.__SSG_MANIFEST_CB&&self.__SSG_MANIFEST_CB()`;
// This function takes the asset map generated in BuildManifestPlugin and creates a
// reduced version to send to the client.
function generateClientManifest(compiler, compilation, assetMap, rewrites) {
const compilationSpan = spans.get(compilation) || spans.get(compiler);
const genClientManifestSpan = compilationSpan == null ? void 0 : compilationSpan.traceChild("NextJsBuildManifest-generateClientManifest");
const normalizeRewrite = (item)=>{
return {
has: item.has,
source: item.source,
destination: item.destination
};
};
return genClientManifestSpan == null ? void 0 : genClientManifestSpan.traceFn(()=>{
var _rewrites_afterFiles, _rewrites_beforeFiles, _rewrites_fallback;
const clientManifest = {
__rewrites: {
afterFiles: (_rewrites_afterFiles = rewrites.afterFiles) == null ? void 0 : _rewrites_afterFiles.map((item)=>normalizeRewrite(item)),
beforeFiles: (_rewrites_beforeFiles = rewrites.beforeFiles) == null ? void 0 : _rewrites_beforeFiles.map((item)=>normalizeRewrite(item)),
fallback: (_rewrites_fallback = rewrites.fallback) == null ? void 0 : _rewrites_fallback.map((item)=>normalizeRewrite(item))
}
};
const appDependencies = new Set(assetMap.pages["/_app"]);
const sortedPageKeys = getSortedRoutes(Object.keys(assetMap.pages));
sortedPageKeys.forEach((page)=>{
const dependencies = assetMap.pages[page];
if (page === "/_app") return;
// Filter out dependencies in the _app entry, because those will have already
// been loaded by the client prior to a navigation event
const filteredDeps = dependencies.filter((dep)=>!appDependencies.has(dep));
// The manifest can omit the page if it has no requirements
if (filteredDeps.length) {
clientManifest[page] = filteredDeps;
}
});
// provide the sorted pages as an array so we don't rely on the object's keys
// being in order and we don't slow down look-up time for page assets
clientManifest.sortedPages = sortedPageKeys;
return devalue(clientManifest);
});
}
export function getEntrypointFiles(entrypoint) {
return (entrypoint == null ? void 0 : entrypoint.getFiles().filter((file)=>{
// We don't want to include `.hot-update.js` files into the initial page
return /(?<!\.hot-update)\.(js|css)($|\?)/.test(file);
}).map((file)=>file.replace(/\\/g, "/"))) ?? [];
}
const processRoute = (r)=>{
const rewrite = {
...r
};
// omit external rewrite destinations since these aren't
// handled client-side
if (!rewrite.destination.startsWith("/")) {
delete rewrite.destination;
}
return rewrite;
};
// This plugin creates a build-manifest.json for all assets that are being output
// It has a mapping of "entry" filename to real filename. Because the real filename can be hashed in production
export default class BuildManifestPlugin {
constructor(options){
this.buildId = options.buildId;
this.isDevFallback = !!options.isDevFallback;
this.rewrites = {
beforeFiles: [],
afterFiles: [],
fallback: []
};
this.appDirEnabled = options.appDirEnabled;
this.rewrites.beforeFiles = options.rewrites.beforeFiles.map(processRoute);
this.rewrites.afterFiles = options.rewrites.afterFiles.map(processRoute);
this.rewrites.fallback = options.rewrites.fallback.map(processRoute);
this.exportRuntime = !!options.exportRuntime;
}
createAssets(compiler, compilation, assets) {
const compilationSpan = spans.get(compilation) || spans.get(compiler);
const createAssetsSpan = compilationSpan == null ? void 0 : compilationSpan.traceChild("NextJsBuildManifest-createassets");
return createAssetsSpan == null ? void 0 : createAssetsSpan.traceFn(()=>{
const entrypoints = compilation.entrypoints;
const assetMap = {
polyfillFiles: [],
devFiles: [],
ampDevFiles: [],
lowPriorityFiles: [],
rootMainFiles: [],
pages: {
"/_app": []
},
ampFirstPages: []
};
const ampFirstEntryNames = ampFirstEntryNamesMap.get(compilation);
if (ampFirstEntryNames) {
for (const entryName of ampFirstEntryNames){
const pagePath = getRouteFromEntrypoint(entryName);
if (!pagePath) {
continue;
}
assetMap.ampFirstPages.push(pagePath);
}
}
const mainFiles = new Set(getEntrypointFiles(entrypoints.get(CLIENT_STATIC_FILES_RUNTIME_MAIN)));
if (this.appDirEnabled) {
assetMap.rootMainFiles = [
...new Set(getEntrypointFiles(entrypoints.get(CLIENT_STATIC_FILES_RUNTIME_MAIN_APP)))
];
}
const compilationAssets = compilation.getAssets();
assetMap.polyfillFiles = compilationAssets.filter((p)=>{
// Ensure only .js files are passed through
if (!p.name.endsWith(".js")) {
return false;
}
return p.info && CLIENT_STATIC_FILES_RUNTIME_POLYFILLS_SYMBOL in p.info;
}).map((v)=>v.name);
assetMap.devFiles = getEntrypointFiles(entrypoints.get(CLIENT_STATIC_FILES_RUNTIME_REACT_REFRESH)).filter((file)=>!mainFiles.has(file));
assetMap.ampDevFiles = getEntrypointFiles(entrypoints.get(CLIENT_STATIC_FILES_RUNTIME_AMP));
for (const entrypoint of compilation.entrypoints.values()){
if (SYSTEM_ENTRYPOINTS.has(entrypoint.name)) continue;
const pagePath = getRouteFromEntrypoint(entrypoint.name);
if (!pagePath) {
continue;
}
const filesForPage = getEntrypointFiles(entrypoint);
assetMap.pages[pagePath] = [
...new Set([
...mainFiles,
...filesForPage
])
];
}
if (!this.isDevFallback) {
// Add the runtime build manifest file (generated later in this file)
// as a dependency for the app. If the flag is false, the file won't be
// downloaded by the client.
assetMap.lowPriorityFiles.push(`${CLIENT_STATIC_FILES_PATH}/${this.buildId}/_buildManifest.js`);
const ssgManifestPath = `${CLIENT_STATIC_FILES_PATH}/${this.buildId}/_ssgManifest.js`;
assetMap.lowPriorityFiles.push(ssgManifestPath);
assets[ssgManifestPath] = new sources.RawSource(srcEmptySsgManifest);
}
assetMap.pages = Object.keys(assetMap.pages).sort()// eslint-disable-next-line
.reduce((a, c)=>(a[c] = assetMap.pages[c], a), {});
let buildManifestName = BUILD_MANIFEST;
if (this.isDevFallback) {
buildManifestName = `fallback-${BUILD_MANIFEST}`;
}
assets[buildManifestName] = new sources.RawSource(JSON.stringify(assetMap, null, 2));
if (this.exportRuntime) {
assets[`server/${MIDDLEWARE_BUILD_MANIFEST}.js`] = new sources.RawSource(`self.__BUILD_MANIFEST=${JSON.stringify(assetMap)}`);
}
if (!this.isDevFallback) {
const clientManifestPath = `${CLIENT_STATIC_FILES_PATH}/${this.buildId}/_buildManifest.js`;
assets[clientManifestPath] = new sources.RawSource(`self.__BUILD_MANIFEST = ${generateClientManifest(compiler, compilation, assetMap, this.rewrites)};self.__BUILD_MANIFEST_CB && self.__BUILD_MANIFEST_CB()`);
}
return assets;
});
}
apply(compiler) {
compiler.hooks.make.tap("NextJsBuildManifest", (compilation)=>{
compilation.hooks.processAssets.tap({
name: "NextJsBuildManifest",
stage: webpack.Compilation.PROCESS_ASSETS_STAGE_ADDITIONS
}, (assets)=>{
this.createAssets(compiler, compilation, assets);
});
});
return;
}
}
//# sourceMappingURL=build-manifest-plugin.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,52 @@
import { promises as fs } from "fs";
import loaderUtils from "next/dist/compiled/loader-utils3";
import { sources, webpack } from "next/dist/compiled/webpack/webpack";
const PLUGIN_NAME = "CopyFilePlugin";
export class CopyFilePlugin {
constructor({ filePath, cacheKey, name, info }){
this.filePath = filePath;
this.cacheKey = cacheKey;
this.name = name;
this.info = info;
}
apply(compiler) {
compiler.hooks.thisCompilation.tap(PLUGIN_NAME, (compilation)=>{
const cache = compilation.getCache("CopyFilePlugin");
const hook = compilation.hooks.processAssets;
hook.tapPromise({
name: PLUGIN_NAME,
stage: webpack.Compilation.PROCESS_ASSETS_STAGE_ADDITIONS
}, async ()=>{
if (cache) {
const cachedResult = await cache.getPromise(this.filePath, this.cacheKey);
if (cachedResult) {
const { file, source } = cachedResult;
compilation.emitAsset(file, source, {
...this.info
});
return;
}
}
const content = await fs.readFile(this.filePath, "utf8");
const file = loaderUtils.interpolateName({
resourcePath: this.filePath
}, this.name, {
content,
context: compiler.context
});
const source = new sources.RawSource(content);
if (cache) {
await cache.storePromise(this.filePath, this.cacheKey, {
file,
source
});
}
compilation.emitAsset(file, source, {
...this.info
});
});
});
}
}
//# sourceMappingURL=copy-file-plugin.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../src/build/webpack/plugins/copy-file-plugin.ts"],"names":["promises","fs","loaderUtils","sources","webpack","PLUGIN_NAME","CopyFilePlugin","constructor","filePath","cacheKey","name","info","apply","compiler","hooks","thisCompilation","tap","compilation","cache","getCache","hook","processAssets","tapPromise","stage","Compilation","PROCESS_ASSETS_STAGE_ADDITIONS","cachedResult","getPromise","file","source","emitAsset","content","readFile","interpolateName","resourcePath","context","RawSource","storePromise"],"mappings":"AAAA,SAASA,YAAYC,EAAE,QAAQ,KAAI;AACnC,OAAOC,iBAAiB,mCAAkC;AAC1D,SAASC,OAAO,EAAEC,OAAO,QAAQ,qCAAoC;AAErE,MAAMC,cAAc;AAEpB,OAAO,MAAMC;IAMXC,YAAY,EACVC,QAAQ,EACRC,QAAQ,EACRC,IAAI,EACJC,IAAI,EAOL,CAAE;QACD,IAAI,CAACH,QAAQ,GAAGA;QAChB,IAAI,CAACC,QAAQ,GAAGA;QAChB,IAAI,CAACC,IAAI,GAAGA;QACZ,IAAI,CAACC,IAAI,GAAGA;IACd;IAEAC,MAAMC,QAA0B,EAAE;QAChCA,SAASC,KAAK,CAACC,eAAe,CAACC,GAAG,CAACX,aAAa,CAACY;YAC/C,MAAMC,QAAQD,YAAYE,QAAQ,CAAC;YACnC,MAAMC,OAAOH,YAAYH,KAAK,CAACO,aAAa;YAC5CD,KAAKE,UAAU,CACb;gBACEZ,MAAML;gBACNkB,OAAOnB,QAAQoB,WAAW,CAACC,8BAA8B;YAC3D,GACA;gBACE,IAAIP,OAAO;oBACT,MAAMQ,eAAe,MAAMR,MAAMS,UAAU,CACzC,IAAI,CAACnB,QAAQ,EACb,IAAI,CAACC,QAAQ;oBAEf,IAAIiB,cAAc;wBAChB,MAAM,EAAEE,IAAI,EAAEC,MAAM,EAAE,GAAGH;wBACzBT,YAAYa,SAAS,CAACF,MAAMC,QAAQ;4BAClC,GAAG,IAAI,CAAClB,IAAI;wBACd;wBACA;oBACF;gBACF;gBACA,MAAMoB,UAAU,MAAM9B,GAAG+B,QAAQ,CAAC,IAAI,CAACxB,QAAQ,EAAE;gBAEjD,MAAMoB,OAAO1B,YAAY+B,eAAe,CACtC;oBAAEC,cAAc,IAAI,CAAC1B,QAAQ;gBAAC,GAC9B,IAAI,CAACE,IAAI,EACT;oBAAEqB;oBAASI,SAAStB,SAASsB,OAAO;gBAAC;gBAGvC,MAAMN,SAAS,IAAI1B,QAAQiC,SAAS,CAACL;gBAErC,IAAIb,OAAO;oBACT,MAAMA,MAAMmB,YAAY,CAAC,IAAI,CAAC7B,QAAQ,EAAE,IAAI,CAACC,QAAQ,EAAE;wBACrDmB;wBACAC;oBACF;gBACF;gBAEAZ,YAAYa,SAAS,CAACF,MAAMC,QAAQ;oBAClC,GAAG,IAAI,CAAClB,IAAI;gBACd;YACF;QAEJ;IACF;AACF"}

View File

@@ -0,0 +1,76 @@
import cssnanoSimple from "next/dist/compiled/cssnano-simple";
import postcssScss from "next/dist/compiled/postcss-scss";
import postcss from "postcss";
import { webpack, sources } from "next/dist/compiled/webpack/webpack";
import { spans } from "./profiling-plugin";
// https://github.com/NMFR/optimize-css-assets-webpack-plugin/blob/0a410a9bf28c7b0e81a3470a13748e68ca2f50aa/src/index.js#L20
const CSS_REGEX = /\.css(\?.*)?$/i;
export class CssMinimizerPlugin {
constructor(options){
this.__next_css_remove = true;
this.options = options;
}
optimizeAsset(file, asset) {
const postcssOptions = {
...this.options.postcssOptions,
to: file,
from: file,
// We don't actually add this parser to support Sass. It can also be used
// for inline comment support. See the README:
// https://github.com/postcss/postcss-scss/blob/master/README.md#2-inline-comments-for-postcss
parser: postcssScss
};
let input;
if (postcssOptions.map && asset.sourceAndMap) {
const { source, map } = asset.sourceAndMap();
input = source;
postcssOptions.map.prev = map ? map : false;
} else {
input = asset.source();
}
return postcss([
cssnanoSimple({}, postcss)
]).process(input, postcssOptions).then((res)=>{
if (res.map) {
return new sources.SourceMapSource(res.css, file, res.map.toJSON());
} else {
return new sources.RawSource(res.css);
}
});
}
apply(compiler) {
compiler.hooks.compilation.tap("CssMinimizerPlugin", (compilation)=>{
const cache = compilation.getCache("CssMinimizerPlugin");
compilation.hooks.processAssets.tapPromise({
name: "CssMinimizerPlugin",
stage: webpack.Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE_SIZE
}, async (assets)=>{
const compilationSpan = spans.get(compilation) || spans.get(compiler);
const cssMinimizerSpan = compilationSpan.traceChild("css-minimizer-plugin");
cssMinimizerSpan.setAttribute("webpackVersion", 5);
return cssMinimizerSpan.traceAsyncFn(async ()=>{
const files = Object.keys(assets);
await Promise.all(files.filter((file)=>CSS_REGEX.test(file)).map(async (file)=>{
const assetSpan = cssMinimizerSpan.traceChild("minify-css");
assetSpan.setAttribute("file", file);
return assetSpan.traceAsyncFn(async ()=>{
const asset = assets[file];
const etag = cache.getLazyHashedEtag(asset);
const cachedResult = await cache.getPromise(file, etag);
assetSpan.setAttribute("cache", cachedResult ? "HIT" : "MISS");
if (cachedResult) {
assets[file] = cachedResult;
return;
}
const result = await this.optimizeAsset(file, asset);
await cache.storePromise(file, etag, result);
assets[file] = result;
});
}));
});
});
});
}
}
//# sourceMappingURL=css-minimizer-plugin.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../src/build/webpack/plugins/css-minimizer-plugin.ts"],"names":["cssnanoSimple","postcssScss","postcss","webpack","sources","spans","CSS_REGEX","CssMinimizerPlugin","constructor","options","__next_css_remove","optimizeAsset","file","asset","postcssOptions","to","from","parser","input","map","sourceAndMap","source","prev","process","then","res","SourceMapSource","css","toJSON","RawSource","apply","compiler","hooks","compilation","tap","cache","getCache","processAssets","tapPromise","name","stage","Compilation","PROCESS_ASSETS_STAGE_OPTIMIZE_SIZE","assets","compilationSpan","get","cssMinimizerSpan","traceChild","setAttribute","traceAsyncFn","files","Object","keys","Promise","all","filter","test","assetSpan","etag","getLazyHashedEtag","cachedResult","getPromise","result","storePromise"],"mappings":"AAAA,OAAOA,mBAAmB,oCAAmC;AAC7D,OAAOC,iBAAiB,kCAAiC;AACzD,OAAOC,aAAyB,UAAS;AACzC,SAASC,OAAO,EAAEC,OAAO,QAAQ,qCAAoC;AACrE,SAASC,KAAK,QAAQ,qBAAoB;AAE1C,4HAA4H;AAC5H,MAAMC,YAAY;AAQlB,OAAO,MAAMC;IAKXC,YAAYC,OAAkC,CAAE;aAJhDC,oBAAoB;QAKlB,IAAI,CAACD,OAAO,GAAGA;IACjB;IAEAE,cAAcC,IAAY,EAAEC,KAAU,EAAE;QACtC,MAAMC,iBAAiB;YACrB,GAAG,IAAI,CAACL,OAAO,CAACK,cAAc;YAC9BC,IAAIH;YACJI,MAAMJ;YAEN,yEAAyE;YACzE,8CAA8C;YAC9C,8FAA8F;YAC9FK,QAAQhB;QACV;QAEA,IAAIiB;QACJ,IAAIJ,eAAeK,GAAG,IAAIN,MAAMO,YAAY,EAAE;YAC5C,MAAM,EAAEC,MAAM,EAAEF,GAAG,EAAE,GAAGN,MAAMO,YAAY;YAC1CF,QAAQG;YACRP,eAAeK,GAAG,CAACG,IAAI,GAAGH,MAAMA,MAAM;QACxC,OAAO;YACLD,QAAQL,MAAMQ,MAAM;QACtB;QAEA,OAAOnB,QAAQ;YAACF,cAAc,CAAC,GAAGE;SAAS,EACxCqB,OAAO,CAACL,OAAOJ,gBACfU,IAAI,CAAC,CAACC;YACL,IAAIA,IAAIN,GAAG,EAAE;gBACX,OAAO,IAAIf,QAAQsB,eAAe,CAACD,IAAIE,GAAG,EAAEf,MAAMa,IAAIN,GAAG,CAACS,MAAM;YAClE,OAAO;gBACL,OAAO,IAAIxB,QAAQyB,SAAS,CAACJ,IAAIE,GAAG;YACtC;QACF;IACJ;IAEAG,MAAMC,QAA0B,EAAE;QAChCA,SAASC,KAAK,CAACC,WAAW,CAACC,GAAG,CAAC,sBAAsB,CAACD;YACpD,MAAME,QAAQF,YAAYG,QAAQ,CAAC;YACnCH,YAAYD,KAAK,CAACK,aAAa,CAACC,UAAU,CACxC;gBACEC,MAAM;gBACNC,OAAOrC,QAAQsC,WAAW,CAACC,kCAAkC;YAC/D,GACA,OAAOC;gBACL,MAAMC,kBAAkBvC,MAAMwC,GAAG,CAACZ,gBAAgB5B,MAAMwC,GAAG,CAACd;gBAC5D,MAAMe,mBAAmBF,gBAAiBG,UAAU,CAClD;gBAEFD,iBAAiBE,YAAY,CAAC,kBAAkB;gBAEhD,OAAOF,iBAAiBG,YAAY,CAAC;oBACnC,MAAMC,QAAQC,OAAOC,IAAI,CAACT;oBAC1B,MAAMU,QAAQC,GAAG,CACfJ,MACGK,MAAM,CAAC,CAAC3C,OAASN,UAAUkD,IAAI,CAAC5C,OAChCO,GAAG,CAAC,OAAOP;wBACV,MAAM6C,YAAYX,iBAAiBC,UAAU,CAAC;wBAC9CU,UAAUT,YAAY,CAAC,QAAQpC;wBAE/B,OAAO6C,UAAUR,YAAY,CAAC;4BAC5B,MAAMpC,QAAQ8B,MAAM,CAAC/B,KAAK;4BAE1B,MAAM8C,OAAOvB,MAAMwB,iBAAiB,CAAC9C;4BAErC,MAAM+C,eAAe,MAAMzB,MAAM0B,UAAU,CAACjD,MAAM8C;4BAElDD,UAAUT,YAAY,CACpB,SACAY,eAAe,QAAQ;4BAEzB,IAAIA,cAAc;gCAChBjB,MAAM,CAAC/B,KAAK,GAAGgD;gCACf;4BACF;4BAEA,MAAME,SAAS,MAAM,IAAI,CAACnD,aAAa,CAACC,MAAMC;4BAC9C,MAAMsB,MAAM4B,YAAY,CAACnD,MAAM8C,MAAMI;4BACrCnB,MAAM,CAAC/B,KAAK,GAAGkD;wBACjB;oBACF;gBAEN;YACF;QAEJ;IACF;AACF"}

View File

@@ -0,0 +1,583 @@
import { webpack } from "next/dist/compiled/webpack/webpack";
import { stringify } from "querystring";
import path from "path";
import { sources } from "next/dist/compiled/webpack/webpack";
import { getInvalidator, getEntries, EntryTypes, getEntryKey } from "../../../server/dev/on-demand-entry-handler";
import { WEBPACK_LAYERS } from "../../../lib/constants";
import { APP_CLIENT_INTERNALS, COMPILER_NAMES, EDGE_RUNTIME_WEBPACK, SERVER_REFERENCE_MANIFEST } from "../../../shared/lib/constants";
import { generateActionId, getActions, isClientComponentEntryModule, isCSSMod, regexCSS } from "../loaders/utils";
import { traverseModules, forEachEntryModule } from "../utils";
import { normalizePathSep } from "../../../shared/lib/page-path/normalize-path-sep";
import { getProxiedPluginState } from "../../build-context";
const PLUGIN_NAME = "FlightClientEntryPlugin";
const pluginState = getProxiedPluginState({
// A map to track "action" -> "list of bundles".
serverActions: {},
edgeServerActions: {},
actionModServerId: {},
actionModEdgeServerId: {},
// Mapping of resource path to module id for server/edge server.
serverModuleIds: {},
edgeServerModuleIds: {},
// Collect modules from server/edge compiler in client layer,
// and detect if it's been used, and mark it as `async: true` for react.
// So that react could unwrap the async module from promise and render module itself.
ASYNC_CLIENT_MODULES: [],
injectedClientEntries: {}
});
function deduplicateCSSImportsForEntry(mergedCSSimports) {
// If multiple entry module connections are having the same CSS import,
// we only need to have one module to keep track of that CSS import.
// It is based on the fact that if a page or a layout is rendered in the
// given entry, all its parent layouts are always rendered too.
// This can avoid duplicate CSS imports in the generated CSS manifest,
// for example, if a page and its parent layout are both using the same
// CSS import, we only need to have the layout to keep track of that CSS
// import.
// To achieve this, we need to first collect all the CSS imports from
// every connection, and deduplicate them in the order of layers from
// top to bottom. The implementation can be generally described as:
// - Sort by number of `/` in the request path (the more `/`, the deeper)
// - When in the same depth, sort by the filename (template < layout < page and others)
// Sort the connections as described above.
const sortedCSSImports = Object.entries(mergedCSSimports).sort((a, b)=>{
const [aPath] = a;
const [bPath] = b;
const aDepth = aPath.split("/").length;
const bDepth = bPath.split("/").length;
if (aDepth !== bDepth) {
return aDepth - bDepth;
}
const aName = path.parse(aPath).name;
const bName = path.parse(bPath).name;
const indexA = [
"template",
"layout"
].indexOf(aName);
const indexB = [
"template",
"layout"
].indexOf(bName);
if (indexA === -1) return 1;
if (indexB === -1) return -1;
return indexA - indexB;
});
const dedupedCSSImports = {};
const trackedCSSImports = new Set();
for (const [entryName, cssImports] of sortedCSSImports){
for (const cssImport of cssImports){
if (trackedCSSImports.has(cssImport)) continue;
// Only track CSS imports that are in files that can inherit CSS.
const filename = path.parse(entryName).name;
if ([
"template",
"layout"
].includes(filename)) {
trackedCSSImports.add(cssImport);
}
if (!dedupedCSSImports[entryName]) {
dedupedCSSImports[entryName] = [];
}
dedupedCSSImports[entryName].push(cssImport);
}
}
return dedupedCSSImports;
}
export class FlightClientEntryPlugin {
constructor(options){
this.dev = options.dev;
this.appDir = options.appDir;
this.isEdgeServer = options.isEdgeServer;
this.useServerActions = options.useServerActions;
this.serverActionsBodySizeLimit = options.serverActionsBodySizeLimit;
this.assetPrefix = !this.dev && !this.isEdgeServer ? "../" : "";
}
apply(compiler) {
compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation, { normalModuleFactory })=>{
compilation.dependencyFactories.set(webpack.dependencies.ModuleDependency, normalModuleFactory);
compilation.dependencyTemplates.set(webpack.dependencies.ModuleDependency, new webpack.dependencies.NullDependency.Template());
});
compiler.hooks.finishMake.tapPromise(PLUGIN_NAME, (compilation)=>this.createClientEntries(compiler, compilation));
compiler.hooks.afterCompile.tap(PLUGIN_NAME, (compilation)=>{
const recordModule = (modId, mod)=>{
var _mod_resourceResolveData, _mod_resourceResolveData1;
// Match Resource is undefined unless an import is using the inline match resource syntax
// https://webpack.js.org/api/loaders/#inline-matchresource
const modPath = mod.matchResource || ((_mod_resourceResolveData = mod.resourceResolveData) == null ? void 0 : _mod_resourceResolveData.path);
const modQuery = ((_mod_resourceResolveData1 = mod.resourceResolveData) == null ? void 0 : _mod_resourceResolveData1.query) || "";
// query is already part of mod.resource
// so it's only neccessary to add it for matchResource or mod.resourceResolveData
const modResource = modPath ? modPath + modQuery : mod.resource;
if (mod.layer !== WEBPACK_LAYERS.serverSideRendering) {
return;
}
// Check mod resource to exclude the empty resource module like virtual module created by next-flight-client-entry-loader
if (typeof modId !== "undefined" && modResource) {
// Note that this isn't that reliable as webpack is still possible to assign
// additional queries to make sure there's no conflict even using the `named`
// module ID strategy.
let ssrNamedModuleId = path.relative(compiler.context, modResource);
if (!ssrNamedModuleId.startsWith(".")) {
// TODO use getModuleId instead
ssrNamedModuleId = `./${normalizePathSep(ssrNamedModuleId)}`;
}
if (this.isEdgeServer) {
pluginState.edgeServerModuleIds[ssrNamedModuleId.replace(/\/next\/dist\/esm\//, "/next/dist/")] = modId;
} else {
pluginState.serverModuleIds[ssrNamedModuleId] = modId;
}
}
};
traverseModules(compilation, (mod, _chunk, _chunkGroup, modId)=>{
// The module must has request, and resource so it's not a new entry created with loader.
// Using the client layer module, which doesn't have `rsc` tag in buildInfo.
if (mod.request && mod.resource && !mod.buildInfo.rsc) {
if (compilation.moduleGraph.isAsync(mod)) {
pluginState.ASYNC_CLIENT_MODULES.push(mod.resource);
}
}
recordModule(String(modId), mod);
});
});
compiler.hooks.make.tap(PLUGIN_NAME, (compilation)=>{
compilation.hooks.processAssets.tap({
name: PLUGIN_NAME,
stage: webpack.Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE_HASH
}, (assets)=>this.createActionAssets(compilation, assets));
});
}
async createClientEntries(compiler, compilation) {
const addClientEntryAndSSRModulesList = [];
const createdSSRDependenciesForEntry = {};
const addActionEntryList = [];
const actionMapsPerEntry = {};
// For each SC server compilation entry, we need to create its corresponding
// client component entry.
forEachEntryModule(compilation, ({ name, entryModule })=>{
const internalClientComponentEntryImports = new Set();
const actionEntryImports = new Map();
const clientEntriesToInject = [];
const mergedCSSimports = {};
for (const connection of compilation.moduleGraph.getOutgoingConnections(entryModule)){
// Entry can be any user defined entry files such as layout, page, error, loading, etc.
const entryRequest = connection.dependency.request;
const { clientComponentImports, actionImports, cssImports } = this.collectComponentInfoFromServerEntryDependency({
entryRequest,
compilation,
resolvedModule: connection.resolvedModule
});
actionImports.forEach(([dep, names])=>actionEntryImports.set(dep, names));
const isAbsoluteRequest = path.isAbsolute(entryRequest);
// Next.js internals are put into a separate entry.
if (!isAbsoluteRequest) {
clientComponentImports.forEach((value)=>internalClientComponentEntryImports.add(value));
continue;
}
// TODO-APP: Enable these lines. This ensures no entrypoint is created for layout/page when there are no client components.
// Currently disabled because it causes test failures in CI.
// if (clientImports.length === 0 && actionImports.length === 0) {
// continue
// }
const relativeRequest = isAbsoluteRequest ? path.relative(compilation.options.context, entryRequest) : entryRequest;
// Replace file suffix as `.js` will be added.
const bundlePath = normalizePathSep(relativeRequest.replace(/\.[^.\\/]+$/, "").replace(/^src[\\/]/, ""));
Object.assign(mergedCSSimports, cssImports);
clientEntriesToInject.push({
compiler,
compilation,
entryName: name,
clientComponentImports,
bundlePath,
absolutePagePath: entryRequest
});
}
// Make sure CSS imports are deduplicated before injecting the client entry
// and SSR modules.
const dedupedCSSImports = deduplicateCSSImportsForEntry(mergedCSSimports);
for (const clientEntryToInject of clientEntriesToInject){
const injected = this.injectClientEntryAndSSRModules({
...clientEntryToInject,
clientImports: [
...clientEntryToInject.clientComponentImports,
...dedupedCSSImports[clientEntryToInject.absolutePagePath] || []
]
});
// Track all created SSR dependencies for each entry from the server layer.
if (!createdSSRDependenciesForEntry[clientEntryToInject.entryName]) {
createdSSRDependenciesForEntry[clientEntryToInject.entryName] = [];
}
createdSSRDependenciesForEntry[clientEntryToInject.entryName].push(injected[2]);
addClientEntryAndSSRModulesList.push(injected);
}
// Create internal app
addClientEntryAndSSRModulesList.push(this.injectClientEntryAndSSRModules({
compiler,
compilation,
entryName: name,
clientImports: [
...internalClientComponentEntryImports
],
bundlePath: APP_CLIENT_INTERNALS
}));
if (actionEntryImports.size > 0) {
if (!actionMapsPerEntry[name]) {
actionMapsPerEntry[name] = new Map();
}
actionMapsPerEntry[name] = new Map([
...actionMapsPerEntry[name],
...actionEntryImports
]);
}
});
const createdActions = new Set();
for (const [name, actionEntryImports] of Object.entries(actionMapsPerEntry)){
for (const [dep, actionNames] of actionEntryImports){
for (const actionName of actionNames){
createdActions.add(name + "@" + dep + "@" + actionName);
}
}
addActionEntryList.push(this.injectActionEntry({
compiler,
compilation,
actions: actionEntryImports,
entryName: name,
bundlePath: name
}));
}
if (this.useServerActions) {
compilation.hooks.finishModules.tapPromise(PLUGIN_NAME, ()=>{
const addedClientActionEntryList = [];
const actionMapsPerClientEntry = {};
// We need to create extra action entries that are created from the
// client layer.
// Start from each entry's created SSR dependency from our previous step.
for (const [name, ssrEntryDepdendencies] of Object.entries(createdSSRDependenciesForEntry)){
// Collect from all entries, e.g. layout.js, page.js, loading.js, ...
// add agregate them.
const actionEntryImports = this.collectClientActionsFromDependencies({
compilation,
dependencies: ssrEntryDepdendencies
});
if (actionEntryImports.size > 0) {
if (!actionMapsPerClientEntry[name]) {
actionMapsPerClientEntry[name] = new Map();
}
actionMapsPerClientEntry[name] = new Map([
...actionMapsPerClientEntry[name],
...actionEntryImports
]);
}
}
for (const [name, actionEntryImports] of Object.entries(actionMapsPerClientEntry)){
// If an action method is already created in the server layer, we don't
// need to create it again in the action layer.
// This is to avoid duplicate action instances and make sure the module
// state is shared.
let remainingClientImportedActions = false;
const remainingActionEntryImports = new Map();
for (const [dep, actionNames] of actionEntryImports){
const remainingActionNames = [];
for (const actionName of actionNames){
const id = name + "@" + dep + "@" + actionName;
if (!createdActions.has(id)) {
remainingActionNames.push(actionName);
}
}
if (remainingActionNames.length > 0) {
remainingActionEntryImports.set(dep, remainingActionNames);
remainingClientImportedActions = true;
}
}
if (remainingClientImportedActions) {
addedClientActionEntryList.push(this.injectActionEntry({
compiler,
compilation,
actions: remainingActionEntryImports,
entryName: name,
bundlePath: name,
fromClient: true
}));
}
}
return Promise.all(addedClientActionEntryList);
});
}
// Invalidate in development to trigger recompilation
const invalidator = getInvalidator(compiler.outputPath);
// Check if any of the entry injections need an invalidation
if (invalidator && addClientEntryAndSSRModulesList.some(([shouldInvalidate])=>shouldInvalidate === true)) {
invalidator.invalidate([
COMPILER_NAMES.client
]);
}
// Client compiler is invalidated before awaiting the compilation of the SSR client component entries
// so that the client compiler is running in parallel to the server compiler.
await Promise.all(addClientEntryAndSSRModulesList.map((addClientEntryAndSSRModules)=>addClientEntryAndSSRModules[1]));
// Wait for action entries to be added.
await Promise.all(addActionEntryList);
}
collectClientActionsFromDependencies({ compilation, dependencies }) {
// action file path -> action names
const collectedActions = new Map();
// Keep track of checked modules to avoid infinite loops with recursive imports.
const visitedModule = new Set();
const visitedEntry = new Set();
const collectActions = ({ entryRequest, resolvedModule })=>{
const collectActionsInDep = (mod)=>{
var _mod_resourceResolveData, _mod_resourceResolveData1;
if (!mod) return;
// We have to always use the resolved request here to make sure the
// server and client are using the same module path (required by RSC), as
// the server compiler and client compiler have different resolve configs.
const modRequest = ((_mod_resourceResolveData = mod.resourceResolveData) == null ? void 0 : _mod_resourceResolveData.path) + ((_mod_resourceResolveData1 = mod.resourceResolveData) == null ? void 0 : _mod_resourceResolveData1.query);
if (!modRequest || visitedModule.has(modRequest)) return;
visitedModule.add(modRequest);
const actions = getActions(mod);
if (actions) {
collectedActions.set(modRequest, actions);
}
compilation.moduleGraph.getOutgoingConnections(mod).forEach((connection)=>{
collectActionsInDep(connection.resolvedModule);
});
};
// Don't traverse the module graph anymore once hitting the action layer.
if (!entryRequest.includes("next-flight-action-entry-loader")) {
// Traverse the module graph to find all client components.
collectActionsInDep(resolvedModule);
}
};
for (const entryDependency of dependencies){
const ssrEntryModule = compilation.moduleGraph.getResolvedModule(entryDependency);
for (const connection of compilation.moduleGraph.getOutgoingConnections(ssrEntryModule)){
const dependency = connection.dependency;
const request = dependency.request;
// It is possible that the same entry is added multiple times in the
// connection graph. We can just skip these to speed up the process.
if (visitedEntry.has(request)) continue;
visitedEntry.add(request);
collectActions({
entryRequest: request,
resolvedModule: connection.resolvedModule
});
}
}
return collectedActions;
}
collectComponentInfoFromServerEntryDependency({ entryRequest, compilation, resolvedModule }) {
// Keep track of checked modules to avoid infinite loops with recursive imports.
const visited = new Set();
// Info to collect.
const clientComponentImports = [];
const actionImports = [];
const CSSImports = new Set();
const filterClientComponents = (mod)=>{
var _mod_resourceResolveData, _mod_resourceResolveData1;
if (!mod) return;
const isCSS = isCSSMod(mod);
// We have to always use the resolved request here to make sure the
// server and client are using the same module path (required by RSC), as
// the server compiler and client compiler have different resolve configs.
let modRequest = ((_mod_resourceResolveData = mod.resourceResolveData) == null ? void 0 : _mod_resourceResolveData.path) + ((_mod_resourceResolveData1 = mod.resourceResolveData) == null ? void 0 : _mod_resourceResolveData1.query);
// Context modules don't have a resource path, we use the identifier instead.
if (mod.constructor.name === "ContextModule") {
modRequest = mod._identifier;
}
if (!modRequest || visited.has(modRequest)) return;
visited.add(modRequest);
const actions = getActions(mod);
if (actions) {
actionImports.push([
modRequest,
actions
]);
}
if (isCSS) {
const sideEffectFree = mod.factoryMeta && mod.factoryMeta.sideEffectFree;
if (sideEffectFree) {
const unused = !compilation.moduleGraph.getExportsInfo(mod).isModuleUsed(this.isEdgeServer ? EDGE_RUNTIME_WEBPACK : "webpack-runtime");
if (unused) return;
}
CSSImports.add(modRequest);
}
if (isClientComponentEntryModule(mod)) {
clientComponentImports.push(modRequest);
return;
}
compilation.moduleGraph.getOutgoingConnections(mod).forEach((connection)=>{
filterClientComponents(connection.resolvedModule);
});
};
// Traverse the module graph to find all client components.
filterClientComponents(resolvedModule);
return {
clientComponentImports,
cssImports: CSSImports.size ? {
[entryRequest]: Array.from(CSSImports)
} : {},
actionImports
};
}
injectClientEntryAndSSRModules({ compiler, compilation, entryName, clientImports, bundlePath, absolutePagePath }) {
let shouldInvalidate = false;
const loaderOptions = {
modules: clientImports.sort((a, b)=>regexCSS.test(b) ? 1 : a.localeCompare(b)),
server: false
};
// For the client entry, we always use the CJS build of Next.js. If the
// server is using the ESM build (when using the Edge runtime), we need to
// replace them.
const clientLoader = `next-flight-client-entry-loader?${stringify({
modules: this.isEdgeServer ? loaderOptions.modules.map((importPath)=>importPath.replace(/[\\/]next[\\/]dist[\\/]esm[\\/]/, "/next/dist/".replace(/\//g, path.sep))) : loaderOptions.modules,
server: false
})}!`;
const clientSSRLoader = `next-flight-client-entry-loader?${stringify({
...loaderOptions,
server: true
})}!`;
// Add for the client compilation
// Inject the entry to the client compiler.
if (this.dev) {
const entries = getEntries(compiler.outputPath);
const pageKey = getEntryKey(COMPILER_NAMES.client, "app", bundlePath);
if (!entries[pageKey]) {
entries[pageKey] = {
type: EntryTypes.CHILD_ENTRY,
parentEntries: new Set([
entryName
]),
absoluteEntryFilePath: absolutePagePath,
bundlePath,
request: clientLoader,
dispose: false,
lastActiveTime: Date.now()
};
shouldInvalidate = true;
} else {
const entryData = entries[pageKey];
// New version of the client loader
if (entryData.request !== clientLoader) {
entryData.request = clientLoader;
shouldInvalidate = true;
}
if (entryData.type === EntryTypes.CHILD_ENTRY) {
entryData.parentEntries.add(entryName);
}
entryData.dispose = false;
entryData.lastActiveTime = Date.now();
}
} else {
pluginState.injectedClientEntries[bundlePath] = clientLoader;
}
// Inject the entry to the server compiler (__ssr__).
const clientComponentEntryDep = webpack.EntryPlugin.createDependency(clientSSRLoader, {
name: bundlePath
});
return [
shouldInvalidate,
// Add the dependency to the server compiler.
// This promise is awaited later using `Promise.all` in order to parallelize adding the entries.
// It ensures we can parallelize the SSR and Client compiler entries.
this.addEntry(compilation, // Reuse compilation context.
compiler.context, clientComponentEntryDep, {
// By using the same entry name
name: entryName,
// Layer should be client for the SSR modules
// This ensures the client components are bundled on client layer
layer: WEBPACK_LAYERS.serverSideRendering
}),
clientComponentEntryDep
];
}
injectActionEntry({ compiler, compilation, actions, entryName, bundlePath, fromClient }) {
const actionsArray = Array.from(actions.entries());
const actionLoader = `next-flight-action-entry-loader?${stringify({
actions: JSON.stringify(actionsArray),
__client_imported__: fromClient
})}!`;
const currentCompilerServerActions = this.isEdgeServer ? pluginState.edgeServerActions : pluginState.serverActions;
for (const [p, names] of actionsArray){
for (const name of names){
const id = generateActionId(p, name);
if (typeof currentCompilerServerActions[id] === "undefined") {
currentCompilerServerActions[id] = {
workers: {},
layer: {}
};
}
currentCompilerServerActions[id].workers[bundlePath] = "";
currentCompilerServerActions[id].layer[bundlePath] = fromClient ? WEBPACK_LAYERS.actionBrowser : WEBPACK_LAYERS.reactServerComponents;
}
}
// Inject the entry to the server compiler
const actionEntryDep = webpack.EntryPlugin.createDependency(actionLoader, {
name: bundlePath
});
return this.addEntry(compilation, // Reuse compilation context.
compiler.context, actionEntryDep, {
name: entryName,
layer: fromClient ? WEBPACK_LAYERS.actionBrowser : WEBPACK_LAYERS.reactServerComponents
});
}
addEntry(compilation, context, dependency, options) /* Promise<module> */ {
return new Promise((resolve, reject)=>{
const entry = compilation.entries.get(options.name);
entry.includeDependencies.push(dependency);
compilation.hooks.addEntry.call(entry, options);
compilation.addModuleTree({
context,
dependency,
contextInfo: {
issuerLayer: options.layer
}
}, (err, module)=>{
if (err) {
compilation.hooks.failedEntry.call(dependency, options, err);
return reject(err);
}
compilation.hooks.succeedEntry.call(dependency, options, module);
return resolve(module);
});
});
}
createActionAssets(compilation, assets) {
const serverActions = {};
const edgeServerActions = {};
if (this.useServerActions) {
traverseModules(compilation, (mod, _chunk, chunkGroup, modId)=>{
// Go through all action entries and record the module ID for each entry.
if (chunkGroup.name && mod.request && /next-flight-action-entry-loader/.test(mod.request)) {
const fromClient = /&__client_imported__=true/.test(mod.request);
const mapping = this.isEdgeServer ? pluginState.actionModEdgeServerId : pluginState.actionModServerId;
if (!mapping[chunkGroup.name]) {
mapping[chunkGroup.name] = {};
}
mapping[chunkGroup.name][fromClient ? "client" : "server"] = modId;
}
});
for(let id in pluginState.serverActions){
const action = pluginState.serverActions[id];
for(let name in action.workers){
const modId = pluginState.actionModServerId[name][action.layer[name] === WEBPACK_LAYERS.actionBrowser ? "client" : "server"];
action.workers[name] = modId;
}
serverActions[id] = action;
}
for(let id in pluginState.edgeServerActions){
const action = pluginState.edgeServerActions[id];
for(let name in action.workers){
const modId = pluginState.actionModEdgeServerId[name][action.layer[name] === WEBPACK_LAYERS.actionBrowser ? "client" : "server"];
action.workers[name] = modId;
}
edgeServerActions[id] = action;
}
}
const json = JSON.stringify({
node: serverActions,
edge: edgeServerActions
}, null, this.dev ? 2 : undefined);
assets[`${this.assetPrefix}${SERVER_REFERENCE_MANIFEST}.js`] = new sources.RawSource(`self.__RSC_SERVER_MANIFEST=${JSON.stringify(json)}`);
assets[`${this.assetPrefix}${SERVER_REFERENCE_MANIFEST}.json`] = new sources.RawSource(json);
}
}
//# sourceMappingURL=flight-client-entry-plugin.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,252 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/ import path from "path";
import { webpack, sources } from "next/dist/compiled/webpack/webpack";
import { CLIENT_REFERENCE_MANIFEST, SYSTEM_ENTRYPOINTS } from "../../../shared/lib/constants";
import { relative } from "path";
import { getProxiedPluginState } from "../../build-context";
import { nonNullable } from "../../../lib/non-nullable";
import { WEBPACK_LAYERS } from "../../../lib/constants";
import { normalizePagePath } from "../../../shared/lib/page-path/normalize-page-path";
const pluginState = getProxiedPluginState({
serverModuleIds: {},
edgeServerModuleIds: {},
ASYNC_CLIENT_MODULES: []
});
function getAppPathRequiredChunks(chunkGroup) {
return chunkGroup.chunks.map((requiredChunk)=>{
if (SYSTEM_ENTRYPOINTS.has(requiredChunk.name || "")) {
return null;
}
// Get the actual chunk file names from the chunk file list.
// It's possible that the chunk is generated via `import()`, in
// that case the chunk file name will be '[name].[contenthash]'
// instead of '[name]-[chunkhash]'.
return [
...requiredChunk.files
].map((file)=>{
// It's possible that a chunk also emits CSS files, that will
// be handled separatedly.
if (!file.endsWith(".js")) return null;
if (file.endsWith(".hot-update.js")) return null;
return requiredChunk.id + ":" + file;
});
}).flat().filter(nonNullable);
}
// Normalize the entry names to their "group names" so a page can easily track
// all the manifest items it needs from parent groups by looking up the group
// segments:
// - app/foo/loading -> app/foo
// - app/foo/page -> app/foo
// - app/(group)/@named/foo/page -> app/foo
// - app/(.)foo/(..)bar/loading -> app/bar
function entryNameToGroupName(entryName) {
let groupName = entryName.slice(0, entryName.lastIndexOf("/")).replace(/\/@[^/]+/g, "")// Remove the group with lookahead to make sure it's not interception route
.replace(/\/\([^/]+\)(?=(\/|$))/g, "");
// Interception routes
groupName = groupName.replace(/^.+\/\(\.\.\.\)/g, "app/").replace(/\/\(\.\)/g, "/");
// Interception routes (recursive)
while(/\/[^/]+\/\(\.\.\)/.test(groupName)){
groupName = groupName.replace(/\/[^/]+\/\(\.\.\)/g, "/");
}
return groupName;
}
function mergeManifest(manifest, manifestToMerge) {
Object.assign(manifest.clientModules, manifestToMerge.clientModules);
Object.assign(manifest.ssrModuleMapping, manifestToMerge.ssrModuleMapping);
Object.assign(manifest.edgeSSRModuleMapping, manifestToMerge.edgeSSRModuleMapping);
Object.assign(manifest.entryCSSFiles, manifestToMerge.entryCSSFiles);
}
const PLUGIN_NAME = "ClientReferenceManifestPlugin";
export class ClientReferenceManifestPlugin {
constructor(options){
this.dev = false;
this.dev = options.dev;
this.appDir = options.appDir;
this.appDirBase = path.dirname(this.appDir) + path.sep;
this.ASYNC_CLIENT_MODULES = new Set(pluginState.ASYNC_CLIENT_MODULES);
}
apply(compiler) {
compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation, { normalModuleFactory })=>{
compilation.dependencyFactories.set(webpack.dependencies.ModuleDependency, normalModuleFactory);
compilation.dependencyTemplates.set(webpack.dependencies.ModuleDependency, new webpack.dependencies.NullDependency.Template());
compilation.hooks.processAssets.tap({
name: PLUGIN_NAME,
// Have to be in the optimize stage to run after updating the CSS
// asset hash via extract mini css plugin.
stage: webpack.Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE_HASH
}, (assets)=>this.createAsset(assets, compilation, compiler.context));
});
}
createAsset(assets, compilation, context) {
const manifestsPerGroup = new Map();
const manifestEntryFiles = [];
compilation.chunkGroups.forEach((chunkGroup)=>{
// By default it's the shared chunkGroup (main-app) for every page.
let entryName = "";
const manifest = {
ssrModuleMapping: {},
edgeSSRModuleMapping: {},
clientModules: {},
entryCSSFiles: {}
};
if (chunkGroup.name && /^app[\\/]/.test(chunkGroup.name)) {
// Absolute path without the extension
const chunkEntryName = (this.appDirBase + chunkGroup.name).replace(/[\\/]/g, path.sep);
manifest.entryCSSFiles[chunkEntryName] = chunkGroup.getFiles().filter((f)=>!f.startsWith("static/css/pages/") && f.endsWith(".css"));
entryName = chunkGroup.name;
}
const requiredChunks = getAppPathRequiredChunks(chunkGroup);
const recordModule = (id, mod)=>{
var _mod_resourceResolveData;
// Skip all modules from the pages folder.
if (mod.layer !== WEBPACK_LAYERS.appPagesBrowser) {
return;
}
const resource = mod.type === "css/mini-extract" ? mod._identifier.slice(mod._identifier.lastIndexOf("!") + 1) : mod.resource;
if (!resource) {
return;
}
const moduleReferences = manifest.clientModules;
const moduleIdMapping = manifest.ssrModuleMapping;
const edgeModuleIdMapping = manifest.edgeSSRModuleMapping;
// Note that this isn't that reliable as webpack is still possible to assign
// additional queries to make sure there's no conflict even using the `named`
// module ID strategy.
let ssrNamedModuleId = relative(context, ((_mod_resourceResolveData = mod.resourceResolveData) == null ? void 0 : _mod_resourceResolveData.path) || resource);
if (!ssrNamedModuleId.startsWith(".")) ssrNamedModuleId = `./${ssrNamedModuleId.replace(/\\/g, "/")}`;
const isAsyncModule = this.ASYNC_CLIENT_MODULES.has(mod.resource);
// The client compiler will always use the CJS Next.js build, so here we
// also add the mapping for the ESM build (Edge runtime) to consume.
const esmResource = /[\\/]next[\\/]dist[\\/]/.test(resource) ? resource.replace(/[\\/]next[\\/]dist[\\/]/, "/next/dist/esm/".replace(/\//g, path.sep)) : null;
function addClientReference() {
const exportName = resource;
manifest.clientModules[exportName] = {
id,
name: "*",
chunks: requiredChunks,
async: isAsyncModule
};
if (esmResource) {
const edgeExportName = esmResource;
manifest.clientModules[edgeExportName] = manifest.clientModules[exportName];
}
}
function addSSRIdMapping() {
const exportName = resource;
if (typeof pluginState.serverModuleIds[ssrNamedModuleId] !== "undefined") {
moduleIdMapping[id] = moduleIdMapping[id] || {};
moduleIdMapping[id]["*"] = {
...manifest.clientModules[exportName],
// During SSR, we don't have external chunks to load on the server
// side with our architecture of Webpack / Turbopack. We can keep
// this field empty to save some bytes.
chunks: [],
id: pluginState.serverModuleIds[ssrNamedModuleId]
};
}
if (typeof pluginState.edgeServerModuleIds[ssrNamedModuleId] !== "undefined") {
edgeModuleIdMapping[id] = edgeModuleIdMapping[id] || {};
edgeModuleIdMapping[id]["*"] = {
...manifest.clientModules[exportName],
// During SSR, we don't have external chunks to load on the server
// side with our architecture of Webpack / Turbopack. We can keep
// this field empty to save some bytes.
chunks: [],
id: pluginState.edgeServerModuleIds[ssrNamedModuleId]
};
}
}
addClientReference();
addSSRIdMapping();
manifest.clientModules = moduleReferences;
manifest.ssrModuleMapping = moduleIdMapping;
manifest.edgeSSRModuleMapping = edgeModuleIdMapping;
};
// Only apply following logic to client module requests from client entry,
// or if the module is marked as client module. That's because other
// client modules don't need to be in the manifest at all as they're
// never be referenced by the server/client boundary.
// This saves a lot of bytes in the manifest.
chunkGroup.chunks.forEach((chunk)=>{
const entryMods = compilation.chunkGraph.getChunkEntryModulesIterable(chunk);
for (const mod of entryMods){
if (mod.layer !== WEBPACK_LAYERS.appPagesBrowser) continue;
const request = mod.request;
if (!request || !request.includes("next-flight-client-entry-loader.js?")) {
continue;
}
const connections = compilation.moduleGraph.getOutgoingConnections(mod);
for (const connection of connections){
const dependency = connection.dependency;
if (!dependency) continue;
const clientEntryMod = compilation.moduleGraph.getResolvedModule(dependency);
const modId = compilation.chunkGraph.getModuleId(clientEntryMod);
if (modId !== null) {
recordModule(modId, clientEntryMod);
} else {
var _connection_module;
// If this is a concatenation, register each child to the parent ID.
if (((_connection_module = connection.module) == null ? void 0 : _connection_module.constructor.name) === "ConcatenatedModule") {
const concatenatedMod = connection.module;
const concatenatedModId = compilation.chunkGraph.getModuleId(concatenatedMod);
recordModule(concatenatedModId, clientEntryMod);
}
}
}
}
});
// A page's entry name can have extensions. For example, these are both valid:
// - app/foo/page
// - app/foo/page.page
if (/\/page(\.[^/]+)?$/.test(entryName)) {
manifestEntryFiles.push(entryName.replace(/\/page(\.[^/]+)?$/, "/page"));
}
// Special case for the root not-found page.
// dev: app/not-found
// prod: app/_not-found
if (/^app\/_?not-found(\.[^.]+)?$/.test(entryName)) {
manifestEntryFiles.push(this.dev ? "app/not-found" : "app/_not-found");
}
const groupName = entryNameToGroupName(entryName);
if (!manifestsPerGroup.has(groupName)) {
manifestsPerGroup.set(groupName, []);
}
manifestsPerGroup.get(groupName).push(manifest);
});
// Generate per-page manifests.
for (const pageName of manifestEntryFiles){
const mergedManifest = {
ssrModuleMapping: {},
edgeSSRModuleMapping: {},
clientModules: {},
entryCSSFiles: {}
};
const segments = [
...entryNameToGroupName(pageName).split("/"),
"page"
];
let group = "";
for (const segment of segments){
for (const manifest of manifestsPerGroup.get(group) || []){
mergeManifest(mergedManifest, manifest);
}
group += (group ? "/" : "") + segment;
}
const json = JSON.stringify(mergedManifest);
const pagePath = pageName.replace(/%5F/g, "_");
const pageBundlePath = normalizePagePath(pagePath.slice("app".length));
assets["server/app" + pageBundlePath + "_" + CLIENT_REFERENCE_MANIFEST + ".js"] = new sources.RawSource(`globalThis.__RSC_MANIFEST=(globalThis.__RSC_MANIFEST||{});globalThis.__RSC_MANIFEST[${JSON.stringify(pagePath.slice("app".length))}]=${json}`);
if (pagePath === "app/not-found") {
// Create a separate special manifest for the root not-found page.
assets["server/app/_not-found_" + CLIENT_REFERENCE_MANIFEST + ".js"] = new sources.RawSource(`globalThis.__RSC_MANIFEST=(globalThis.__RSC_MANIFEST||{});globalThis.__RSC_MANIFEST[${JSON.stringify("/_not-found")}]=${json}`);
}
}
pluginState.ASYNC_CLIENT_MODULES = [];
}
}
//# sourceMappingURL=flight-manifest-plugin.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,168 @@
import { webpack, BasicEvaluatedExpression, sources } from "next/dist/compiled/webpack/webpack";
import { getFontDefinitionFromNetwork, getFontOverrideCss } from "../../../server/font-utils";
import postcss from "postcss";
import minifier from "next/dist/compiled/cssnano-simple";
import { FONT_MANIFEST, OPTIMIZED_FONT_PROVIDERS } from "../../../shared/lib/constants";
import * as Log from "../../output/log";
function minifyCss(css) {
return postcss([
minifier({
excludeAll: true,
discardComments: true,
normalizeWhitespace: {
exclude: false
}
}, postcss)
]).process(css, {
from: undefined
}).then((res)=>res.css);
}
function isNodeCreatingLinkElement(node) {
const callee = node.callee;
if (callee.type !== "Identifier") {
return false;
}
const componentNode = node.arguments[0];
if (componentNode.type !== "Literal") {
return false;
}
// React has pragma: _jsx.
// Next has pragma: __jsx.
return (callee.name === "_jsx" || callee.name === "__jsx") && componentNode.value === "link";
}
export class FontStylesheetGatheringPlugin {
constructor({ adjustFontFallbacks, adjustFontFallbacksWithSizeAdjust }){
this.gatheredStylesheets = [];
this.manifestContent = [];
this.parserHandler = (factory)=>{
const JS_TYPES = [
"auto",
"esm",
"dynamic"
];
// Do an extra walk per module and add interested visitors to the walk.
for (const type of JS_TYPES){
factory.hooks.parser.for("javascript/" + type).tap(this.constructor.name, (parser)=>{
/**
* Webpack fun facts:
* `parser.hooks.call.for` cannot catch calls for user defined identifiers like `__jsx`
* it can only detect calls for native objects like `window`, `this`, `eval` etc.
* In order to be able to catch calls of variables like `__jsx`, first we need to catch them as
* Identifier and then return `BasicEvaluatedExpression` whose `id` and `type` webpack matches to
* invoke hook for call.
* See: https://github.com/webpack/webpack/blob/webpack-4/lib/Parser.js#L1931-L1932.
*/ parser.hooks.evaluate.for("Identifier").tap(this.constructor.name, (node)=>{
var _parser_state_module, _parser_state;
// We will only optimize fonts from first party code.
if (parser == null ? void 0 : (_parser_state = parser.state) == null ? void 0 : (_parser_state_module = _parser_state.module) == null ? void 0 : _parser_state_module.resource.includes("node_modules")) {
return;
}
let result;
if (node.name === "_jsx" || node.name === "__jsx") {
result = new BasicEvaluatedExpression();
// @ts-ignore
result.setRange(node.range);
result.setExpression(node);
result.setIdentifier(node.name);
// This was added in webpack 5.
result.getMembers = ()=>[];
}
return result;
});
const jsxNodeHandler = (node)=>{
var _parser_state_module, _parser_state;
if (node.arguments.length !== 2) {
// A font link tag has only two arguments rel=stylesheet and href='...'
return;
}
if (!isNodeCreatingLinkElement(node)) {
return;
}
// node.arguments[0] is the name of the tag and [1] are the props.
const arg1 = node.arguments[1];
const propsNode = arg1.type === "ObjectExpression" ? arg1 : undefined;
const props = {};
if (propsNode) {
propsNode.properties.forEach((prop)=>{
if (prop.type !== "Property") {
return;
}
if (prop.key.type === "Identifier" && prop.value.type === "Literal") {
props[prop.key.name] = prop.value.value;
}
});
}
if (!props.rel || props.rel !== "stylesheet" || !props.href || !OPTIMIZED_FONT_PROVIDERS.some(({ url })=>props.href.startsWith(url))) {
return false;
}
this.gatheredStylesheets.push(props.href);
const buildInfo = parser == null ? void 0 : (_parser_state = parser.state) == null ? void 0 : (_parser_state_module = _parser_state.module) == null ? void 0 : _parser_state_module.buildInfo;
if (buildInfo) {
buildInfo.valueDependencies.set(FONT_MANIFEST, this.gatheredStylesheets);
}
};
// React JSX transform:
parser.hooks.call.for("_jsx").tap(this.constructor.name, jsxNodeHandler);
// Next.js JSX transform:
parser.hooks.call.for("__jsx").tap(this.constructor.name, jsxNodeHandler);
// New React JSX transform:
parser.hooks.call.for("imported var").tap(this.constructor.name, jsxNodeHandler);
});
}
};
this.adjustFontFallbacks = adjustFontFallbacks;
this.adjustFontFallbacksWithSizeAdjust = adjustFontFallbacksWithSizeAdjust;
}
apply(compiler) {
this.compiler = compiler;
compiler.hooks.normalModuleFactory.tap(this.constructor.name, this.parserHandler);
compiler.hooks.make.tapAsync(this.constructor.name, (compilation, cb)=>{
compilation.hooks.finishModules.tapAsync(this.constructor.name, async (modules, modulesFinished)=>{
let fontStylesheets = this.gatheredStylesheets;
const fontUrls = new Set();
modules.forEach((module)=>{
var _module_buildInfo_valueDependencies, _module_buildInfo;
const fontDependencies = module == null ? void 0 : (_module_buildInfo = module.buildInfo) == null ? void 0 : (_module_buildInfo_valueDependencies = _module_buildInfo.valueDependencies) == null ? void 0 : _module_buildInfo_valueDependencies.get(FONT_MANIFEST);
if (fontDependencies) {
fontDependencies.forEach((v)=>fontUrls.add(v));
}
});
fontStylesheets = Array.from(fontUrls);
const fontDefinitionPromises = fontStylesheets.map((url)=>getFontDefinitionFromNetwork(url));
this.manifestContent = [];
for(let promiseIndex in fontDefinitionPromises){
let css = await fontDefinitionPromises[promiseIndex];
if (this.adjustFontFallbacks) {
css += getFontOverrideCss(fontStylesheets[promiseIndex], css, this.adjustFontFallbacksWithSizeAdjust);
}
if (css) {
try {
const content = await minifyCss(css);
this.manifestContent.push({
url: fontStylesheets[promiseIndex],
content
});
} catch (err) {
Log.warn(`Failed to minify the stylesheet for ${fontStylesheets[promiseIndex]}. Skipped optimizing this font.`);
console.error(err);
}
}
}
// @ts-expect-error invalid assets type
compilation.assets[FONT_MANIFEST] = new sources.RawSource(JSON.stringify(this.manifestContent, null, " "));
modulesFinished();
});
cb();
});
compiler.hooks.make.tap(this.constructor.name, (compilation)=>{
compilation.hooks.processAssets.tap({
name: this.constructor.name,
stage: webpack.Compilation.PROCESS_ASSETS_STAGE_ADDITIONS
}, (assets)=>{
assets["../" + FONT_MANIFEST] = new sources.RawSource(JSON.stringify(this.manifestContent, null, " "));
});
});
}
}
//# sourceMappingURL=font-stylesheet-gathering-plugin.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,175 @@
/**
* This webpack resolver is largely based on TypeScript's "paths" handling
* The TypeScript license can be found here:
* https://github.com/microsoft/TypeScript/blob/214df64e287804577afa1fea0184c18c40f7d1ca/LICENSE.txt
*/ import path from "path";
import { debug } from "next/dist/compiled/debug";
const log = debug("next:jsconfig-paths-plugin");
const asterisk = 0x2a;
export function hasZeroOrOneAsteriskCharacter(str) {
let seenAsterisk = false;
for(let i = 0; i < str.length; i++){
if (str.charCodeAt(i) === asterisk) {
if (!seenAsterisk) {
seenAsterisk = true;
} else {
// have already seen asterisk
return false;
}
}
}
return true;
}
/**
* Determines whether a path starts with a relative path component (i.e. `.` or `..`).
*/ export function pathIsRelative(testPath) {
return /^\.\.?($|[\\/])/.test(testPath);
}
export function tryParsePattern(pattern) {
// This should be verified outside of here and a proper error thrown.
const indexOfStar = pattern.indexOf("*");
return indexOfStar === -1 ? undefined : {
prefix: pattern.slice(0, indexOfStar),
suffix: pattern.slice(indexOfStar + 1)
};
}
function isPatternMatch({ prefix, suffix }, candidate) {
return candidate.length >= prefix.length + suffix.length && candidate.startsWith(prefix) && candidate.endsWith(suffix);
}
/** Return the object corresponding to the best pattern to match `candidate`. */ export function findBestPatternMatch(values, getPattern, candidate) {
let matchedValue;
// use length of prefix as betterness criteria
let longestMatchPrefixLength = -1;
for (const v of values){
const pattern = getPattern(v);
if (isPatternMatch(pattern, candidate) && pattern.prefix.length > longestMatchPrefixLength) {
longestMatchPrefixLength = pattern.prefix.length;
matchedValue = v;
}
}
return matchedValue;
}
/**
* patternStrings contains both pattern strings (containing "*") and regular strings.
* Return an exact match if possible, or a pattern match, or undefined.
* (These are verified by verifyCompilerOptions to have 0 or 1 "*" characters.)
*/ export function matchPatternOrExact(patternStrings, candidate) {
const patterns = [];
for (const patternString of patternStrings){
if (!hasZeroOrOneAsteriskCharacter(patternString)) continue;
const pattern = tryParsePattern(patternString);
if (pattern) {
patterns.push(pattern);
} else if (patternString === candidate) {
// pattern was matched as is - no need to search further
return patternString;
}
}
return findBestPatternMatch(patterns, (_)=>_, candidate);
}
/**
* Tests whether a value is string
*/ export function isString(text) {
return typeof text === "string";
}
/**
* Given that candidate matches pattern, returns the text matching the '*'.
* E.g.: matchedText(tryParsePattern("foo*baz"), "foobarbaz") === "bar"
*/ export function matchedText(pattern, candidate) {
return candidate.substring(pattern.prefix.length, candidate.length - pattern.suffix.length);
}
export function patternText({ prefix, suffix }) {
return `${prefix}*${suffix}`;
}
/**
* Calls the iterator function for each entry of the array
* until the first result or error is reached
*/ function forEachBail(array, iterator, callback) {
if (array.length === 0) return callback();
let i = 0;
const next = ()=>{
let loop = undefined;
iterator(array[i++], (err, result)=>{
if (err || result !== undefined || i >= array.length) {
return callback(err, result);
}
if (loop === false) while(next());
loop = true;
});
if (!loop) loop = false;
return loop;
};
while(next());
}
const NODE_MODULES_REGEX = /node_modules/;
/**
* Handles tsconfig.json or jsconfig.js "paths" option for webpack
* Largely based on how the TypeScript compiler handles it:
* https://github.com/microsoft/TypeScript/blob/1a9c8197fffe3dace5f8dca6633d450a88cba66d/src/compiler/moduleNameResolver.ts#L1362
*/ export class JsConfigPathsPlugin {
constructor(paths, resolvedBaseUrl){
this.paths = paths;
this.resolvedBaseUrl = resolvedBaseUrl;
this.jsConfigPlugin = true;
log("tsconfig.json or jsconfig.json paths: %O", paths);
log("resolved baseUrl: %s", resolvedBaseUrl);
}
apply(resolver) {
const target = resolver.ensureHook("resolve");
resolver.getHook("described-resolve").tapAsync("JsConfigPathsPlugin", (request, resolveContext, callback)=>{
const paths = this.paths;
const pathsKeys = Object.keys(paths);
// If no aliases are added bail out
if (pathsKeys.length === 0) {
log("paths are empty, bailing out");
return callback();
}
const moduleName = request.request;
// Exclude node_modules from paths support (speeds up resolving)
if (request.path.match(NODE_MODULES_REGEX)) {
log("skipping request as it is inside node_modules %s", moduleName);
return callback();
}
if (path.posix.isAbsolute(moduleName) || process.platform === "win32" && path.win32.isAbsolute(moduleName)) {
log("skipping request as it is an absolute path %s", moduleName);
return callback();
}
if (pathIsRelative(moduleName)) {
log("skipping request as it is a relative path %s", moduleName);
return callback();
}
// log('starting to resolve request %s', moduleName)
// If the module name does not match any of the patterns in `paths` we hand off resolving to webpack
const matchedPattern = matchPatternOrExact(pathsKeys, moduleName);
if (!matchedPattern) {
log("moduleName did not match any paths pattern %s", moduleName);
return callback();
}
const matchedStar = isString(matchedPattern) ? undefined : matchedText(matchedPattern, moduleName);
const matchedPatternText = isString(matchedPattern) ? matchedPattern : patternText(matchedPattern);
let triedPaths = [];
forEachBail(paths[matchedPatternText], (subst, pathCallback)=>{
const curPath = matchedStar ? subst.replace("*", matchedStar) : subst;
// Ensure .d.ts is not matched
if (curPath.endsWith(".d.ts")) {
// try next path candidate
return pathCallback();
}
const candidate = path.join(this.resolvedBaseUrl, curPath);
const obj = Object.assign({}, request, {
request: candidate
});
resolver.doResolve(target, obj, `Aliased with tsconfig.json or jsconfig.json ${matchedPatternText} to ${candidate}`, resolveContext, (resolverErr, resolverResult)=>{
if (resolverErr || resolverResult === undefined) {
triedPaths.push(candidate);
// try next path candidate
return pathCallback();
}
return pathCallback(resolverErr, resolverResult);
});
}, callback);
});
}
}
//# sourceMappingURL=jsconfig-paths-plugin.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../src/build/webpack/plugins/jsconfig-paths-plugin.ts"],"names":["path","debug","log","asterisk","hasZeroOrOneAsteriskCharacter","str","seenAsterisk","i","length","charCodeAt","pathIsRelative","testPath","test","tryParsePattern","pattern","indexOfStar","indexOf","undefined","prefix","slice","suffix","isPatternMatch","candidate","startsWith","endsWith","findBestPatternMatch","values","getPattern","matchedValue","longestMatchPrefixLength","v","matchPatternOrExact","patternStrings","patterns","patternString","push","_","isString","text","matchedText","substring","patternText","forEachBail","array","iterator","callback","next","loop","err","result","NODE_MODULES_REGEX","JsConfigPathsPlugin","constructor","paths","resolvedBaseUrl","jsConfigPlugin","apply","resolver","target","ensureHook","getHook","tapAsync","request","resolveContext","pathsKeys","Object","keys","moduleName","match","posix","isAbsolute","process","platform","win32","matchedPattern","matchedStar","matchedPatternText","triedPaths","subst","pathCallback","curPath","replace","join","obj","assign","doResolve","resolverErr","resolverResult"],"mappings":"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"}

View File

@@ -0,0 +1,104 @@
/*
This plugin is based on the internal one in webpack but heavily modified to use a different caching heuristic.
https://github.com/webpack/webpack/blob/853bfda35a0080605c09e1bdeb0103bcb9367a10/lib/cache/MemoryWithGcCachePlugin.js#L15
https://github.com/webpack/webpack/blob/main/LICENSE
Copyright JS Foundation and other contributors
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 SOFTWARE.
*/ /*
The change in this plugin compared to the built-in one in webpack is that this plugin always cleans up after 5 compilations.
The built-in plugin only cleans up "total modules / max generations".
The default for max generations is 5, so 1/5th of the modules would be marked for deletion.
This plugin instead always checks the cache and decreases the time to live of all entries. That way memory is cleaned up earlier.
*/ // Used to hook into the memory stage of the webpack caching
const CACHE_STAGE_MEMORY = -10 // TODO: Somehow webpack.Cache.STAGE_MEMORY doesn't work.
;
const PLUGIN_NAME = "NextJsMemoryWithGcCachePlugin";
export class MemoryWithGcCachePlugin {
constructor({ maxGenerations }){
this.maxGenerations = maxGenerations;
}
apply(compiler) {
const maxGenerations = this.maxGenerations;
/**
* The memory cache
*/ const cache = new Map();
/**
* Cache cleanup implementation
*/ function decreaseTTLAndEvict() {
for (const [identifier, entry] of cache){
// Decrease item time to live
entry.ttl--;
// if ttl is 0 or below, evict entry from the cache
if (entry.ttl <= 0) {
cache.delete(identifier);
}
}
}
compiler.hooks.afterDone.tap(PLUGIN_NAME, decreaseTTLAndEvict);
compiler.cache.hooks.store.tap({
name: PLUGIN_NAME,
stage: CACHE_STAGE_MEMORY
}, (identifier, etag, data)=>{
cache.set(identifier, {
etag,
data,
ttl: maxGenerations
});
});
compiler.cache.hooks.get.tap({
name: PLUGIN_NAME,
stage: CACHE_STAGE_MEMORY
}, (identifier, etag, gotHandlers)=>{
const cacheEntry = cache.get(identifier);
// Item found
if (cacheEntry !== undefined) {
// When cache entry is hit we reset the counter.
cacheEntry.ttl = maxGenerations;
// Handles `null` separately as it doesn't have an etag.
if (cacheEntry.data === null) {
return null;
}
return cacheEntry.etag === etag ? cacheEntry.data : null;
}
// Handle case where other cache does have the identifier, puts it into the memory cache
gotHandlers.push((result, callback)=>{
cache.set(identifier, {
// Handles `null` separately as it doesn't have an etag.
etag: result === null ? null : etag,
data: result,
ttl: maxGenerations
});
return callback();
});
// No item found
return undefined;
});
compiler.cache.hooks.shutdown.tap({
name: PLUGIN_NAME,
stage: CACHE_STAGE_MEMORY
}, ()=>{
cache.clear();
});
}
}
//# sourceMappingURL=memory-with-gc-cache-plugin.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../src/build/webpack/plugins/memory-with-gc-cache-plugin.ts"],"names":["CACHE_STAGE_MEMORY","PLUGIN_NAME","MemoryWithGcCachePlugin","constructor","maxGenerations","apply","compiler","cache","Map","decreaseTTLAndEvict","identifier","entry","ttl","delete","hooks","afterDone","tap","store","name","stage","etag","data","set","get","gotHandlers","cacheEntry","undefined","push","result","callback","shutdown","clear"],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;AAyBA,GAEA;;;;;AAKA,GAyBA,4DAA4D;AAC5D,MAAMA,qBAAqB,CAAC,GAAG,yDAAyD;;AAExF,MAAMC,cAAc;AAEpB,OAAO,MAAMC;IAMXC,YAAY,EAAEC,cAAc,EAA8B,CAAE;QAC1D,IAAI,CAACA,cAAc,GAAGA;IACxB;IACAC,MAAMC,QAAkB,EAAE;QACxB,MAAMF,iBAAiB,IAAI,CAACA,cAAc;QAE1C;;KAEC,GACD,MAAMG,QAAQ,IAAIC;QAElB;;KAEC,GACD,SAASC;YACP,KAAK,MAAM,CAACC,YAAYC,MAAM,IAAIJ,MAAO;gBACvC,6BAA6B;gBAC7BI,MAAMC,GAAG;gBAET,mDAAmD;gBACnD,IAAID,MAAMC,GAAG,IAAI,GAAG;oBAClBL,MAAMM,MAAM,CAACH;gBACf;YACF;QACF;QACAJ,SAASQ,KAAK,CAACC,SAAS,CAACC,GAAG,CAACf,aAAaQ;QAC1CH,SAASC,KAAK,CAACO,KAAK,CAACG,KAAK,CAACD,GAAG,CAC5B;YAAEE,MAAMjB;YAAakB,OAAOnB;QAAmB,GAC/C,CAACU,YAAYU,MAAMC;YACjBd,MAAMe,GAAG,CAACZ,YAAY;gBAAEU;gBAAMC;gBAAMT,KAAKR;YAAe;QAC1D;QAEFE,SAASC,KAAK,CAACO,KAAK,CAACS,GAAG,CAACP,GAAG,CAC1B;YAAEE,MAAMjB;YAAakB,OAAOnB;QAAmB,GAC/C,CAACU,YAAYU,MAAMI;YACjB,MAAMC,aAAalB,MAAMgB,GAAG,CAACb;YAC7B,aAAa;YACb,IAAIe,eAAeC,WAAW;gBAC5B,gDAAgD;gBAChDD,WAAWb,GAAG,GAAGR;gBACjB,wDAAwD;gBACxD,IAAIqB,WAAWJ,IAAI,KAAK,MAAM;oBAC5B,OAAO;gBACT;gBAEA,OAAOI,WAAWL,IAAI,KAAKA,OAAOK,WAAWJ,IAAI,GAAG;YACtD;YAEA,wFAAwF;YACxFG,YAAYG,IAAI,CAAC,CAACC,QAAQC;gBACxBtB,MAAMe,GAAG,CAACZ,YAAY;oBACpB,wDAAwD;oBACxDU,MAAMQ,WAAW,OAAO,OAAOR;oBAC/BC,MAAMO;oBACNhB,KAAKR;gBACP;gBACA,OAAOyB;YACT;YAEA,gBAAgB;YAChB,OAAOH;QACT;QAEFpB,SAASC,KAAK,CAACO,KAAK,CAACgB,QAAQ,CAACd,GAAG,CAC/B;YAAEE,MAAMjB;YAAakB,OAAOnB;QAAmB,GAC/C;YACEO,MAAMwB,KAAK;QACb;IAEJ;AACF"}

View File

@@ -0,0 +1,510 @@
import { getNamedMiddlewareRegex } from "../../../shared/lib/router/utils/route-regex";
import { getModuleBuildInfo } from "../loaders/get-module-build-info";
import { getSortedRoutes } from "../../../shared/lib/router/utils";
import { webpack, sources } from "next/dist/compiled/webpack/webpack";
import { isMatch } from "next/dist/compiled/micromatch";
import path from "path";
import { EDGE_RUNTIME_WEBPACK, EDGE_UNSUPPORTED_NODE_APIS, MIDDLEWARE_BUILD_MANIFEST, CLIENT_REFERENCE_MANIFEST, MIDDLEWARE_MANIFEST, MIDDLEWARE_REACT_LOADABLE_MANIFEST, SUBRESOURCE_INTEGRITY_MANIFEST, NEXT_FONT_MANIFEST, SERVER_REFERENCE_MANIFEST, PRERENDER_MANIFEST } from "../../../shared/lib/constants";
import { traceGlobals } from "../../../trace/shared";
import { EVENT_BUILD_FEATURE_USAGE } from "../../../telemetry/events";
import { normalizeAppPath } from "../../../shared/lib/router/utils/app-paths";
import { INSTRUMENTATION_HOOK_FILENAME } from "../../../lib/constants";
import { NextBuildContext } from "../../build-context";
const KNOWN_SAFE_DYNAMIC_PACKAGES = require("../../../lib/known-edge-safe-packages.json");
const NAME = "MiddlewarePlugin";
/**
* Checks the value of usingIndirectEval and when it is a set of modules it
* check if any of the modules is actually being used. If the value is
* simply truthy it will return true.
*/ function isUsingIndirectEvalAndUsedByExports(args) {
const { moduleGraph, runtime, module, usingIndirectEval, wp } = args;
if (typeof usingIndirectEval === "boolean") {
return usingIndirectEval;
}
const exportsInfo = moduleGraph.getExportsInfo(module);
for (const exportName of usingIndirectEval){
if (exportsInfo.getUsed(exportName, runtime) !== wp.UsageState.Unused) {
return true;
}
}
return false;
}
function getEntryFiles(entryFiles, meta, opts) {
const files = [];
if (meta.edgeSSR) {
if (meta.edgeSSR.isServerComponent) {
files.push(`server/${SERVER_REFERENCE_MANIFEST}.js`);
if (opts.sriEnabled) {
files.push(`server/${SUBRESOURCE_INTEGRITY_MANIFEST}.js`);
}
files.push(...entryFiles.filter((file)=>file.startsWith("app/") && !file.endsWith(".hot-update.js")).map((file)=>"server/" + file.replace(".js", "_" + CLIENT_REFERENCE_MANIFEST + ".js")));
}
files.push(`server/${MIDDLEWARE_BUILD_MANIFEST}.js`, `server/${MIDDLEWARE_REACT_LOADABLE_MANIFEST}.js`);
files.push(`server/${NEXT_FONT_MANIFEST}.js`);
}
if (NextBuildContext.hasInstrumentationHook) {
files.push(`server/edge-${INSTRUMENTATION_HOOK_FILENAME}.js`);
}
if (process.env.NODE_ENV === "production") {
files.push(PRERENDER_MANIFEST.replace("json", "js"));
}
files.push(...entryFiles.filter((file)=>!file.endsWith(".hot-update.js")).map((file)=>"server/" + file));
return files;
}
function getCreateAssets(params) {
const { compilation, metadataByEntry, opts } = params;
return (assets)=>{
const middlewareManifest = {
sortedMiddleware: [],
middleware: {},
functions: {},
version: 2
};
for (const entrypoint of compilation.entrypoints.values()){
var _metadata_edgeMiddleware, _metadata_edgeSSR, _metadata_edgeApiFunction, _metadata_edgeSSR1, _metadata_edgeMiddleware1;
if (!entrypoint.name) {
continue;
}
// There should always be metadata for the entrypoint.
const metadata = metadataByEntry.get(entrypoint.name);
const page = (metadata == null ? void 0 : (_metadata_edgeMiddleware = metadata.edgeMiddleware) == null ? void 0 : _metadata_edgeMiddleware.page) || (metadata == null ? void 0 : (_metadata_edgeSSR = metadata.edgeSSR) == null ? void 0 : _metadata_edgeSSR.page) || (metadata == null ? void 0 : (_metadata_edgeApiFunction = metadata.edgeApiFunction) == null ? void 0 : _metadata_edgeApiFunction.page);
if (!page) {
continue;
}
const matcherSource = ((_metadata_edgeSSR1 = metadata.edgeSSR) == null ? void 0 : _metadata_edgeSSR1.isAppDir) ? normalizeAppPath(page) : page;
const catchAll = !metadata.edgeSSR && !metadata.edgeApiFunction;
const { namedRegex } = getNamedMiddlewareRegex(matcherSource, {
catchAll
});
const matchers = (metadata == null ? void 0 : (_metadata_edgeMiddleware1 = metadata.edgeMiddleware) == null ? void 0 : _metadata_edgeMiddleware1.matchers) ?? [
{
regexp: namedRegex,
originalSource: page === "/" && catchAll ? "/:path*" : matcherSource
}
];
const edgeFunctionDefinition = {
files: getEntryFiles(entrypoint.getFiles(), metadata, opts),
name: entrypoint.name,
page: page,
matchers,
wasm: Array.from(metadata.wasmBindings, ([name, filePath])=>({
name,
filePath
})),
assets: Array.from(metadata.assetBindings, ([name, filePath])=>({
name,
filePath
})),
...metadata.regions && {
regions: metadata.regions
}
};
if (metadata.edgeApiFunction || metadata.edgeSSR) {
middlewareManifest.functions[page] = edgeFunctionDefinition;
} else {
middlewareManifest.middleware[page] = edgeFunctionDefinition;
}
}
middlewareManifest.sortedMiddleware = getSortedRoutes(Object.keys(middlewareManifest.middleware));
assets[MIDDLEWARE_MANIFEST] = new sources.RawSource(JSON.stringify(middlewareManifest, null, 2));
};
}
function buildWebpackError({ message, loc, compilation, entryModule, parser }) {
const error = new compilation.compiler.webpack.WebpackError(message);
error.name = NAME;
const module = entryModule ?? (parser == null ? void 0 : parser.state.current);
if (module) {
error.module = module;
}
error.loc = loc;
return error;
}
function isInMiddlewareLayer(parser) {
var _parser_state_module;
return ((_parser_state_module = parser.state.module) == null ? void 0 : _parser_state_module.layer) === "middleware";
}
function isNodeJsModule(moduleName) {
return require("module").builtinModules.includes(moduleName);
}
function isDynamicCodeEvaluationAllowed(fileName, middlewareConfig, rootDir) {
// Some packages are known to use `eval` but are safe to use in the Edge
// Runtime because the dynamic code will never be executed.
if (KNOWN_SAFE_DYNAMIC_PACKAGES.some((pkg)=>fileName.includes(`/node_modules/${pkg}/`.replace(/\//g, path.sep)))) {
return true;
}
const name = fileName.replace(rootDir ?? "", "");
return isMatch(name, (middlewareConfig == null ? void 0 : middlewareConfig.unstable_allowDynamicGlobs) ?? []);
}
function buildUnsupportedApiError({ apiName, loc, ...rest }) {
return buildWebpackError({
message: `A Node.js API is used (${apiName} at line: ${loc.start.line}) which is not supported in the Edge Runtime.
Learn more: https://nextjs.org/docs/api-reference/edge-runtime`,
loc,
...rest
});
}
function registerUnsupportedApiHooks(parser, compilation) {
for (const expression of EDGE_UNSUPPORTED_NODE_APIS){
const warnForUnsupportedApi = (node)=>{
if (!isInMiddlewareLayer(parser)) {
return;
}
compilation.warnings.push(buildUnsupportedApiError({
compilation,
parser,
apiName: expression,
...node
}));
return true;
};
parser.hooks.call.for(expression).tap(NAME, warnForUnsupportedApi);
parser.hooks.expression.for(expression).tap(NAME, warnForUnsupportedApi);
parser.hooks.callMemberChain.for(expression).tap(NAME, warnForUnsupportedApi);
parser.hooks.expressionMemberChain.for(expression).tap(NAME, warnForUnsupportedApi);
}
const warnForUnsupportedProcessApi = (node, [callee])=>{
if (!isInMiddlewareLayer(parser) || callee === "env") {
return;
}
compilation.warnings.push(buildUnsupportedApiError({
compilation,
parser,
apiName: `process.${callee}`,
...node
}));
return true;
};
parser.hooks.callMemberChain.for("process").tap(NAME, warnForUnsupportedProcessApi);
parser.hooks.expressionMemberChain.for("process").tap(NAME, warnForUnsupportedProcessApi);
}
function getCodeAnalyzer(params) {
return (parser)=>{
const { dev, compiler: { webpack: wp }, compilation } = params;
const { hooks } = parser;
/**
* For an expression this will check the graph to ensure it is being used
* by exports. Then it will store in the module buildInfo a boolean to
* express that it contains dynamic code and, if it is available, the
* module path that is using it.
*/ const handleExpression = ()=>{
if (!isInMiddlewareLayer(parser)) {
return;
}
wp.optimize.InnerGraph.onUsage(parser.state, (used = true)=>{
const buildInfo = getModuleBuildInfo(parser.state.module);
if (buildInfo.usingIndirectEval === true || used === false) {
return;
}
if (!buildInfo.usingIndirectEval || used === true) {
buildInfo.usingIndirectEval = used;
return;
}
buildInfo.usingIndirectEval = new Set([
...Array.from(buildInfo.usingIndirectEval),
...Array.from(used)
]);
});
};
/**
* This expression handler allows to wrap a dynamic code expression with a
* function call where we can warn about dynamic code not being allowed
* but actually execute the expression.
*/ const handleWrapExpression = (expr)=>{
if (!isInMiddlewareLayer(parser)) {
return;
}
const { ConstDependency } = wp.dependencies;
const dep1 = new ConstDependency("__next_eval__(function() { return ", expr.range[0]);
dep1.loc = expr.loc;
parser.state.module.addPresentationalDependency(dep1);
const dep2 = new ConstDependency("})", expr.range[1]);
dep2.loc = expr.loc;
parser.state.module.addPresentationalDependency(dep2);
handleExpression();
return true;
};
/**
* This expression handler allows to wrap a WebAssembly.compile invocation with a
* function call where we can warn about WASM code generation not being allowed
* but actually execute the expression.
*/ const handleWrapWasmCompileExpression = (expr)=>{
if (!isInMiddlewareLayer(parser)) {
return;
}
const { ConstDependency } = wp.dependencies;
const dep1 = new ConstDependency("__next_webassembly_compile__(function() { return ", expr.range[0]);
dep1.loc = expr.loc;
parser.state.module.addPresentationalDependency(dep1);
const dep2 = new ConstDependency("})", expr.range[1]);
dep2.loc = expr.loc;
parser.state.module.addPresentationalDependency(dep2);
handleExpression();
};
/**
* This expression handler allows to wrap a WebAssembly.instatiate invocation with a
* function call where we can warn about WASM code generation not being allowed
* but actually execute the expression.
*
* Note that we don't update `usingIndirectEval`, i.e. we don't abort a production build
* since we can't determine statically if the first parameter is a module (legit use) or
* a buffer (dynamic code generation).
*/ const handleWrapWasmInstantiateExpression = (expr)=>{
if (!isInMiddlewareLayer(parser)) {
return;
}
if (dev) {
const { ConstDependency } = wp.dependencies;
const dep1 = new ConstDependency("__next_webassembly_instantiate__(function() { return ", expr.range[0]);
dep1.loc = expr.loc;
parser.state.module.addPresentationalDependency(dep1);
const dep2 = new ConstDependency("})", expr.range[1]);
dep2.loc = expr.loc;
parser.state.module.addPresentationalDependency(dep2);
}
};
/**
* Handler to store original source location of static and dynamic imports into module's buildInfo.
*/ const handleImport = (node)=>{
var _node_source;
if (isInMiddlewareLayer(parser) && ((_node_source = node.source) == null ? void 0 : _node_source.value) && (node == null ? void 0 : node.loc)) {
var _node_source_value;
const { module, source } = parser.state;
const buildInfo = getModuleBuildInfo(module);
if (!buildInfo.importLocByPath) {
buildInfo.importLocByPath = new Map();
}
const importedModule = (_node_source_value = node.source.value) == null ? void 0 : _node_source_value.toString();
buildInfo.importLocByPath.set(importedModule, {
sourcePosition: {
...node.loc.start,
source: module.identifier()
},
sourceContent: source.toString()
});
if (!dev && isNodeJsModule(importedModule)) {
compilation.warnings.push(buildWebpackError({
message: `A Node.js module is loaded ('${importedModule}' at line ${node.loc.start.line}) which is not supported in the Edge Runtime.
Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime`,
compilation,
parser,
...node
}));
}
}
};
/**
* A noop handler to skip analyzing some cases.
* Order matters: for it to work, it must be registered first
*/ const skip = ()=>isInMiddlewareLayer(parser) ? true : undefined;
for (const prefix of [
"",
"global."
]){
hooks.expression.for(`${prefix}Function.prototype`).tap(NAME, skip);
hooks.expression.for(`${prefix}Function.bind`).tap(NAME, skip);
hooks.call.for(`${prefix}eval`).tap(NAME, handleWrapExpression);
hooks.call.for(`${prefix}Function`).tap(NAME, handleWrapExpression);
hooks.new.for(`${prefix}Function`).tap(NAME, handleWrapExpression);
hooks.call.for(`${prefix}WebAssembly.compile`).tap(NAME, handleWrapWasmCompileExpression);
hooks.call.for(`${prefix}WebAssembly.instantiate`).tap(NAME, handleWrapWasmInstantiateExpression);
}
hooks.importCall.tap(NAME, handleImport);
hooks.import.tap(NAME, handleImport);
if (!dev) {
// do not issue compilation warning on dev: invoking code will provide details
registerUnsupportedApiHooks(parser, compilation);
}
};
}
function getExtractMetadata(params) {
const { dev, compilation, metadataByEntry, compiler } = params;
const { webpack: wp } = compiler;
return async ()=>{
metadataByEntry.clear();
const telemetry = traceGlobals.get("telemetry");
for (const [entryName, entry] of compilation.entries){
var _entry_dependencies, _route_middlewareConfig;
if (entry.options.runtime !== EDGE_RUNTIME_WEBPACK) {
continue;
}
const entryDependency = (_entry_dependencies = entry.dependencies) == null ? void 0 : _entry_dependencies[0];
const { rootDir, route } = getModuleBuildInfo(compilation.moduleGraph.getResolvedModule(entryDependency));
const { moduleGraph } = compilation;
const modules = new Set();
const addEntriesFromDependency = (dependency)=>{
const module = moduleGraph.getModule(dependency);
if (module) {
modules.add(module);
}
};
entry.dependencies.forEach(addEntriesFromDependency);
entry.includeDependencies.forEach(addEntriesFromDependency);
const entryMetadata = {
wasmBindings: new Map(),
assetBindings: new Map()
};
if (route == null ? void 0 : (_route_middlewareConfig = route.middlewareConfig) == null ? void 0 : _route_middlewareConfig.regions) {
entryMetadata.regions = route.middlewareConfig.regions;
}
if (route == null ? void 0 : route.preferredRegion) {
const preferredRegion = route.preferredRegion;
entryMetadata.regions = // Ensures preferredRegion is always an array in the manifest.
typeof preferredRegion === "string" ? [
preferredRegion
] : preferredRegion;
}
let ogImageGenerationCount = 0;
for (const module of modules){
const buildInfo = getModuleBuildInfo(module);
/**
* Check if it uses the image generation feature.
*/ if (!dev) {
const resource = module.resource;
const hasOGImageGeneration = resource && /[\\/]node_modules[\\/]@vercel[\\/]og[\\/]dist[\\/]index\.(edge|node)\.js$|[\\/]next[\\/]dist[\\/](esm[\\/])?server[\\/]web[\\/]spec-extension[\\/]image-response\.js$/.test(resource);
if (hasOGImageGeneration) {
ogImageGenerationCount++;
}
}
/**
* When building for production checks if the module is using `eval`
* and in such case produces a compilation error. The module has to
* be in use.
*/ if (!dev && buildInfo.usingIndirectEval && isUsingIndirectEvalAndUsedByExports({
module,
moduleGraph,
runtime: wp.util.runtime.getEntryRuntime(compilation, entryName),
usingIndirectEval: buildInfo.usingIndirectEval,
wp
})) {
var _route_middlewareConfig1;
const id = module.identifier();
if (/node_modules[\\/]regenerator-runtime[\\/]runtime\.js/.test(id)) {
continue;
}
if (route == null ? void 0 : (_route_middlewareConfig1 = route.middlewareConfig) == null ? void 0 : _route_middlewareConfig1.unstable_allowDynamicGlobs) {
telemetry == null ? void 0 : telemetry.record({
eventName: "NEXT_EDGE_ALLOW_DYNAMIC_USED",
payload: {
file: route == null ? void 0 : route.absolutePagePath.replace(rootDir ?? "", ""),
config: route == null ? void 0 : route.middlewareConfig,
fileWithDynamicCode: module.userRequest.replace(rootDir ?? "", "")
}
});
}
if (!isDynamicCodeEvaluationAllowed(module.userRequest, route == null ? void 0 : route.middlewareConfig, rootDir)) {
compilation.errors.push(buildWebpackError({
message: `Dynamic Code Evaluation (e. g. 'eval', 'new Function', 'WebAssembly.compile') not allowed in Edge Runtime ${typeof buildInfo.usingIndirectEval !== "boolean" ? `\nUsed by ${Array.from(buildInfo.usingIndirectEval).join(", ")}` : ""}\nLearn More: https://nextjs.org/docs/messages/edge-dynamic-code-evaluation`,
entryModule: module,
compilation
}));
}
}
/**
* The entry module has to be either a page or a middleware and hold
* the corresponding metadata.
*/ if (buildInfo == null ? void 0 : buildInfo.nextEdgeSSR) {
entryMetadata.edgeSSR = buildInfo.nextEdgeSSR;
} else if (buildInfo == null ? void 0 : buildInfo.nextEdgeMiddleware) {
entryMetadata.edgeMiddleware = buildInfo.nextEdgeMiddleware;
} else if (buildInfo == null ? void 0 : buildInfo.nextEdgeApiFunction) {
entryMetadata.edgeApiFunction = buildInfo.nextEdgeApiFunction;
}
/**
* If the module is a WASM module we read the binding information and
* append it to the entry wasm bindings.
*/ if (buildInfo == null ? void 0 : buildInfo.nextWasmMiddlewareBinding) {
entryMetadata.wasmBindings.set(buildInfo.nextWasmMiddlewareBinding.name, buildInfo.nextWasmMiddlewareBinding.filePath);
}
if (buildInfo == null ? void 0 : buildInfo.nextAssetMiddlewareBinding) {
entryMetadata.assetBindings.set(buildInfo.nextAssetMiddlewareBinding.name, buildInfo.nextAssetMiddlewareBinding.filePath);
}
/**
* Append to the list of modules to process outgoingConnections from
* the module that is being processed.
*/ for (const conn of moduleGraph.getOutgoingConnections(module)){
if (conn.module) {
modules.add(conn.module);
}
}
}
telemetry == null ? void 0 : telemetry.record({
eventName: EVENT_BUILD_FEATURE_USAGE,
payload: {
featureName: "vercelImageGeneration",
invocationCount: ogImageGenerationCount
}
});
metadataByEntry.set(entryName, entryMetadata);
}
};
}
export default class MiddlewarePlugin {
constructor({ dev, sriEnabled }){
this.dev = dev;
this.sriEnabled = sriEnabled;
}
apply(compiler) {
compiler.hooks.compilation.tap(NAME, (compilation, params)=>{
const { hooks } = params.normalModuleFactory;
/**
* This is the static code analysis phase.
*/ const codeAnalyzer = getCodeAnalyzer({
dev: this.dev,
compiler,
compilation
});
hooks.parser.for("javascript/auto").tap(NAME, codeAnalyzer);
hooks.parser.for("javascript/dynamic").tap(NAME, codeAnalyzer);
hooks.parser.for("javascript/esm").tap(NAME, codeAnalyzer);
/**
* Extract all metadata for the entry points in a Map object.
*/ const metadataByEntry = new Map();
compilation.hooks.finishModules.tapPromise(NAME, getExtractMetadata({
compilation,
compiler,
dev: this.dev,
metadataByEntry
}));
/**
* Emit the middleware manifest.
*/ compilation.hooks.processAssets.tap({
name: "NextJsMiddlewareManifest",
stage: webpack.Compilation.PROCESS_ASSETS_STAGE_ADDITIONS
}, getCreateAssets({
compilation,
metadataByEntry,
opts: {
sriEnabled: this.sriEnabled
}
}));
});
}
}
export const SUPPORTED_NATIVE_MODULES = [
"buffer",
"events",
"assert",
"util",
"async_hooks"
];
const supportedEdgePolyfills = new Set(SUPPORTED_NATIVE_MODULES);
export function getEdgePolyfilledModules() {
const records = {};
for (const mod of SUPPORTED_NATIVE_MODULES){
records[mod] = `commonjs node:${mod}`;
records[`node:${mod}`] = `commonjs node:${mod}`;
}
return records;
}
export async function handleWebpackExternalForEdgeRuntime({ request, context, contextInfo, getResolve }) {
if (contextInfo.issuerLayer === "middleware" && isNodeJsModule(request) && !supportedEdgePolyfills.has(request)) {
// allows user to provide and use their polyfills, as we do with buffer.
try {
await getResolve()(context, request);
} catch {
return `root globalThis.__import_unsupported('${request}')`;
}
}
}
//# sourceMappingURL=middleware-plugin.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,10 @@
// @ts-ignore: TODO: remove when webpack 5 is stable
import MiniCssExtractPlugin from "next/dist/compiled/mini-css-extract-plugin";
export default class NextMiniCssExtractPlugin extends MiniCssExtractPlugin {
constructor(...args){
super(...args);
this.__next_css_remove = true;
}
}
//# sourceMappingURL=mini-css-extract-plugin.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../src/build/webpack/plugins/mini-css-extract-plugin.ts"],"names":["MiniCssExtractPlugin","NextMiniCssExtractPlugin","__next_css_remove"],"mappings":"AAAA,oDAAoD;AACpD,OAAOA,0BAA0B,6CAA4C;AAE7E,eAAe,MAAMC,iCAAiCD;;;aACpDE,oBAAoB;;AACtB"}

View File

@@ -0,0 +1,64 @@
import { STRING_LITERAL_DROP_BUNDLE } from "../../../shared/lib/constants";
export const ampFirstEntryNamesMap = new WeakMap();
const PLUGIN_NAME = "DropAmpFirstPagesPlugin";
// Prevents outputting client pages when they are not needed
export class DropClientPage {
apply(compiler) {
compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation, { normalModuleFactory })=>{
// Recursively look up the issuer till it ends up at the root
function findEntryModule(mod) {
const queue = new Set([
mod
]);
for (const module of queue){
const incomingConnections = compilation.moduleGraph.getIncomingConnections(module);
for (const incomingConnection of incomingConnections){
if (!incomingConnection.originModule) return module;
queue.add(incomingConnection.originModule);
}
}
return null;
}
function handler(parser) {
function markAsAmpFirst() {
const entryModule = findEntryModule(parser.state.module);
if (!entryModule) {
return;
}
// @ts-ignore buildInfo exists on Module
entryModule.buildInfo.NEXT_ampFirst = true;
}
parser.hooks.preDeclarator.tap(PLUGIN_NAME, (declarator)=>{
var _declarator_id;
if ((declarator == null ? void 0 : (_declarator_id = declarator.id) == null ? void 0 : _declarator_id.name) === STRING_LITERAL_DROP_BUNDLE) {
markAsAmpFirst();
}
});
}
normalModuleFactory.hooks.parser.for("javascript/auto").tap(PLUGIN_NAME, handler);
normalModuleFactory.hooks.parser.for("javascript/esm").tap(PLUGIN_NAME, handler);
normalModuleFactory.hooks.parser.for("javascript/dynamic").tap(PLUGIN_NAME, handler);
if (!ampFirstEntryNamesMap.has(compilation)) {
ampFirstEntryNamesMap.set(compilation, []);
}
const ampFirstEntryNamesItem = ampFirstEntryNamesMap.get(compilation);
compilation.hooks.seal.tap(PLUGIN_NAME, ()=>{
for (const [name, entryData] of compilation.entries){
for (const dependency of entryData.dependencies){
var _module_buildInfo;
const module = compilation.moduleGraph.getModule(dependency);
if (module == null ? void 0 : (_module_buildInfo = module.buildInfo) == null ? void 0 : _module_buildInfo.NEXT_ampFirst) {
ampFirstEntryNamesItem.push(name);
compilation.entries.delete(name);
}
}
}
});
});
}
constructor(){
this.ampPages = new Set();
}
}
//# sourceMappingURL=next-drop-client-page-plugin.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../src/build/webpack/plugins/next-drop-client-page-plugin.ts"],"names":["STRING_LITERAL_DROP_BUNDLE","ampFirstEntryNamesMap","WeakMap","PLUGIN_NAME","DropClientPage","apply","compiler","hooks","compilation","tap","normalModuleFactory","findEntryModule","mod","queue","Set","module","incomingConnections","moduleGraph","getIncomingConnections","incomingConnection","originModule","add","handler","parser","markAsAmpFirst","entryModule","state","buildInfo","NEXT_ampFirst","preDeclarator","declarator","id","name","for","has","set","ampFirstEntryNamesItem","get","seal","entryData","entries","dependency","dependencies","getModule","push","delete","ampPages"],"mappings":"AACA,SAASA,0BAA0B,QAAQ,gCAA+B;AAE1E,OAAO,MAAMC,wBACX,IAAIC,UAAS;AAEf,MAAMC,cAAc;AAEpB,4DAA4D;AAC5D,OAAO,MAAMC;IAGXC,MAAMC,QAA0B,EAAE;QAChCA,SAASC,KAAK,CAACC,WAAW,CAACC,GAAG,CAC5BN,aACA,CAACK,aAAkB,EAAEE,mBAAmB,EAAO;YAC7C,6DAA6D;YAC7D,SAASC,gBAAgBC,GAAQ;gBAC/B,MAAMC,QAAQ,IAAIC,IAAI;oBAACF;iBAAI;gBAC3B,KAAK,MAAMG,UAAUF,MAAO;oBAC1B,MAAMG,sBACJR,YAAYS,WAAW,CAACC,sBAAsB,CAACH;oBAEjD,KAAK,MAAMI,sBAAsBH,oBAAqB;wBACpD,IAAI,CAACG,mBAAmBC,YAAY,EAAE,OAAOL;wBAC7CF,MAAMQ,GAAG,CAACF,mBAAmBC,YAAY;oBAC3C;gBACF;gBAEA,OAAO;YACT;YAEA,SAASE,QAAQC,MAAW;gBAC1B,SAASC;oBACP,MAAMC,cAAcd,gBAAgBY,OAAOG,KAAK,CAACX,MAAM;oBAEvD,IAAI,CAACU,aAAa;wBAChB;oBACF;oBAEA,wCAAwC;oBACxCA,YAAYE,SAAS,CAACC,aAAa,GAAG;gBACxC;gBAEAL,OAAOhB,KAAK,CAACsB,aAAa,CAACpB,GAAG,CAACN,aAAa,CAAC2B;wBACvCA;oBAAJ,IAAIA,CAAAA,+BAAAA,iBAAAA,WAAYC,EAAE,qBAAdD,eAAgBE,IAAI,MAAKhC,4BAA4B;wBACvDwB;oBACF;gBACF;YACF;YAEAd,oBAAoBH,KAAK,CAACgB,MAAM,CAC7BU,GAAG,CAAC,mBACJxB,GAAG,CAACN,aAAamB;YAEpBZ,oBAAoBH,KAAK,CAACgB,MAAM,CAC7BU,GAAG,CAAC,kBACJxB,GAAG,CAACN,aAAamB;YAEpBZ,oBAAoBH,KAAK,CAACgB,MAAM,CAC7BU,GAAG,CAAC,sBACJxB,GAAG,CAACN,aAAamB;YAEpB,IAAI,CAACrB,sBAAsBiC,GAAG,CAAC1B,cAAc;gBAC3CP,sBAAsBkC,GAAG,CAAC3B,aAAa,EAAE;YAC3C;YAEA,MAAM4B,yBAAyBnC,sBAAsBoC,GAAG,CACtD7B;YAGFA,YAAYD,KAAK,CAAC+B,IAAI,CAAC7B,GAAG,CAACN,aAAa;gBACtC,KAAK,MAAM,CAAC6B,MAAMO,UAAU,IAAI/B,YAAYgC,OAAO,CAAE;oBACnD,KAAK,MAAMC,cAAcF,UAAUG,YAAY,CAAE;4BAE3C3B;wBADJ,MAAMA,SAASP,YAAYS,WAAW,CAAC0B,SAAS,CAACF;wBACjD,IAAI1B,2BAAAA,oBAAAA,OAAQY,SAAS,qBAAjBZ,kBAAmBa,aAAa,EAAE;4BACpCQ,uBAAuBQ,IAAI,CAACZ;4BAC5BxB,YAAYgC,OAAO,CAACK,MAAM,CAACb;wBAC7B;oBACF;gBACF;YACF;QACF;IAEJ;;aA1EAc,WAAW,IAAIhC;;AA2EjB"}

View File

@@ -0,0 +1,118 @@
import { webpack, sources } from "next/dist/compiled/webpack/webpack";
import getRouteFromEntrypoint from "../../../server/get-route-from-entrypoint";
import { NEXT_FONT_MANIFEST } from "../../../shared/lib/constants";
import { traverseModules } from "../utils";
import path from "path";
const PLUGIN_NAME = "NextFontManifestPlugin";
/**
* When calling font functions with next/font, you can specify if you'd like the font to be preloaded (true by default).
* e.g.: const inter = Inter({ subsets: ['latin'], preload: true })
*
* In that case, next-font-loader will emit the font file as [name].p.[ext] instead of [name].[ext]
* This function returns those files from an array that can include both preloaded and non-preloaded files.
*/ function getPreloadedFontFiles(fontFiles) {
return fontFiles.filter((file)=>/\.p\.(woff|woff2|eot|ttf|otf)$/.test(file));
}
/**
* Similarly to getPreloadedFontFiles, but returns true if some of the files includes -s in the name.
* This means that a font is using size adjust in its fallback font.
* This was added to enable adding data-size-adjust="true" to the dom, used by the Google Aurora team to collect statistics.
*/ function getPageIsUsingSizeAdjust(fontFiles) {
return fontFiles.some((file)=>file.includes("-s"));
}
/**
* The NextFontManifestPlugin collects all font files emitted by next-font-loader and creates a manifest file.
* The manifest file is used in the Next.js render functions (_document.tsx for pages/ and app-render for app/) to add preload tags for the font files.
* We only want to att preload fonts that are used by the current route.
*
* For pages/ the plugin finds the fonts imported in the entrypoint chunks and creates a map:
* { [route]: fontFile[] }
* When rendering the app in _document.tsx, it gets the font files to preload: manifest.pages[currentRouteBeingRendered].
*
* For app/, the manifest is a bit different.
* Instead of creating a map of route to font files, it creates a map of the webpack module request to font files.
* { [webpackModuleRequest]: fontFile[]]}
* When creating the component tree in app-render it looks for font files to preload: manifest.app[moduleBeingRendered]
*/ export class NextFontManifestPlugin {
constructor(options){
this.appDir = options.appDir;
}
apply(compiler) {
compiler.hooks.make.tap(PLUGIN_NAME, (compilation)=>{
// In this stage the font files are emitted and we can collect all files emitted by each chunkGroup (entry).
compilation.hooks.processAssets.tap({
name: PLUGIN_NAME,
stage: webpack.Compilation.PROCESS_ASSETS_STAGE_ADDITIONS
}, (assets)=>{
const nextFontManifest = {
pages: {},
app: {},
appUsingSizeAdjust: false,
pagesUsingSizeAdjust: false
};
if (this.appDir) {
const appDirBase = path.dirname(this.appDir) + path.sep;
// After all modules are created, we collect the modules that was created by next-font-loader.
traverseModules(compilation, (mod, _chunk, chunkGroup)=>{
var _mod_request;
if (mod == null ? void 0 : (_mod_request = mod.request) == null ? void 0 : _mod_request.includes("/next-font-loader/index.js?")) {
var _mod_buildInfo;
if (!((_mod_buildInfo = mod.buildInfo) == null ? void 0 : _mod_buildInfo.assets)) return;
const chunkEntryName = (appDirBase + chunkGroup.name).replace(/[\\/]/g, path.sep);
const modAssets = Object.keys(mod.buildInfo.assets);
const fontFiles = modAssets.filter((file)=>/\.(woff|woff2|eot|ttf|otf)$/.test(file));
// Look if size-adjust fallback font is being used
if (!nextFontManifest.appUsingSizeAdjust) {
nextFontManifest.appUsingSizeAdjust = getPageIsUsingSizeAdjust(fontFiles);
}
const preloadedFontFiles = getPreloadedFontFiles(fontFiles);
// Add an entry of the module's font files in the manifest.
// We'll add an entry even if no files should preload.
// When an entry is present but empty, instead of preloading the font files, a preconnect tag is added.
if (fontFiles.length > 0) {
if (!nextFontManifest.app[chunkEntryName]) {
nextFontManifest.app[chunkEntryName] = [];
}
nextFontManifest.app[chunkEntryName].push(...preloadedFontFiles);
}
}
}, (chunkGroup)=>{
var _chunkGroup_name;
// Only loop through entrypoints that are under app/.
return !!((_chunkGroup_name = chunkGroup.name) == null ? void 0 : _chunkGroup_name.startsWith("app/"));
});
}
// Look at all the entrypoints created for pages/.
for (const entrypoint of compilation.entrypoints.values()){
const pagePath = getRouteFromEntrypoint(entrypoint.name);
if (!pagePath) {
continue;
}
// Get font files from the chunks included in the entrypoint.
const fontFiles = entrypoint.chunks.flatMap((chunk)=>[
...chunk.auxiliaryFiles
]).filter((file)=>/\.(woff|woff2|eot|ttf|otf)$/.test(file));
// Look if size-adjust fallback font is being used
if (!nextFontManifest.pagesUsingSizeAdjust) {
nextFontManifest.pagesUsingSizeAdjust = getPageIsUsingSizeAdjust(fontFiles);
}
const preloadedFontFiles = getPreloadedFontFiles(fontFiles);
// Add an entry of the route's font files in the manifest.
// We'll add an entry even if no files should preload.
// When an entry is present but empty, instead of preloading the font files, a preconnect tag is added.
if (fontFiles.length > 0) {
nextFontManifest.pages[pagePath] = preloadedFontFiles;
}
}
const manifest = JSON.stringify(nextFontManifest, null);
// Create manifest for edge
assets[`server/${NEXT_FONT_MANIFEST}.js`] = new sources.RawSource(`self.__NEXT_FONT_MANIFEST=${JSON.stringify(manifest)}`);
// Create manifest for server
assets[`server/${NEXT_FONT_MANIFEST}.json`] = new sources.RawSource(manifest);
});
});
return;
}
}
//# sourceMappingURL=next-font-manifest-plugin.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../src/build/webpack/plugins/next-font-manifest-plugin.ts"],"names":["webpack","sources","getRouteFromEntrypoint","NEXT_FONT_MANIFEST","traverseModules","path","PLUGIN_NAME","getPreloadedFontFiles","fontFiles","filter","file","test","getPageIsUsingSizeAdjust","some","includes","NextFontManifestPlugin","constructor","options","appDir","apply","compiler","hooks","make","tap","compilation","processAssets","name","stage","Compilation","PROCESS_ASSETS_STAGE_ADDITIONS","assets","nextFontManifest","pages","app","appUsingSizeAdjust","pagesUsingSizeAdjust","appDirBase","dirname","sep","mod","_chunk","chunkGroup","request","buildInfo","chunkEntryName","replace","modAssets","Object","keys","preloadedFontFiles","length","push","startsWith","entrypoint","entrypoints","values","pagePath","chunks","flatMap","chunk","auxiliaryFiles","manifest","JSON","stringify","RawSource"],"mappings":"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"}

View File

@@ -0,0 +1,560 @@
import nodePath from "path";
import { spans } from "./profiling-plugin";
import isError from "../../../lib/is-error";
import { nodeFileTrace } from "next/dist/compiled/@vercel/nft";
import { CLIENT_REFERENCE_MANIFEST, TRACE_OUTPUT_VERSION } from "../../../shared/lib/constants";
import { webpack, sources } from "next/dist/compiled/webpack/webpack";
import { NODE_ESM_RESOLVE_OPTIONS, NODE_RESOLVE_OPTIONS, resolveExternal } from "../../webpack-config";
import { loadBindings } from "../../swc";
import { isMatch } from "next/dist/compiled/micromatch";
import { getModuleBuildInfo } from "../loaders/get-module-build-info";
import { getPageFilePath } from "../../entries";
const PLUGIN_NAME = "TraceEntryPointsPlugin";
const TRACE_IGNORES = [
"**/*/next/dist/server/next.js",
"**/*/next/dist/bin/next"
];
const NOT_TRACEABLE = [
".wasm",
".png",
".jpg",
".jpeg",
".gif",
".webp",
".avif",
".ico",
".bmp",
".svg"
];
function getModuleFromDependency(compilation, dep) {
return compilation.moduleGraph.getModule(dep);
}
function getFilesMapFromReasons(fileList, reasons, ignoreFn) {
// this uses the reasons tree to collect files specific to a
// certain parent allowing us to not have to trace each parent
// separately
const parentFilesMap = new Map();
function propagateToParents(parents, file, seen = new Set()) {
for (const parent of parents || []){
if (!seen.has(parent)) {
seen.add(parent);
let parentFiles = parentFilesMap.get(parent);
if (!parentFiles) {
parentFiles = new Set();
parentFilesMap.set(parent, parentFiles);
}
if (!(ignoreFn == null ? void 0 : ignoreFn(file, parent))) {
parentFiles.add(file);
}
const parentReason = reasons.get(parent);
if (parentReason == null ? void 0 : parentReason.parents) {
propagateToParents(parentReason.parents, file, seen);
}
}
}
}
for (const file of fileList){
const reason = reasons.get(file);
const isInitial = (reason == null ? void 0 : reason.type.length) === 1 && reason.type.includes("initial");
if (!reason || !reason.parents || isInitial && reason.parents.size === 0) {
continue;
}
propagateToParents(reason.parents, file);
}
return parentFilesMap;
}
export class TraceEntryPointsPlugin {
constructor({ rootDir, appDir, pagesDir, appDirEnabled, traceIgnores, esmExternals, outputFileTracingRoot, turbotrace }){
this.turbotraceContext = {};
this.chunksToTrace = [];
this.rootDir = rootDir;
this.appDir = appDir;
this.pagesDir = pagesDir;
this.entryTraces = new Map();
this.esmExternals = esmExternals;
this.appDirEnabled = appDirEnabled;
this.traceIgnores = traceIgnores || [];
this.tracingRoot = outputFileTracingRoot || rootDir;
this.turbotrace = turbotrace;
}
// Here we output all traced assets and webpack chunks to a
// ${page}.js.nft.json file
async createTraceAssets(compilation, assets, span, readlink, stat) {
const outputPath = compilation.outputOptions.path;
await span.traceChild("create-trace-assets").traceAsyncFn(async ()=>{
const entryFilesMap = new Map();
const chunksToTrace = new Set();
const isTraceable = (file)=>!NOT_TRACEABLE.some((suffix)=>{
return file.endsWith(suffix);
});
for (const entrypoint of compilation.entrypoints.values()){
const entryFiles = new Set();
for (const chunk of entrypoint.getEntrypointChunk().getAllReferencedChunks()){
for (const file of chunk.files){
if (isTraceable(file)) {
const filePath = nodePath.join(outputPath, file);
chunksToTrace.add(filePath);
entryFiles.add(filePath);
}
}
for (const file of chunk.auxiliaryFiles){
if (isTraceable(file)) {
const filePath = nodePath.join(outputPath, file);
chunksToTrace.add(filePath);
entryFiles.add(filePath);
}
}
}
entryFilesMap.set(entrypoint, entryFiles);
}
// startTrace existed and callable
if (this.turbotrace) {
let binding = await loadBindings();
if (!(binding == null ? void 0 : binding.isWasm) && typeof binding.turbo.startTrace === "function") {
this.chunksToTrace = [
...chunksToTrace
];
return;
}
}
const ignores = [
...TRACE_IGNORES,
...this.traceIgnores
];
const ignoreFn = (path)=>{
return isMatch(path, ignores, {
contains: true,
dot: true
});
};
const result = await nodeFileTrace([
...chunksToTrace
], {
base: this.tracingRoot,
processCwd: this.rootDir,
readFile: async (path)=>{
if (chunksToTrace.has(path)) {
var _assets_nodePath_relative_replace_source, _assets_nodePath_relative_replace;
const source = (_assets_nodePath_relative_replace = assets[nodePath.relative(outputPath, path).replace(/\\/g, "/")]) == null ? void 0 : (_assets_nodePath_relative_replace_source = _assets_nodePath_relative_replace.source) == null ? void 0 : _assets_nodePath_relative_replace_source.call(_assets_nodePath_relative_replace);
if (source) return source;
}
try {
return await new Promise((resolve, reject)=>{
compilation.inputFileSystem.readFile(path, (err, data)=>{
if (err) return reject(err);
resolve(data);
});
});
} catch (e) {
if (isError(e) && (e.code === "ENOENT" || e.code === "EISDIR")) {
return null;
}
throw e;
}
},
readlink,
stat,
ignore: ignoreFn,
mixedModules: true
});
const reasons = result.reasons;
const fileList = result.fileList;
result.esmFileList.forEach((file)=>fileList.add(file));
const parentFilesMap = getFilesMapFromReasons(fileList, reasons);
for (const [entrypoint, entryFiles] of entryFilesMap){
const traceOutputName = `../${entrypoint.name}.js.nft.json`;
const traceOutputPath = nodePath.dirname(nodePath.join(outputPath, traceOutputName));
const allEntryFiles = new Set();
entryFiles.forEach((file)=>{
var _parentFilesMap_get;
(_parentFilesMap_get = parentFilesMap.get(nodePath.relative(this.tracingRoot, file))) == null ? void 0 : _parentFilesMap_get.forEach((child)=>{
allEntryFiles.add(nodePath.join(this.tracingRoot, child));
});
});
// don't include the entry itself in the trace
entryFiles.delete(nodePath.join(outputPath, `../${entrypoint.name}.js`));
if (entrypoint.name.startsWith("app/")) {
// include the client reference manifest
const clientManifestsForPage = entrypoint.name.endsWith("/page") || entrypoint.name === "app/not-found" || entrypoint.name === "app/_not-found" ? nodePath.join(outputPath, "..", entrypoint.name.replace(/%5F/g, "_") + "_" + CLIENT_REFERENCE_MANIFEST + ".js") : null;
if (clientManifestsForPage !== null) {
entryFiles.add(clientManifestsForPage);
}
}
const finalFiles = [];
for (const file of new Set([
...entryFiles,
...allEntryFiles,
...this.entryTraces.get(entrypoint.name) || []
])){
if (file) {
finalFiles.push(nodePath.relative(traceOutputPath, file).replace(/\\/g, "/"));
}
}
assets[traceOutputName] = new sources.RawSource(JSON.stringify({
version: TRACE_OUTPUT_VERSION,
files: finalFiles
}));
}
});
}
tapfinishModules(compilation, traceEntrypointsPluginSpan, doResolve, readlink, stat) {
compilation.hooks.finishModules.tapAsync(PLUGIN_NAME, async (_stats, callback)=>{
const finishModulesSpan = traceEntrypointsPluginSpan.traceChild("finish-modules");
await finishModulesSpan.traceAsyncFn(async ()=>{
// we create entry -> module maps so that we can
// look them up faster instead of having to iterate
// over the compilation modules list
const entryNameMap = new Map();
const entryModMap = new Map();
const additionalEntries = new Map();
const depModMap = new Map();
finishModulesSpan.traceChild("get-entries").traceFn(()=>{
compilation.entries.forEach((entry, name)=>{
const normalizedName = name == null ? void 0 : name.replace(/\\/g, "/");
const isPage = normalizedName.startsWith("pages/");
const isApp = this.appDirEnabled && normalizedName.startsWith("app/");
if (isApp || isPage) {
for (const dep of entry.dependencies){
if (!dep) continue;
const entryMod = getModuleFromDependency(compilation, dep);
// Handle case where entry is a loader coming from Next.js.
// For example edge-loader or app-loader.
if (entryMod && entryMod.resource === "") {
const moduleBuildInfo = getModuleBuildInfo(entryMod);
// All loaders that are used to create entries have a `route` property on the buildInfo.
if (moduleBuildInfo.route) {
const absolutePath = getPageFilePath({
absolutePagePath: moduleBuildInfo.route.absolutePagePath,
rootDir: this.rootDir,
appDir: this.appDir,
pagesDir: this.pagesDir
});
// Ensures we don't handle non-pages.
if (this.pagesDir && absolutePath.startsWith(this.pagesDir) || this.appDir && absolutePath.startsWith(this.appDir)) {
entryModMap.set(absolutePath, entryMod);
entryNameMap.set(absolutePath, name);
}
}
// If there was no `route` property, we can assume that it was something custom instead.
// In order to trace these we add them to the additionalEntries map.
if (entryMod.request) {
let curMap = additionalEntries.get(name);
if (!curMap) {
curMap = new Map();
additionalEntries.set(name, curMap);
}
depModMap.set(entryMod.request, entryMod);
curMap.set(entryMod.resource, entryMod);
}
}
if (entryMod && entryMod.resource) {
entryNameMap.set(entryMod.resource, name);
entryModMap.set(entryMod.resource, entryMod);
let curMap = additionalEntries.get(name);
if (!curMap) {
curMap = new Map();
additionalEntries.set(name, curMap);
}
depModMap.set(entryMod.resource, entryMod);
curMap.set(entryMod.resource, entryMod);
}
}
}
});
});
const readFile = async (path)=>{
var _mod_originalSource;
const mod = depModMap.get(path) || entryModMap.get(path);
// map the transpiled source when available to avoid
// parse errors in node-file-trace
const source = mod == null ? void 0 : (_mod_originalSource = mod.originalSource) == null ? void 0 : _mod_originalSource.call(mod);
if (source) {
return source.buffer();
}
// we don't want to analyze non-transpiled
// files here, that is done against webpack output
return "";
};
const entryPaths = Array.from(entryModMap.keys());
const collectDependencies = (mod)=>{
if (!mod || !mod.dependencies) return;
for (const dep of mod.dependencies){
const depMod = getModuleFromDependency(compilation, dep);
if ((depMod == null ? void 0 : depMod.resource) && !depModMap.get(depMod.resource)) {
depModMap.set(depMod.resource, depMod);
collectDependencies(depMod);
}
}
};
const entriesToTrace = [
...entryPaths
];
entryPaths.forEach((entry)=>{
collectDependencies(entryModMap.get(entry));
const entryName = entryNameMap.get(entry);
const curExtraEntries = additionalEntries.get(entryName);
if (curExtraEntries) {
entriesToTrace.push(...curExtraEntries.keys());
}
});
// startTrace existed and callable
if (this.turbotrace) {
let binding = await loadBindings();
if (!(binding == null ? void 0 : binding.isWasm) && typeof binding.turbo.startTrace === "function") {
var _this_turbotrace, _this_turbotrace1, _this_turbotrace2, _this_turbotrace3;
const contextDirectory = ((_this_turbotrace = this.turbotrace) == null ? void 0 : _this_turbotrace.contextDirectory) ?? this.tracingRoot;
const chunks = [
...entriesToTrace
];
this.turbotraceContext.entriesTrace = {
action: {
action: "print",
input: chunks,
contextDirectory,
processCwd: ((_this_turbotrace1 = this.turbotrace) == null ? void 0 : _this_turbotrace1.processCwd) ?? this.rootDir,
logLevel: (_this_turbotrace2 = this.turbotrace) == null ? void 0 : _this_turbotrace2.logLevel,
showAll: (_this_turbotrace3 = this.turbotrace) == null ? void 0 : _this_turbotrace3.logAll
},
appDir: this.rootDir,
depModArray: Array.from(depModMap.keys()),
entryNameMap,
outputPath: compilation.outputOptions.path
};
return;
}
}
let fileList;
let reasons;
const ignores = [
...TRACE_IGNORES,
...this.traceIgnores,
"**/node_modules/**"
];
const ignoreFn = (path)=>{
return isMatch(path, ignores, {
contains: true,
dot: true
});
};
await finishModulesSpan.traceChild("node-file-trace", {
traceEntryCount: entriesToTrace.length + ""
}).traceAsyncFn(async ()=>{
const result = await nodeFileTrace(entriesToTrace, {
base: this.tracingRoot,
processCwd: this.rootDir,
readFile,
readlink,
stat,
resolve: doResolve ? async (id, parent, job, isCjs)=>{
return doResolve(id, parent, job, !isCjs);
} : undefined,
ignore: ignoreFn,
mixedModules: true
});
// @ts-ignore
fileList = result.fileList;
result.esmFileList.forEach((file)=>fileList.add(file));
reasons = result.reasons;
});
await finishModulesSpan.traceChild("collect-traced-files").traceAsyncFn(()=>{
const parentFilesMap = getFilesMapFromReasons(fileList, reasons, (file)=>{
var _reasons_get;
// if a file was imported and a loader handled it
// we don't include it in the trace e.g.
// static image imports, CSS imports
file = nodePath.join(this.tracingRoot, file);
const depMod = depModMap.get(file);
const isAsset = (_reasons_get = reasons.get(nodePath.relative(this.tracingRoot, file))) == null ? void 0 : _reasons_get.type.includes("asset");
return !isAsset && Array.isArray(depMod == null ? void 0 : depMod.loaders) && depMod.loaders.length > 0;
});
entryPaths.forEach((entry)=>{
var _parentFilesMap_get;
const entryName = entryNameMap.get(entry);
const normalizedEntry = nodePath.relative(this.tracingRoot, entry);
const curExtraEntries = additionalEntries.get(entryName);
const finalDeps = new Set();
(_parentFilesMap_get = parentFilesMap.get(normalizedEntry)) == null ? void 0 : _parentFilesMap_get.forEach((dep)=>{
finalDeps.add(nodePath.join(this.tracingRoot, dep));
});
if (curExtraEntries) {
for (const extraEntry of curExtraEntries.keys()){
var _parentFilesMap_get1;
const normalizedExtraEntry = nodePath.relative(this.tracingRoot, extraEntry);
finalDeps.add(extraEntry);
(_parentFilesMap_get1 = parentFilesMap.get(normalizedExtraEntry)) == null ? void 0 : _parentFilesMap_get1.forEach((dep)=>{
finalDeps.add(nodePath.join(this.tracingRoot, dep));
});
}
}
this.entryTraces.set(entryName, finalDeps);
});
});
}).then(()=>callback(), (err)=>callback(err));
});
}
apply(compiler) {
compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation)=>{
const readlink = async (path)=>{
try {
return await new Promise((resolve, reject)=>{
compilation.inputFileSystem.readlink(path, (err, link)=>{
if (err) return reject(err);
resolve(link);
});
});
} catch (e) {
if (isError(e) && (e.code === "EINVAL" || e.code === "ENOENT" || e.code === "UNKNOWN")) {
return null;
}
throw e;
}
};
const stat = async (path)=>{
try {
return await new Promise((resolve, reject)=>{
compilation.inputFileSystem.stat(path, (err, stats)=>{
if (err) return reject(err);
resolve(stats);
});
});
} catch (e) {
if (isError(e) && (e.code === "ENOENT" || e.code === "ENOTDIR")) {
return null;
}
throw e;
}
};
const compilationSpan = spans.get(compilation) || spans.get(compiler);
const traceEntrypointsPluginSpan = compilationSpan.traceChild("next-trace-entrypoint-plugin");
traceEntrypointsPluginSpan.traceFn(()=>{
compilation.hooks.processAssets.tapAsync({
name: PLUGIN_NAME,
stage: webpack.Compilation.PROCESS_ASSETS_STAGE_SUMMARIZE
}, (assets, callback)=>{
this.createTraceAssets(compilation, assets, traceEntrypointsPluginSpan, readlink, stat).then(()=>callback()).catch((err)=>callback(err));
});
let resolver = compilation.resolverFactory.get("normal");
function getPkgName(name) {
const segments = name.split("/");
if (name[0] === "@" && segments.length > 1) return segments.length > 1 ? segments.slice(0, 2).join("/") : null;
return segments.length ? segments[0] : null;
}
const getResolve = (options)=>{
const curResolver = resolver.withOptions(options);
return (parent, request, job)=>new Promise((resolve, reject)=>{
const context = nodePath.dirname(parent);
curResolver.resolve({}, context, request, {
fileDependencies: compilation.fileDependencies,
missingDependencies: compilation.missingDependencies,
contextDependencies: compilation.contextDependencies
}, async (err, result, resContext)=>{
if (err) return reject(err);
if (!result) {
return reject(new Error("module not found"));
}
// webpack resolver doesn't strip loader query info
// from the result so use path instead
if (result.includes("?") || result.includes("!")) {
result = (resContext == null ? void 0 : resContext.path) || result;
}
try {
// we need to collect all parent package.json's used
// as webpack's resolve doesn't expose this and parent
// package.json could be needed for resolving e.g. stylis
// stylis/package.json -> stylis/dist/umd/package.json
if (result.includes("node_modules")) {
let requestPath = result.replace(/\\/g, "/").replace(/\0/g, "");
if (!nodePath.isAbsolute(request) && request.includes("/") && (resContext == null ? void 0 : resContext.descriptionFileRoot)) {
var _getPkgName;
requestPath = (resContext.descriptionFileRoot + request.slice(((_getPkgName = getPkgName(request)) == null ? void 0 : _getPkgName.length) || 0) + nodePath.sep + "package.json").replace(/\\/g, "/").replace(/\0/g, "");
}
const rootSeparatorIndex = requestPath.indexOf("/");
let separatorIndex;
while((separatorIndex = requestPath.lastIndexOf("/")) > rootSeparatorIndex){
requestPath = requestPath.slice(0, separatorIndex);
const curPackageJsonPath = `${requestPath}/package.json`;
if (await job.isFile(curPackageJsonPath)) {
await job.emitFile(await job.realpath(curPackageJsonPath), "resolve", parent);
}
}
}
} catch (_err) {
// we failed to resolve the package.json boundary,
// we don't block emitting the initial asset from this
}
resolve([
result,
options.dependencyType === "esm"
]);
});
});
};
const CJS_RESOLVE_OPTIONS = {
...NODE_RESOLVE_OPTIONS,
fullySpecified: undefined,
modules: undefined,
extensions: undefined
};
const BASE_CJS_RESOLVE_OPTIONS = {
...CJS_RESOLVE_OPTIONS,
alias: false
};
const ESM_RESOLVE_OPTIONS = {
...NODE_ESM_RESOLVE_OPTIONS,
fullySpecified: undefined,
modules: undefined,
extensions: undefined
};
const BASE_ESM_RESOLVE_OPTIONS = {
...ESM_RESOLVE_OPTIONS,
alias: false
};
const doResolve = async (request, parent, job, isEsmRequested)=>{
const context = nodePath.dirname(parent);
// When in esm externals mode, and using import, we resolve with
// ESM resolving options.
const { res } = await resolveExternal(this.rootDir, this.esmExternals, context, request, isEsmRequested, !!this.appDirEnabled, (options)=>(_, resRequest)=>{
return getResolve(options)(parent, resRequest, job);
}, undefined, undefined, ESM_RESOLVE_OPTIONS, CJS_RESOLVE_OPTIONS, BASE_ESM_RESOLVE_OPTIONS, BASE_CJS_RESOLVE_OPTIONS);
if (!res) {
throw new Error(`failed to resolve ${request} from ${parent}`);
}
return res.replace(/\0/g, "");
};
this.tapfinishModules(compilation, traceEntrypointsPluginSpan, doResolve, readlink, stat);
});
});
if (this.turbotrace) {
compiler.hooks.afterEmit.tapPromise(PLUGIN_NAME, async ()=>{
let binding = await loadBindings();
if (!(binding == null ? void 0 : binding.isWasm) && typeof binding.turbo.startTrace === "function") {
var _this_turbotrace, _this_turbotrace1, _this_turbotrace2, _this_turbotrace3;
const ignores = [
...TRACE_IGNORES,
...this.traceIgnores
];
const ignoreFn = (path)=>{
return isMatch(path, ignores, {
contains: true,
dot: true
});
};
const chunks = this.chunksToTrace.filter((chunk)=>!ignoreFn(chunk));
this.turbotraceContext.chunksTrace = {
action: {
action: "annotate",
input: chunks,
contextDirectory: ((_this_turbotrace = this.turbotrace) == null ? void 0 : _this_turbotrace.contextDirectory) ?? this.tracingRoot,
processCwd: ((_this_turbotrace1 = this.turbotrace) == null ? void 0 : _this_turbotrace1.processCwd) ?? this.rootDir,
showAll: (_this_turbotrace2 = this.turbotrace) == null ? void 0 : _this_turbotrace2.logAll,
logLevel: (_this_turbotrace3 = this.turbotrace) == null ? void 0 : _this_turbotrace3.logLevel
},
outputPath: compiler.outputPath
};
}
});
}
}
}
//# sourceMappingURL=next-trace-entrypoints-plugin.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,528 @@
import fs from "fs/promises";
import { webpack, sources } from "next/dist/compiled/webpack/webpack";
import { parse } from "next/dist/compiled/path-to-regexp";
import path from "path";
import { WEBPACK_LAYERS } from "../../../../lib/constants";
import { denormalizePagePath } from "../../../../shared/lib/page-path/denormalize-page-path";
import { ensureLeadingSlash } from "../../../../shared/lib/page-path/ensure-leading-slash";
import { normalizePathSep } from "../../../../shared/lib/page-path/normalize-path-sep";
import { HTTP_METHODS } from "../../../../server/web/http";
import { isDynamicRoute } from "../../../../shared/lib/router/utils";
import { normalizeAppPath } from "../../../../shared/lib/router/utils/app-paths";
import { getPageFromPath } from "../../../entries";
import { devPageFiles } from "./shared";
const PLUGIN_NAME = "NextTypesPlugin";
function createTypeGuardFile(fullPath, relativePath, options) {
return `// File: ${fullPath}
import * as entry from '${relativePath}.js'
${options.type === "route" ? `import type { NextRequest } from 'next/server.js'` : `import type { ResolvingMetadata } from 'next/dist/lib/metadata/types/metadata-interface.js'`}
type TEntry = typeof import('${relativePath}.js')
// Check that the entry is a valid entry
checkFields<Diff<{
${options.type === "route" ? HTTP_METHODS.map((method)=>`${method}?: Function`).join("\n ") : "default: Function"}
config?: {}
generateStaticParams?: Function
revalidate?: RevalidateRange<TEntry> | false
dynamic?: 'auto' | 'force-dynamic' | 'error' | 'force-static'
dynamicParams?: boolean
fetchCache?: 'auto' | 'force-no-store' | 'only-no-store' | 'default-no-store' | 'default-cache' | 'only-cache' | 'force-cache'
preferredRegion?: 'auto' | 'global' | 'home' | string | string[]
runtime?: 'nodejs' | 'experimental-edge' | 'edge'
maxDuration?: number
${options.type === "route" ? "" : `
metadata?: any
generateMetadata?: Function
`}
}, TEntry, ''>>()
${options.type === "route" ? HTTP_METHODS.map((method)=>`// Check the prop type of the entry function
if ('${method}' in entry) {
checkFields<
Diff<
ParamCheck<Request | NextRequest>,
{
__tag__: '${method}'
__param_position__: 'first'
__param_type__: FirstArg<MaybeField<TEntry, '${method}'>>
},
'${method}'
>
>()
checkFields<
Diff<
ParamCheck<PageParams>,
{
__tag__: '${method}'
__param_position__: 'second'
__param_type__: SecondArg<MaybeField<TEntry, '${method}'>>
},
'${method}'
>
>()
checkFields<
Diff<
{
__tag__: '${method}',
__return_type__: Response | Promise<Response>
},
{
__tag__: '${method}',
__return_type__: ReturnType<MaybeField<TEntry, '${method}'>>
},
'${method}'
>
>()
}
`).join("") : `// Check the prop type of the entry function
checkFields<Diff<${options.type === "page" ? "PageProps" : "LayoutProps"}, FirstArg<TEntry['default']>, 'default'>>()
// Check the arguments and return type of the generateMetadata function
if ('generateMetadata' in entry) {
checkFields<Diff<${options.type === "page" ? "PageProps" : "LayoutProps"}, FirstArg<MaybeField<TEntry, 'generateMetadata'>>, 'generateMetadata'>>()
checkFields<Diff<ResolvingMetadata, SecondArg<MaybeField<TEntry, 'generateMetadata'>>, 'generateMetadata'>>()
}
`}
// Check the arguments and return type of the generateStaticParams function
if ('generateStaticParams' in entry) {
checkFields<Diff<{ params: PageParams }, FirstArg<MaybeField<TEntry, 'generateStaticParams'>>, 'generateStaticParams'>>()
checkFields<Diff<{ __tag__: 'generateStaticParams', __return_type__: any[] | Promise<any[]> }, { __tag__: 'generateStaticParams', __return_type__: ReturnType<MaybeField<TEntry, 'generateStaticParams'>> }>>()
}
type PageParams = any
export interface PageProps {
params?: any
searchParams?: any
}
export interface LayoutProps {
children?: React.ReactNode
${options.slots ? options.slots.map((slot)=>` ${slot}: React.ReactNode`).join("\n") : ""}
params?: any
}
// =============
// Utility types
type RevalidateRange<T> = T extends { revalidate: any } ? NonNegative<T['revalidate']> : never
// If T is unknown or any, it will be an empty {} type. Otherwise, it will be the same as Omit<T, keyof Base>.
type OmitWithTag<T, K extends keyof any, _M> = Omit<T, K>
type Diff<Base, T extends Base, Message extends string = ''> = 0 extends (1 & T) ? {} : OmitWithTag<T, keyof Base, Message>
type FirstArg<T extends Function> = T extends (...args: [infer T, any]) => any ? unknown extends T ? any : T : never
type SecondArg<T extends Function> = T extends (...args: [any, infer T]) => any ? unknown extends T ? any : T : never
type MaybeField<T, K extends string> = T extends { [k in K]: infer G } ? G extends Function ? G : never : never
${options.type === "route" ? `type ParamCheck<T> = {
__tag__: string
__param_position__: string
__param_type__: T
}` : ""}
function checkFields<_ extends { [k in keyof any]: never }>() {}
// https://github.com/sindresorhus/type-fest
type Numeric = number | bigint
type Zero = 0 | 0n
type Negative<T extends Numeric> = T extends Zero ? never : \`\${T}\` extends \`-\${string}\` ? T : never
type NonNegative<T extends Numeric> = T extends Zero ? T : Negative<T> extends never ? T : '__invalid_negative_number__'
`;
}
async function collectNamedSlots(layoutPath) {
const layoutDir = path.dirname(layoutPath);
const items = await fs.readdir(layoutDir, {
withFileTypes: true
});
const slots = [];
for (const item of items){
if (item.isDirectory() && item.name.startsWith("@")) {
slots.push(item.name.slice(1));
}
}
return slots;
}
// By exposing the static route types separately as string literals,
// editors can provide autocompletion for them. However it's currently not
// possible to provide the same experience for dynamic routes.
const routeTypes = {
edge: {
static: "",
dynamic: ""
},
node: {
static: "",
dynamic: ""
},
extra: {
static: "",
dynamic: ""
}
};
function formatRouteToRouteType(route) {
const isDynamic = isDynamicRoute(route);
if (isDynamic) {
route = route.split("/").map((part)=>{
if (part.startsWith("[") && part.endsWith("]")) {
if (part.startsWith("[...")) {
// /[...slug]
return `\${CatchAllSlug<T>}`;
} else if (part.startsWith("[[...") && part.endsWith("]]")) {
// /[[...slug]]
return `\${OptionalCatchAllSlug<T>}`;
}
// /[slug]
return `\${SafeSlug<T>}`;
}
return part;
}).join("/");
}
return {
isDynamic,
routeType: `\n | \`${route}\``
};
}
// Whether redirects and rewrites have been converted into routeTypes or not.
let redirectsRewritesTypesProcessed = false;
// Convert redirects and rewrites into routeTypes.
function addRedirectsRewritesRouteTypes(rewrites, redirects) {
function addExtraRoute(source) {
let tokens;
try {
tokens = parse(source);
} catch {
// Ignore invalid routes - they will be handled by other checks.
}
if (Array.isArray(tokens)) {
const possibleNormalizedRoutes = [
""
];
let slugCnt = 1;
function append(suffix) {
for(let i = 0; i < possibleNormalizedRoutes.length; i++){
possibleNormalizedRoutes[i] += suffix;
}
}
function fork(suffix) {
const currentLength = possibleNormalizedRoutes.length;
for(let i = 0; i < currentLength; i++){
possibleNormalizedRoutes.push(possibleNormalizedRoutes[i] + suffix);
}
}
for (const token of tokens){
if (typeof token === "object") {
// Make sure the slug is always named.
const slug = token.name || (slugCnt++ === 1 ? "slug" : `slug${slugCnt}`);
if (token.modifier === "*") {
append(`${token.prefix}[[...${slug}]]`);
} else if (token.modifier === "+") {
append(`${token.prefix}[...${slug}]`);
} else if (token.modifier === "") {
if (token.pattern === "[^\\/#\\?]+?") {
// A safe slug
append(`${token.prefix}[${slug}]`);
} else if (token.pattern === ".*") {
// An optional catch-all slug
append(`${token.prefix}[[...${slug}]]`);
} else if (token.pattern === ".+") {
// A catch-all slug
append(`${token.prefix}[...${slug}]`);
} else {
// Other regex patterns are not supported. Skip this route.
return;
}
} else if (token.modifier === "?") {
if (/^[a-zA-Z0-9_/]*$/.test(token.pattern)) {
// An optional slug with plain text only, fork the route.
append(token.prefix);
fork(token.pattern);
} else {
// Optional modifier `?` and regex patterns are not supported.
return;
}
}
} else if (typeof token === "string") {
append(token);
}
}
for (const normalizedRoute of possibleNormalizedRoutes){
const { isDynamic, routeType } = formatRouteToRouteType(normalizedRoute);
routeTypes.extra[isDynamic ? "dynamic" : "static"] += routeType;
}
}
}
if (rewrites) {
for (const rewrite of rewrites.beforeFiles){
addExtraRoute(rewrite.source);
}
for (const rewrite of rewrites.afterFiles){
addExtraRoute(rewrite.source);
}
for (const rewrite of rewrites.fallback){
addExtraRoute(rewrite.source);
}
}
if (redirects) {
for (const redirect of redirects){
// Skip internal redirects
// https://github.com/vercel/next.js/blob/8ff3d7ff57836c24088474175d595b4d50b3f857/packages/next/src/lib/load-custom-routes.ts#L704-L710
if (!("internal" in redirect)) {
addExtraRoute(redirect.source);
}
}
}
}
function createRouteDefinitions() {
let staticRouteTypes = "";
let dynamicRouteTypes = "";
for (const type of [
"edge",
"node",
"extra"
]){
staticRouteTypes += routeTypes[type].static;
dynamicRouteTypes += routeTypes[type].dynamic;
}
// If both StaticRoutes and DynamicRoutes are empty, fallback to type 'string'.
const routeTypesFallback = !staticRouteTypes && !dynamicRouteTypes ? "string" : "";
return `// Type definitions for Next.js routes
/**
* Internal types used by the Next.js router and Link component.
* These types are not meant to be used directly.
* @internal
*/
declare namespace __next_route_internal_types__ {
type SearchOrHash = \`?\${string}\` | \`#\${string}\`
type WithProtocol = \`\${string}:\${string}\`
type Suffix = '' | SearchOrHash
type SafeSlug<S extends string> = S extends \`\${string}/\${string}\`
? never
: S extends \`\${string}\${SearchOrHash}\`
? never
: S extends ''
? never
: S
type CatchAllSlug<S extends string> = S extends \`\${string}\${SearchOrHash}\`
? never
: S extends ''
? never
: S
type OptionalCatchAllSlug<S extends string> =
S extends \`\${string}\${SearchOrHash}\` ? never : S
type StaticRoutes = ${staticRouteTypes || "never"}
type DynamicRoutes<T extends string = string> = ${dynamicRouteTypes || "never"}
type RouteImpl<T> = ${routeTypesFallback || `
${// This keeps autocompletion working for static routes.
"| StaticRoutes"}
| SearchOrHash
| WithProtocol
| \`\${StaticRoutes}\${SearchOrHash}\`
| (T extends \`\${DynamicRoutes<infer _>}\${Suffix}\` ? T : never)
`}
}
declare module 'next' {
export { default } from 'next/types/index.js'
export * from 'next/types/index.js'
export type Route<T extends string = string> =
__next_route_internal_types__.RouteImpl<T>
}
declare module 'next/link' {
import type { LinkProps as OriginalLinkProps } from 'next/dist/client/link.js'
import type { AnchorHTMLAttributes, DetailedHTMLProps } from 'react'
import type { UrlObject } from 'url'
type LinkRestProps = Omit<
Omit<
DetailedHTMLProps<
AnchorHTMLAttributes<HTMLAnchorElement>,
HTMLAnchorElement
>,
keyof OriginalLinkProps
> &
OriginalLinkProps,
'href'
>
export type LinkProps<RouteInferType> = LinkRestProps & {
/**
* The path or URL to navigate to. This is the only required prop. It can also be an object.
* @see https://nextjs.org/docs/api-reference/next/link
*/
href: __next_route_internal_types__.RouteImpl<RouteInferType> | UrlObject
}
export default function Link<RouteType>(props: LinkProps<RouteType>): JSX.Element
}
declare module 'next/navigation' {
export * from 'next/dist/client/components/navigation.js'
import type { NavigateOptions, AppRouterInstance as OriginalAppRouterInstance } from 'next/dist/shared/lib/app-router-context.shared-runtime.js'
interface AppRouterInstance extends OriginalAppRouterInstance {
/**
* Navigate to the provided href.
* Pushes a new history entry.
*/
push<RouteType>(href: __next_route_internal_types__.RouteImpl<RouteType>, options?: NavigateOptions): void
/**
* Navigate to the provided href.
* Replaces the current history entry.
*/
replace<RouteType>(href: __next_route_internal_types__.RouteImpl<RouteType>, options?: NavigateOptions): void
/**
* Prefetch the provided href.
*/
prefetch<RouteType>(href: __next_route_internal_types__.RouteImpl<RouteType>): void
}
export declare function useRouter(): AppRouterInstance;
}
`;
}
const appTypesBasePath = path.join("types", "app");
export class NextTypesPlugin {
constructor(options){
this.dir = options.dir;
this.distDir = options.distDir;
this.appDir = options.appDir;
this.dev = options.dev;
this.isEdgeServer = options.isEdgeServer;
this.pageExtensions = options.pageExtensions;
this.pagesDir = path.join(this.appDir, "..", "pages");
this.typedRoutes = options.typedRoutes;
this.distDirAbsolutePath = path.join(this.dir, this.distDir);
if (this.typedRoutes && !redirectsRewritesTypesProcessed) {
redirectsRewritesTypesProcessed = true;
addRedirectsRewritesRouteTypes(options.originalRewrites, options.originalRedirects);
}
}
getRelativePathFromAppTypesDir(moduleRelativePathToAppDir) {
const moduleAbsolutePath = path.join(this.appDir, moduleRelativePathToAppDir);
const moduleInAppTypesAbsolutePath = path.join(this.distDirAbsolutePath, appTypesBasePath, moduleRelativePathToAppDir);
return path.relative(moduleInAppTypesAbsolutePath + "/..", moduleAbsolutePath);
}
collectPage(filePath) {
if (!this.typedRoutes) return;
const isApp = filePath.startsWith(this.appDir + path.sep);
const isPages = !isApp && filePath.startsWith(this.pagesDir + path.sep);
if (!isApp && !isPages) {
return;
}
// Filter out non-page and non-route files in app dir
if (isApp && !/[/\\](?:page|route)\.[^.]+$/.test(filePath)) {
return;
}
// Filter out non-page files in pages dir
if (isPages && /[/\\](?:_app|_document|_error|404|500)\.[^.]+$/.test(filePath)) {
return;
}
let route = (isApp ? normalizeAppPath : denormalizePagePath)(ensureLeadingSlash(getPageFromPath(path.relative(isApp ? this.appDir : this.pagesDir, filePath), this.pageExtensions)));
const { isDynamic, routeType } = formatRouteToRouteType(route);
routeTypes[this.isEdgeServer ? "edge" : "node"][isDynamic ? "dynamic" : "static"] += routeType;
}
apply(compiler) {
// From asset root to dist root
const assetDirRelative = this.dev ? ".." : this.isEdgeServer ? ".." : "../..";
const handleModule = async (mod, assets)=>{
if (!mod.resource) return;
if (!/\.(js|jsx|ts|tsx|mjs)$/.test(mod.resource)) return;
if (!mod.resource.startsWith(this.appDir + path.sep)) {
if (!this.dev) {
if (mod.resource.startsWith(this.pagesDir + path.sep)) {
this.collectPage(mod.resource);
}
}
return;
}
if (mod.layer !== WEBPACK_LAYERS.reactServerComponents && mod.layer !== WEBPACK_LAYERS.appRouteHandler) return;
const IS_LAYOUT = /[/\\]layout\.[^./\\]+$/.test(mod.resource);
const IS_PAGE = !IS_LAYOUT && /[/\\]page\.[^.]+$/.test(mod.resource);
const IS_ROUTE = !IS_PAGE && /[/\\]route\.[^.]+$/.test(mod.resource);
const relativePathToApp = path.relative(this.appDir, mod.resource);
if (!this.dev) {
if (IS_PAGE || IS_ROUTE) {
this.collectPage(mod.resource);
}
}
const typePath = path.join(appTypesBasePath, relativePathToApp.replace(/\.(js|jsx|ts|tsx|mjs)$/, ".ts"));
const relativeImportPath = normalizePathSep(path.join(this.getRelativePathFromAppTypesDir(relativePathToApp)).replace(/\.(js|jsx|ts|tsx|mjs)$/, ""));
const assetPath = path.join(assetDirRelative, typePath);
if (IS_LAYOUT) {
const slots = await collectNamedSlots(mod.resource);
assets[assetPath] = new sources.RawSource(createTypeGuardFile(mod.resource, relativeImportPath, {
type: "layout",
slots
}));
} else if (IS_PAGE) {
assets[assetPath] = new sources.RawSource(createTypeGuardFile(mod.resource, relativeImportPath, {
type: "page"
}));
} else if (IS_ROUTE) {
assets[assetPath] = new sources.RawSource(createTypeGuardFile(mod.resource, relativeImportPath, {
type: "route"
}));
}
};
compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation)=>{
compilation.hooks.processAssets.tapAsync({
name: PLUGIN_NAME,
stage: webpack.Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE_HASH
}, async (assets, callback)=>{
const promises = [];
// Clear routes
if (this.isEdgeServer) {
routeTypes.edge.dynamic = "";
routeTypes.edge.static = "";
} else {
routeTypes.node.dynamic = "";
routeTypes.node.static = "";
}
compilation.chunkGroups.forEach((chunkGroup)=>{
chunkGroup.chunks.forEach((chunk)=>{
if (!chunk.name) return;
// Here we only track page and route chunks.
if (!chunk.name.startsWith("pages/") && !(chunk.name.startsWith("app/") && (chunk.name.endsWith("/page") || chunk.name.endsWith("/route")))) {
return;
}
const chunkModules = compilation.chunkGraph.getChunkModulesIterable(chunk);
for (const mod of chunkModules){
promises.push(handleModule(mod, assets));
// If this is a concatenation, register each child to the parent ID.
const anyModule = mod;
if (anyModule.modules) {
anyModule.modules.forEach((concatenatedMod)=>{
promises.push(handleModule(concatenatedMod, assets));
});
}
}
});
});
await Promise.all(promises);
// Support `"moduleResolution": "Node16" | "NodeNext"` with `"type": "module"`
const packageJsonAssetPath = path.join(assetDirRelative, "types/package.json");
assets[packageJsonAssetPath] = new sources.RawSource('{"type": "module"}');
if (this.typedRoutes) {
if (this.dev && !this.isEdgeServer) {
devPageFiles.forEach((file)=>{
this.collectPage(file);
});
}
const linkAssetPath = path.join(assetDirRelative, "types/link.d.ts");
assets[linkAssetPath] = new sources.RawSource(createRouteDefinitions());
}
callback();
});
});
}
}
//# sourceMappingURL=index.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,4 @@
// TODO: Eliminate this singleton in the future.
export const devPageFiles = new Set();
//# sourceMappingURL=shared.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../../src/build/webpack/plugins/next-types-plugin/shared.ts"],"names":["devPageFiles","Set"],"mappings":"AAAA,gDAAgD;AAChD,OAAO,MAAMA,eAAe,IAAIC,MAAa"}

View File

@@ -0,0 +1,92 @@
import { clearModuleContext } from "../../../server/web/sandbox";
import { realpathSync } from "../../../lib/realpath";
import path from "path";
import isError from "../../../lib/is-error";
import { clearManifestCache } from "../../../server/load-manifest";
const originModules = [
require.resolve("../../../server/require"),
require.resolve("../../../server/load-components"),
require.resolve("../../../server/next-server"),
require.resolve("next/dist/compiled/next-server/app-page.runtime.dev.js"),
require.resolve("next/dist/compiled/next-server/app-route.runtime.dev.js"),
require.resolve("next/dist/compiled/next-server/pages.runtime.dev.js"),
require.resolve("next/dist/compiled/next-server/pages-api.runtime.dev.js")
];
const RUNTIME_NAMES = [
"webpack-runtime",
"webpack-api-runtime"
];
function deleteFromRequireCache(filePath) {
try {
filePath = realpathSync(filePath);
} catch (e) {
if (isError(e) && e.code !== "ENOENT") throw e;
}
const mod = require.cache[filePath];
if (mod) {
// remove the child reference from the originModules
for (const originModule of originModules){
const parent = require.cache[originModule];
if (parent) {
const idx = parent.children.indexOf(mod);
if (idx >= 0) parent.children.splice(idx, 1);
}
}
// remove parent references from external modules
for (const child of mod.children){
child.parent = null;
}
delete require.cache[filePath];
return true;
}
return false;
}
export function deleteAppClientCache() {
deleteFromRequireCache(require.resolve("next/dist/compiled/next-server/app-page.runtime.dev.js"));
}
export function deleteCache(filePath) {
// try to clear it from the fs cache
clearManifestCache(filePath);
deleteFromRequireCache(filePath);
}
const PLUGIN_NAME = "NextJsRequireCacheHotReloader";
// This plugin flushes require.cache after emitting the files. Providing 'hot reloading' of server files.
export class NextJsRequireCacheHotReloader {
constructor(opts){
this.prevAssets = null;
this.hasServerComponents = opts.hasServerComponents;
}
apply(compiler) {
compiler.hooks.assetEmitted.tap(PLUGIN_NAME, (_file, { targetPath })=>{
// Clear module context in this process
clearModuleContext(targetPath);
deleteCache(targetPath);
});
compiler.hooks.afterEmit.tapPromise(PLUGIN_NAME, async (compilation)=>{
for (const name of RUNTIME_NAMES){
const runtimeChunkPath = path.join(compilation.outputOptions.path, `${name}.js`);
deleteCache(runtimeChunkPath);
}
// we need to make sure to clear all server entries from cache
// since they can have a stale webpack-runtime cache
// which needs to always be in-sync
let hasAppEntry = false;
const entries = [
...compilation.entries.keys()
].filter((entry)=>{
const isAppPath = entry.toString().startsWith("app/");
if (isAppPath) hasAppEntry = true;
return entry.toString().startsWith("pages/") || isAppPath;
});
if (hasAppEntry) {
deleteAppClientCache();
}
for (const page of entries){
const outputPath = path.join(compilation.outputOptions.path, page + ".js");
deleteCache(outputPath);
}
});
}
}
//# sourceMappingURL=nextjs-require-cache-hot-reloader.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../src/build/webpack/plugins/nextjs-require-cache-hot-reloader.ts"],"names":["clearModuleContext","realpathSync","path","isError","clearManifestCache","originModules","require","resolve","RUNTIME_NAMES","deleteFromRequireCache","filePath","e","code","mod","cache","originModule","parent","idx","children","indexOf","splice","child","deleteAppClientCache","deleteCache","PLUGIN_NAME","NextJsRequireCacheHotReloader","constructor","opts","prevAssets","hasServerComponents","apply","compiler","hooks","assetEmitted","tap","_file","targetPath","afterEmit","tapPromise","compilation","name","runtimeChunkPath","join","outputOptions","hasAppEntry","entries","keys","filter","entry","isAppPath","toString","startsWith","page","outputPath"],"mappings":"AACA,SAASA,kBAAkB,QAAQ,8BAA6B;AAChE,SAASC,YAAY,QAAQ,wBAAuB;AACpD,OAAOC,UAAU,OAAM;AACvB,OAAOC,aAAa,wBAAuB;AAC3C,SAASC,kBAAkB,QAAQ,gCAA+B;AAKlE,MAAMC,gBAAgB;IACpBC,QAAQC,OAAO,CAAC;IAChBD,QAAQC,OAAO,CAAC;IAChBD,QAAQC,OAAO,CAAC;IAChBD,QAAQC,OAAO,CAAC;IAChBD,QAAQC,OAAO,CAAC;IAChBD,QAAQC,OAAO,CAAC;IAChBD,QAAQC,OAAO,CAAC;CACjB;AAED,MAAMC,gBAAgB;IAAC;IAAmB;CAAsB;AAEhE,SAASC,uBAAuBC,QAAgB;IAC9C,IAAI;QACFA,WAAWT,aAAaS;IAC1B,EAAE,OAAOC,GAAG;QACV,IAAIR,QAAQQ,MAAMA,EAAEC,IAAI,KAAK,UAAU,MAAMD;IAC/C;IACA,MAAME,MAAMP,QAAQQ,KAAK,CAACJ,SAAS;IACnC,IAAIG,KAAK;QACP,oDAAoD;QACpD,KAAK,MAAME,gBAAgBV,cAAe;YACxC,MAAMW,SAASV,QAAQQ,KAAK,CAACC,aAAa;YAC1C,IAAIC,QAAQ;gBACV,MAAMC,MAAMD,OAAOE,QAAQ,CAACC,OAAO,CAACN;gBACpC,IAAII,OAAO,GAAGD,OAAOE,QAAQ,CAACE,MAAM,CAACH,KAAK;YAC5C;QACF;QACA,iDAAiD;QACjD,KAAK,MAAMI,SAASR,IAAIK,QAAQ,CAAE;YAChCG,MAAML,MAAM,GAAG;QACjB;QACA,OAAOV,QAAQQ,KAAK,CAACJ,SAAS;QAC9B,OAAO;IACT;IACA,OAAO;AACT;AAEA,OAAO,SAASY;IACdb,uBACEH,QAAQC,OAAO,CAAC;AAEpB;AAEA,OAAO,SAASgB,YAAYb,QAAgB;IAC1C,oCAAoC;IACpCN,mBAAmBM;IAEnBD,uBAAuBC;AACzB;AAEA,MAAMc,cAAc;AAEpB,yGAAyG;AACzG,OAAO,MAAMC;IAIXC,YAAYC,IAAsC,CAAE;aAHpDC,aAAkB;QAIhB,IAAI,CAACC,mBAAmB,GAAGF,KAAKE,mBAAmB;IACrD;IAEAC,MAAMC,QAAkB,EAAE;QACxBA,SAASC,KAAK,CAACC,YAAY,CAACC,GAAG,CAACV,aAAa,CAACW,OAAO,EAAEC,UAAU,EAAE;YACjE,uCAAuC;YACvCpC,mBAAmBoC;YACnBb,YAAYa;QACd;QAEAL,SAASC,KAAK,CAACK,SAAS,CAACC,UAAU,CAACd,aAAa,OAAOe;YACtD,KAAK,MAAMC,QAAQhC,cAAe;gBAChC,MAAMiC,mBAAmBvC,KAAKwC,IAAI,CAChCH,YAAYI,aAAa,CAACzC,IAAI,EAC9B,CAAC,EAAEsC,KAAK,GAAG,CAAC;gBAEdjB,YAAYkB;YACd;YAEA,8DAA8D;YAC9D,oDAAoD;YACpD,mCAAmC;YACnC,IAAIG,cAAc;YAClB,MAAMC,UAAU;mBAAIN,YAAYM,OAAO,CAACC,IAAI;aAAG,CAACC,MAAM,CAAC,CAACC;gBACtD,MAAMC,YAAYD,MAAME,QAAQ,GAAGC,UAAU,CAAC;gBAC9C,IAAIF,WAAWL,cAAc;gBAC7B,OAAOI,MAAME,QAAQ,GAAGC,UAAU,CAAC,aAAaF;YAClD;YAEA,IAAIL,aAAa;gBACftB;YACF;YAEA,KAAK,MAAM8B,QAAQP,QAAS;gBAC1B,MAAMQ,aAAanD,KAAKwC,IAAI,CAC1BH,YAAYI,aAAa,CAACzC,IAAI,EAC9BkD,OAAO;gBAET7B,YAAY8B;YACd;QACF;IACF;AACF"}

View File

@@ -0,0 +1,78 @@
import { webpack, sources } from "next/dist/compiled/webpack/webpack";
import { PAGES_MANIFEST, APP_PATHS_MANIFEST } from "../../../shared/lib/constants";
import getRouteFromEntrypoint from "../../../server/get-route-from-entrypoint";
import { normalizePathSep } from "../../../shared/lib/page-path/normalize-path-sep";
export let edgeServerPages = {};
export let nodeServerPages = {};
export let edgeServerAppPaths = {};
export let nodeServerAppPaths = {};
// This plugin creates a pages-manifest.json from page entrypoints.
// This is used for mapping paths like `/` to `.next/server/static/<buildid>/pages/index.js` when doing SSR
// It's also used by next export to provide defaultPathMap
export default class PagesManifestPlugin {
constructor({ dev, isEdgeRuntime, appDirEnabled }){
this.dev = dev;
this.isEdgeRuntime = isEdgeRuntime;
this.appDirEnabled = appDirEnabled;
}
createAssets(compilation, assets) {
const entrypoints = compilation.entrypoints;
const pages = {};
const appPaths = {};
for (const entrypoint of entrypoints.values()){
const pagePath = getRouteFromEntrypoint(entrypoint.name, this.appDirEnabled);
if (!pagePath) {
continue;
}
const files = entrypoint.getFiles().filter((file)=>!file.includes("webpack-runtime") && !file.includes("webpack-api-runtime") && file.endsWith(".js"));
// Skip entries which are empty
if (!files.length) {
continue;
}
// Write filename, replace any backslashes in path (on windows) with forwardslashes for cross-platform consistency.
let file = files[files.length - 1];
if (!this.dev) {
if (!this.isEdgeRuntime) {
file = file.slice(3);
}
}
file = normalizePathSep(file);
if (entrypoint.name.startsWith("app/")) {
appPaths[pagePath] = file;
} else {
pages[pagePath] = file;
}
}
// This plugin is used by both the Node server and Edge server compilers,
// we need to merge both pages to generate the full manifest.
if (this.isEdgeRuntime) {
edgeServerPages = pages;
edgeServerAppPaths = appPaths;
} else {
nodeServerPages = pages;
nodeServerAppPaths = appPaths;
}
assets[`${!this.dev && !this.isEdgeRuntime ? "../" : ""}` + PAGES_MANIFEST] = new sources.RawSource(JSON.stringify({
...edgeServerPages,
...nodeServerPages
}, null, 2));
if (this.appDirEnabled) {
assets[`${!this.dev && !this.isEdgeRuntime ? "../" : ""}` + APP_PATHS_MANIFEST] = new sources.RawSource(JSON.stringify({
...edgeServerAppPaths,
...nodeServerAppPaths
}, null, 2));
}
}
apply(compiler) {
compiler.hooks.make.tap("NextJsPagesManifest", (compilation)=>{
compilation.hooks.processAssets.tap({
name: "NextJsPagesManifest",
stage: webpack.Compilation.PROCESS_ASSETS_STAGE_ADDITIONS
}, (assets)=>{
this.createAssets(compilation, assets);
});
});
}
}
//# sourceMappingURL=pages-manifest-plugin.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../src/build/webpack/plugins/pages-manifest-plugin.ts"],"names":["webpack","sources","PAGES_MANIFEST","APP_PATHS_MANIFEST","getRouteFromEntrypoint","normalizePathSep","edgeServerPages","nodeServerPages","edgeServerAppPaths","nodeServerAppPaths","PagesManifestPlugin","constructor","dev","isEdgeRuntime","appDirEnabled","createAssets","compilation","assets","entrypoints","pages","appPaths","entrypoint","values","pagePath","name","files","getFiles","filter","file","includes","endsWith","length","slice","startsWith","RawSource","JSON","stringify","apply","compiler","hooks","make","tap","processAssets","stage","Compilation","PROCESS_ASSETS_STAGE_ADDITIONS"],"mappings":"AAAA,SAASA,OAAO,EAAEC,OAAO,QAAQ,qCAAoC;AACrE,SACEC,cAAc,EACdC,kBAAkB,QACb,gCAA+B;AACtC,OAAOC,4BAA4B,4CAA2C;AAC9E,SAASC,gBAAgB,QAAQ,mDAAkD;AAInF,OAAO,IAAIC,kBAAkB,CAAC,EAAC;AAC/B,OAAO,IAAIC,kBAAkB,CAAC,EAAC;AAC/B,OAAO,IAAIC,qBAAqB,CAAC,EAAC;AAClC,OAAO,IAAIC,qBAAqB,CAAC,EAAC;AAElC,mEAAmE;AACnE,2GAA2G;AAC3G,0DAA0D;AAC1D,eAAe,MAAMC;IAOnBC,YAAY,EACVC,GAAG,EACHC,aAAa,EACbC,aAAa,EAKd,CAAE;QACD,IAAI,CAACF,GAAG,GAAGA;QACX,IAAI,CAACC,aAAa,GAAGA;QACrB,IAAI,CAACC,aAAa,GAAGA;IACvB;IAEAC,aAAaC,WAAgB,EAAEC,MAAW,EAAE;QAC1C,MAAMC,cAAcF,YAAYE,WAAW;QAC3C,MAAMC,QAAuB,CAAC;QAC9B,MAAMC,WAA0B,CAAC;QAEjC,KAAK,MAAMC,cAAcH,YAAYI,MAAM,GAAI;YAC7C,MAAMC,WAAWnB,uBACfiB,WAAWG,IAAI,EACf,IAAI,CAACV,aAAa;YAGpB,IAAI,CAACS,UAAU;gBACb;YACF;YAEA,MAAME,QAAQJ,WACXK,QAAQ,GACRC,MAAM,CACL,CAACC,OACC,CAACA,KAAKC,QAAQ,CAAC,sBACf,CAACD,KAAKC,QAAQ,CAAC,0BACfD,KAAKE,QAAQ,CAAC;YAGpB,+BAA+B;YAC/B,IAAI,CAACL,MAAMM,MAAM,EAAE;gBACjB;YACF;YACA,mHAAmH;YACnH,IAAIH,OAAOH,KAAK,CAACA,MAAMM,MAAM,GAAG,EAAE;YAElC,IAAI,CAAC,IAAI,CAACnB,GAAG,EAAE;gBACb,IAAI,CAAC,IAAI,CAACC,aAAa,EAAE;oBACvBe,OAAOA,KAAKI,KAAK,CAAC;gBACpB;YACF;YACAJ,OAAOvB,iBAAiBuB;YAExB,IAAIP,WAAWG,IAAI,CAACS,UAAU,CAAC,SAAS;gBACtCb,QAAQ,CAACG,SAAS,GAAGK;YACvB,OAAO;gBACLT,KAAK,CAACI,SAAS,GAAGK;YACpB;QACF;QAEA,yEAAyE;QACzE,6DAA6D;QAC7D,IAAI,IAAI,CAACf,aAAa,EAAE;YACtBP,kBAAkBa;YAClBX,qBAAqBY;QACvB,OAAO;YACLb,kBAAkBY;YAClBV,qBAAqBW;QACvB;QAEAH,MAAM,CACJ,CAAC,EAAE,CAAC,IAAI,CAACL,GAAG,IAAI,CAAC,IAAI,CAACC,aAAa,GAAG,QAAQ,GAAG,CAAC,GAAGX,eACtD,GAAG,IAAID,QAAQiC,SAAS,CACvBC,KAAKC,SAAS,CACZ;YACE,GAAG9B,eAAe;YAClB,GAAGC,eAAe;QACpB,GACA,MACA;QAIJ,IAAI,IAAI,CAACO,aAAa,EAAE;YACtBG,MAAM,CACJ,CAAC,EAAE,CAAC,IAAI,CAACL,GAAG,IAAI,CAAC,IAAI,CAACC,aAAa,GAAG,QAAQ,GAAG,CAAC,GAAGV,mBACtD,GAAG,IAAIF,QAAQiC,SAAS,CACvBC,KAAKC,SAAS,CACZ;gBACE,GAAG5B,kBAAkB;gBACrB,GAAGC,kBAAkB;YACvB,GACA,MACA;QAGN;IACF;IAEA4B,MAAMC,QAA0B,EAAQ;QACtCA,SAASC,KAAK,CAACC,IAAI,CAACC,GAAG,CAAC,uBAAuB,CAACzB;YAC9CA,YAAYuB,KAAK,CAACG,aAAa,CAACD,GAAG,CACjC;gBACEjB,MAAM;gBACNmB,OAAO3C,QAAQ4C,WAAW,CAACC,8BAA8B;YAC3D,GACA,CAAC5B;gBACC,IAAI,CAACF,YAAY,CAACC,aAAaC;YACjC;QAEJ;IACF;AACF"}

View File

@@ -0,0 +1,247 @@
import { NormalModule } from "next/dist/compiled/webpack/webpack";
const pluginName = "ProfilingPlugin";
export const spans = new WeakMap();
const moduleSpansByCompilation = new WeakMap();
const makeSpanByCompilation = new WeakMap();
const sealSpanByCompilation = new WeakMap();
export const webpackInvalidSpans = new WeakMap();
const TRACE_LABELS_SEAL = [
"module assets",
"create chunk assets",
"asset render",
"asset emit",
"store asset"
];
function inTraceLabelsSeal(label) {
return TRACE_LABELS_SEAL.some((l)=>label.startsWith(l));
}
export class ProfilingPlugin {
constructor({ runWebpackSpan }){
this.runWebpackSpan = runWebpackSpan;
}
apply(compiler) {
this.traceTopLevelHooks(compiler);
this.traceCompilationHooks(compiler);
this.compiler = compiler;
}
traceHookPair(spanName, startHook, stopHook, { parentSpan, attrs, onStart, onStop } = {}) {
let span;
startHook.tap({
name: pluginName,
stage: -Infinity
}, (...params)=>{
const name = typeof spanName === "function" ? spanName() : spanName;
const attributes = attrs ? attrs(...params) : attrs;
span = parentSpan ? parentSpan(...params).traceChild(name, attributes) : this.runWebpackSpan.traceChild(name, attributes);
if (onStart) onStart(span, ...params);
});
stopHook.tap({
name: pluginName,
stage: Infinity
}, (...params)=>{
// `stopHook` may be triggered when `startHook` has not in cases
// where `stopHook` is used as the terminating event for more
// than one pair of hooks.
if (!span) {
return;
}
if (onStop) onStop(span, ...params);
span.stop();
});
}
traceTopLevelHooks(compiler) {
this.traceHookPair("webpack-compilation", compiler.hooks.compilation, compiler.hooks.afterCompile, {
parentSpan: ()=>webpackInvalidSpans.get(compiler) || this.runWebpackSpan,
attrs: ()=>({
name: compiler.name
}),
onStart: (span, compilation)=>{
spans.set(compilation, span);
spans.set(compiler, span);
moduleSpansByCompilation.set(compilation, new WeakMap());
}
});
if (compiler.options.mode === "development") {
this.traceHookPair(()=>`webpack-invalidated-${compiler.name}`, compiler.hooks.invalid, compiler.hooks.done, {
onStart: (span)=>webpackInvalidSpans.set(compiler, span),
onStop: ()=>webpackInvalidSpans.delete(compiler),
attrs: (fileName)=>({
trigger: fileName || "manual"
})
});
}
}
traceCompilationHooks(compiler) {
this.traceHookPair("emit", compiler.hooks.emit, compiler.hooks.afterEmit, {
parentSpan: ()=>webpackInvalidSpans.get(compiler) || this.runWebpackSpan
});
this.traceHookPair("make", compiler.hooks.make, compiler.hooks.finishMake, {
parentSpan: (compilation)=>{
const compilationSpan = spans.get(compilation);
if (!compilationSpan) {
return webpackInvalidSpans.get(compiler) || this.runWebpackSpan;
}
return compilationSpan;
},
onStart: (span, compilation)=>{
makeSpanByCompilation.set(compilation, span);
},
onStop: (_span, compilation)=>{
makeSpanByCompilation.delete(compilation);
}
});
compiler.hooks.compilation.tap({
name: pluginName,
stage: -Infinity
}, (compilation)=>{
compilation.hooks.buildModule.tap(pluginName, (module)=>{
var _compilation_moduleGraph;
const moduleType = (()=>{
if (!module.userRequest) {
return "";
}
return module.userRequest.split(".").pop();
})();
const issuerModule = compilation == null ? void 0 : (_compilation_moduleGraph = compilation.moduleGraph) == null ? void 0 : _compilation_moduleGraph.getIssuer(module);
let span;
const moduleSpans = moduleSpansByCompilation.get(compilation);
const spanName = `build-module${moduleType ? `-${moduleType}` : ""}`;
const issuerSpan = issuerModule && (moduleSpans == null ? void 0 : moduleSpans.get(issuerModule));
if (issuerSpan) {
span = issuerSpan.traceChild(spanName);
} else {
let parentSpan;
for (const incomingConnection of compilation.moduleGraph.getIncomingConnections(module)){
const entrySpan = spans.get(incomingConnection.dependency);
if (entrySpan) {
parentSpan = entrySpan;
break;
}
}
if (!parentSpan) {
const compilationSpan = spans.get(compilation);
if (!compilationSpan) {
return;
}
parentSpan = compilationSpan;
}
span = parentSpan.traceChild(spanName);
}
span.setAttribute("name", module.userRequest);
span.setAttribute("layer", module.layer);
moduleSpans.set(module, span);
});
const moduleHooks = NormalModule.getCompilationHooks(compilation);
moduleHooks.readResource.for(undefined).intercept({
register (tapInfo) {
const fn = tapInfo.fn;
tapInfo.fn = (loaderContext, callback)=>{
const moduleSpan = loaderContext.currentTraceSpan.traceChild(`read-resource`);
fn(loaderContext, (err, result)=>{
moduleSpan.stop();
callback(err, result);
});
};
return tapInfo;
}
});
moduleHooks.loader.tap(pluginName, (loaderContext, module)=>{
var _moduleSpansByCompilation_get;
const moduleSpan = (_moduleSpansByCompilation_get = moduleSpansByCompilation.get(compilation)) == null ? void 0 : _moduleSpansByCompilation_get.get(module);
loaderContext.currentTraceSpan = moduleSpan;
});
compilation.hooks.succeedModule.tap(pluginName, (module)=>{
var _moduleSpansByCompilation_get_get, _moduleSpansByCompilation_get;
moduleSpansByCompilation == null ? void 0 : (_moduleSpansByCompilation_get = moduleSpansByCompilation.get(compilation)) == null ? void 0 : (_moduleSpansByCompilation_get_get = _moduleSpansByCompilation_get.get(module)) == null ? void 0 : _moduleSpansByCompilation_get_get.stop();
});
compilation.hooks.failedModule.tap(pluginName, (module)=>{
var _moduleSpansByCompilation_get_get, _moduleSpansByCompilation_get;
moduleSpansByCompilation == null ? void 0 : (_moduleSpansByCompilation_get = moduleSpansByCompilation.get(compilation)) == null ? void 0 : (_moduleSpansByCompilation_get_get = _moduleSpansByCompilation_get.get(module)) == null ? void 0 : _moduleSpansByCompilation_get_get.stop();
});
this.traceHookPair("seal", compilation.hooks.seal, compilation.hooks.afterSeal, {
parentSpan: ()=>spans.get(compilation),
onStart (span) {
sealSpanByCompilation.set(compilation, span);
},
onStop () {
sealSpanByCompilation.delete(compilation);
}
});
compilation.hooks.addEntry.tap(pluginName, (entry)=>{
const parentSpan = makeSpanByCompilation.get(compilation) || spans.get(compilation);
if (!parentSpan) {
return;
}
const addEntrySpan = parentSpan.traceChild("add-entry");
addEntrySpan.setAttribute("request", entry.request);
spans.set(entry, addEntrySpan);
});
compilation.hooks.succeedEntry.tap(pluginName, (entry)=>{
var _spans_get;
(_spans_get = spans.get(entry)) == null ? void 0 : _spans_get.stop();
spans.delete(entry);
});
compilation.hooks.failedEntry.tap(pluginName, (entry)=>{
var _spans_get;
(_spans_get = spans.get(entry)) == null ? void 0 : _spans_get.stop();
spans.delete(entry);
});
this.traceHookPair("chunk-graph", compilation.hooks.beforeChunks, compilation.hooks.afterChunks, {
parentSpan: ()=>sealSpanByCompilation.get(compilation) || spans.get(compilation)
});
this.traceHookPair("optimize", compilation.hooks.optimize, compilation.hooks.reviveModules, {
parentSpan: ()=>sealSpanByCompilation.get(compilation) || spans.get(compilation)
});
this.traceHookPair("optimize-modules", compilation.hooks.optimizeModules, compilation.hooks.afterOptimizeModules, {
parentSpan: ()=>sealSpanByCompilation.get(compilation) || spans.get(compilation)
});
this.traceHookPair("optimize-chunks", compilation.hooks.optimizeChunks, compilation.hooks.afterOptimizeChunks, {
parentSpan: ()=>sealSpanByCompilation.get(compilation) || spans.get(compilation)
});
this.traceHookPair("optimize-tree", compilation.hooks.optimizeTree, compilation.hooks.afterOptimizeTree, {
parentSpan: ()=>sealSpanByCompilation.get(compilation) || spans.get(compilation)
});
this.traceHookPair("optimize-chunk-modules", compilation.hooks.optimizeChunkModules, compilation.hooks.afterOptimizeChunkModules, {
parentSpan: ()=>sealSpanByCompilation.get(compilation) || spans.get(compilation)
});
this.traceHookPair("module-hash", compilation.hooks.beforeModuleHash, compilation.hooks.afterModuleHash, {
parentSpan: ()=>sealSpanByCompilation.get(compilation) || spans.get(compilation)
});
this.traceHookPair("code-generation", compilation.hooks.beforeCodeGeneration, compilation.hooks.afterCodeGeneration, {
parentSpan: ()=>sealSpanByCompilation.get(compilation) || spans.get(compilation)
});
this.traceHookPair("hash", compilation.hooks.beforeHash, compilation.hooks.afterHash, {
parentSpan: ()=>sealSpanByCompilation.get(compilation) || spans.get(compilation)
});
this.traceHookPair("code-generation-jobs", compilation.hooks.afterHash, compilation.hooks.beforeModuleAssets, {
parentSpan: ()=>sealSpanByCompilation.get(compilation) || spans.get(compilation)
});
const logs = new Map();
const originalTime = compilation.logger.time;
const originalTimeEnd = compilation.logger.timeEnd;
compilation.logger.time = (label)=>{
if (!inTraceLabelsSeal(label)) {
return originalTime.call(compilation.logger, label);
}
const span = sealSpanByCompilation.get(compilation);
if (span) {
logs.set(label, span.traceChild(label.replace(/ /g, "-")));
}
return originalTime.call(compilation.logger, label);
};
compilation.logger.timeEnd = (label)=>{
if (!inTraceLabelsSeal(label)) {
return originalTimeEnd.call(compilation.logger, label);
}
const span = logs.get(label);
if (span) {
span.stop();
logs.delete(label);
}
return originalTimeEnd.call(compilation.logger, label);
};
});
}
}
//# sourceMappingURL=profiling-plugin.js.map

File diff suppressed because one or more lines are too long

View File

@@ -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
*/ // Implementation of this PR: https://github.com/jamiebuilds/react-loadable/pull/132
// Modified to strip out unneeded results for Next's specific use case
import { webpack, sources } from "next/dist/compiled/webpack/webpack";
import path from "path";
function getModuleId(compilation, module) {
return compilation.chunkGraph.getModuleId(module);
}
function getModuleFromDependency(compilation, dep) {
return compilation.moduleGraph.getModule(dep);
}
function getOriginModuleFromDependency(compilation, dep) {
return compilation.moduleGraph.getParentModule(dep);
}
function getChunkGroupFromBlock(compilation, block) {
return compilation.chunkGraph.getBlockChunkGroup(block);
}
function buildManifest(_compiler, compilation, pagesDir, dev) {
// If there's no pagesDir, output an empty manifest
if (!pagesDir) {
return {};
}
let manifest = {};
// This is allowed:
// import("./module"); <- ImportDependency
// We don't support that:
// import(/* webpackMode: "eager" */ "./module") <- ImportEagerDependency
// import(`./module/${param}`) <- ImportContextDependency
// Find all dependencies blocks which contains a `import()` dependency
const handleBlock = (block)=>{
block.blocks.forEach(handleBlock);
const chunkGroup = getChunkGroupFromBlock(compilation, block);
for (const dependency of block.dependencies){
if (dependency.type.startsWith("import()")) {
// get the referenced module
const module = getModuleFromDependency(compilation, dependency);
if (!module) return;
// get the module containing the import()
const originModule = getOriginModuleFromDependency(compilation, dependency);
const originRequest = originModule == null ? void 0 : originModule.resource;
if (!originRequest) return;
// We construct a "unique" key from origin module and request
// It's not perfect unique, but that will be fine for us.
// We also need to construct the same in the babel plugin.
const key = `${path.relative(pagesDir, originRequest)} -> ${dependency.request}`;
// Capture all files that need to be loaded.
const files = new Set();
if (manifest[key]) {
// In the "rare" case where multiple chunk groups
// are created for the same `import()` or multiple
// import()s reference the same module, we merge
// the files to make sure to not miss files
// This may cause overfetching in edge cases.
for (const file of manifest[key].files){
files.add(file);
}
}
// There might not be a chunk group when all modules
// are already loaded. In this case we only need need
// the module id and no files
if (chunkGroup) {
for (const chunk of chunkGroup.chunks){
chunk.files.forEach((file)=>{
if ((file.endsWith(".js") || file.endsWith(".css")) && file.match(/^static\/(chunks|css)\//)) {
files.add(file);
}
});
}
}
// usually we have to add the parent chunk groups too
// but we assume that all parents are also imported by
// next/dynamic so they are loaded by the same technique
// add the id and files to the manifest
const id = dev ? key : getModuleId(compilation, module);
manifest[key] = {
id,
files: Array.from(files)
};
}
}
};
for (const module of compilation.modules){
module.blocks.forEach(handleBlock);
}
manifest = Object.keys(manifest).sort()// eslint-disable-next-line no-sequences
.reduce((a, c)=>(a[c] = manifest[c], a), {});
return manifest;
}
export class ReactLoadablePlugin {
constructor(opts){
this.filename = opts.filename;
this.pagesDir = opts.pagesDir;
this.runtimeAsset = opts.runtimeAsset;
this.dev = opts.dev;
}
createAssets(compiler, compilation, assets) {
const manifest = buildManifest(compiler, compilation, this.pagesDir, this.dev);
// @ts-ignore: TODO: remove when webpack 5 is stable
assets[this.filename] = new sources.RawSource(JSON.stringify(manifest, null, 2));
if (this.runtimeAsset) {
assets[this.runtimeAsset] = new sources.RawSource(`self.__REACT_LOADABLE_MANIFEST=${JSON.stringify(JSON.stringify(manifest))}`);
}
return assets;
}
apply(compiler) {
compiler.hooks.make.tap("ReactLoadableManifest", (compilation)=>{
compilation.hooks.processAssets.tap({
name: "ReactLoadableManifest",
stage: webpack.Compilation.PROCESS_ASSETS_STAGE_ADDITIONS
}, (assets)=>{
this.createAssets(compiler, compilation, assets);
});
});
}
}
//# sourceMappingURL=react-loadable-plugin.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../src/build/webpack/plugins/react-loadable-plugin.ts"],"names":["webpack","sources","path","getModuleId","compilation","module","chunkGraph","getModuleFromDependency","dep","moduleGraph","getModule","getOriginModuleFromDependency","getParentModule","getChunkGroupFromBlock","block","getBlockChunkGroup","buildManifest","_compiler","pagesDir","dev","manifest","handleBlock","blocks","forEach","chunkGroup","dependency","dependencies","type","startsWith","originModule","originRequest","resource","key","relative","request","files","Set","file","add","chunk","chunks","endsWith","match","id","Array","from","modules","Object","keys","sort","reduce","a","c","ReactLoadablePlugin","constructor","opts","filename","runtimeAsset","createAssets","compiler","assets","RawSource","JSON","stringify","apply","hooks","make","tap","processAssets","name","stage","Compilation","PROCESS_ASSETS_STAGE_ADDITIONS"],"mappings":"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"}

View File

@@ -0,0 +1,43 @@
import { webpack, sources } from "next/dist/compiled/webpack/webpack";
import crypto from "crypto";
import { SUBRESOURCE_INTEGRITY_MANIFEST } from "../../../shared/lib/constants";
const PLUGIN_NAME = "SubresourceIntegrityPlugin";
export class SubresourceIntegrityPlugin {
constructor(algorithm){
this.algorithm = algorithm;
}
apply(compiler) {
compiler.hooks.make.tap(PLUGIN_NAME, (compilation)=>{
compilation.hooks.afterOptimizeAssets.tap({
name: PLUGIN_NAME,
stage: webpack.Compilation.PROCESS_ASSETS_STAGE_ADDITIONS
}, (assets)=>{
// Collect all the assets.
let files = new Set();
for (const asset of compilation.getAssets()){
files.add(asset.name);
}
// For each file, deduped, calculate the file hash.
const hashes = {};
for (const file of files.values()){
// Get the buffer for the asset.
const asset = assets[file];
if (!asset) {
throw new Error(`could not get asset: ${file}`);
}
// Get the buffer for the asset.
const buffer = asset.buffer();
// Create the hash for the content.
const hash = crypto.createHash(this.algorithm).update(buffer).digest().toString("base64");
hashes[file] = `${this.algorithm}-${hash}`;
}
const json = JSON.stringify(hashes, null, 2);
const file = "server/" + SUBRESOURCE_INTEGRITY_MANIFEST;
assets[file + ".js"] = new sources.RawSource(`self.__SUBRESOURCE_INTEGRITY_MANIFEST=${JSON.stringify(json)}`);
assets[file + ".json"] = new sources.RawSource(json);
});
});
}
}
//# sourceMappingURL=subresource-integrity-plugin.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../src/build/webpack/plugins/subresource-integrity-plugin.ts"],"names":["webpack","sources","crypto","SUBRESOURCE_INTEGRITY_MANIFEST","PLUGIN_NAME","SubresourceIntegrityPlugin","constructor","algorithm","apply","compiler","hooks","make","tap","compilation","afterOptimizeAssets","name","stage","Compilation","PROCESS_ASSETS_STAGE_ADDITIONS","assets","files","Set","asset","getAssets","add","hashes","file","values","Error","buffer","hash","createHash","update","digest","toString","json","JSON","stringify","RawSource"],"mappings":"AAAA,SAASA,OAAO,EAAEC,OAAO,QAAQ,qCAAoC;AACrE,OAAOC,YAAY,SAAQ;AAC3B,SAASC,8BAA8B,QAAQ,gCAA+B;AAE9E,MAAMC,cAAc;AAIpB,OAAO,MAAMC;IACXC,YAA6BC,UAA0C;yBAA1CA;IAA2C;IAEjEC,MAAMC,QAA0B,EAAE;QACvCA,SAASC,KAAK,CAACC,IAAI,CAACC,GAAG,CAACR,aAAa,CAACS;YACpCA,YAAYH,KAAK,CAACI,mBAAmB,CAACF,GAAG,CACvC;gBACEG,MAAMX;gBACNY,OAAOhB,QAAQiB,WAAW,CAACC,8BAA8B;YAC3D,GACA,CAACC;gBACC,0BAA0B;gBAC1B,IAAIC,QAAQ,IAAIC;gBAChB,KAAK,MAAMC,SAAST,YAAYU,SAAS,GAAI;oBAC3CH,MAAMI,GAAG,CAACF,MAAMP,IAAI;gBACtB;gBAEA,mDAAmD;gBACnD,MAAMU,SAAiC,CAAC;gBACxC,KAAK,MAAMC,QAAQN,MAAMO,MAAM,GAAI;oBACjC,gCAAgC;oBAChC,MAAML,QAAQH,MAAM,CAACO,KAAK;oBAC1B,IAAI,CAACJ,OAAO;wBACV,MAAM,IAAIM,MAAM,CAAC,qBAAqB,EAAEF,KAAK,CAAC;oBAChD;oBAEA,gCAAgC;oBAChC,MAAMG,SAASP,MAAMO,MAAM;oBAE3B,mCAAmC;oBACnC,MAAMC,OAAO5B,OACV6B,UAAU,CAAC,IAAI,CAACxB,SAAS,EACzByB,MAAM,CAACH,QACPI,MAAM,GACNC,QAAQ,CAAC;oBAEZT,MAAM,CAACC,KAAK,GAAG,CAAC,EAAE,IAAI,CAACnB,SAAS,CAAC,CAAC,EAAEuB,KAAK,CAAC;gBAC5C;gBAEA,MAAMK,OAAOC,KAAKC,SAAS,CAACZ,QAAQ,MAAM;gBAC1C,MAAMC,OAAO,YAAYvB;gBACzBgB,MAAM,CAACO,OAAO,MAAM,GAAG,IAAIzB,QAAQqC,SAAS,CAC1C,CAAC,sCAAsC,EAAEF,KAAKC,SAAS,CAACF,MAAM,CAAC;gBAIjEhB,MAAM,CAACO,OAAO,QAAQ,GAAG,IAAIzB,QAAQqC,SAAS,CAC5CH;YAIJ;QAEJ;IACF;AACF"}

View File

@@ -0,0 +1,167 @@
import { NormalModule } from "next/dist/compiled/webpack/webpack";
// Map of a feature module to the file it belongs in the next package.
const FEATURE_MODULE_MAP = new Map([
[
"next/image",
"/next/image.js"
],
[
"next/future/image",
"/next/future/image.js"
],
[
"next/legacy/image",
"/next/legacy/image.js"
],
[
"next/script",
"/next/script.js"
],
[
"next/dynamic",
"/next/dynamic.js"
]
]);
const FEATURE_MODULE_REGEXP_MAP = new Map([
[
"@next/font/google",
/\/@next\/font\/google\/target.css?.+$/
],
[
"@next/font/local",
/\/@next\/font\/local\/target.css?.+$/
],
[
"next/font/google",
/\/next\/font\/google\/target.css?.+$/
],
[
"next/font/local",
/\/next\/font\/local\/target.css?.+$/
]
]);
// List of build features used in webpack configuration
const BUILD_FEATURES = [
"swcLoader",
"swcMinify",
"swcRelay",
"swcStyledComponents",
"swcReactRemoveProperties",
"swcExperimentalDecorators",
"swcRemoveConsole",
"swcImportSource",
"swcEmotion",
"swc/target/x86_64-apple-darwin",
"swc/target/x86_64-unknown-linux-gnu",
"swc/target/x86_64-pc-windows-msvc",
"swc/target/i686-pc-windows-msvc",
"swc/target/aarch64-unknown-linux-gnu",
"swc/target/armv7-unknown-linux-gnueabihf",
"swc/target/aarch64-apple-darwin",
"swc/target/aarch64-linux-android",
"swc/target/arm-linux-androideabi",
"swc/target/x86_64-unknown-freebsd",
"swc/target/x86_64-unknown-linux-musl",
"swc/target/aarch64-unknown-linux-musl",
"swc/target/aarch64-pc-windows-msvc",
"turbotrace",
"transpilePackages",
"skipMiddlewareUrlNormalize",
"skipTrailingSlashRedirect",
"modularizeImports"
];
const ELIMINATED_PACKAGES = new Set();
/**
* Determine if there is a feature of interest in the specified 'module'.
*/ function findFeatureInModule(module) {
if (module.type !== "javascript/auto") {
return;
}
const normalizedIdentifier = module.identifier().replace(/\\/g, "/");
for (const [feature, path] of FEATURE_MODULE_MAP){
if (normalizedIdentifier.endsWith(path)) {
return feature;
}
}
for (const [feature, regexp] of FEATURE_MODULE_REGEXP_MAP){
if (regexp.test(normalizedIdentifier)) {
return feature;
}
}
}
/**
* Find unique origin modules in the specified 'connections', which possibly
* contains more than one connection for a module due to different types of
* dependency.
*/ function findUniqueOriginModulesInConnections(connections, originModule) {
const originModules = new Set();
for (const connection of connections){
if (!originModules.has(connection.originModule) && connection.originModule !== originModule) {
originModules.add(connection.originModule);
}
}
return originModules;
}
/**
* Plugin that queries the ModuleGraph to look for modules that correspond to
* certain features (e.g. next/image and next/script) and record how many times
* they are imported.
*/ export class TelemetryPlugin {
// Build feature usage is on/off and is known before the build starts
constructor(buildFeaturesMap){
this.usageTracker = new Map();
for (const featureName of BUILD_FEATURES){
this.usageTracker.set(featureName, {
featureName,
invocationCount: buildFeaturesMap.get(featureName) ? 1 : 0
});
}
for (const featureName of FEATURE_MODULE_MAP.keys()){
this.usageTracker.set(featureName, {
featureName,
invocationCount: 0
});
}
for (const featureName of FEATURE_MODULE_REGEXP_MAP.keys()){
this.usageTracker.set(featureName, {
featureName,
invocationCount: 0
});
}
}
apply(compiler) {
compiler.hooks.make.tapAsync(TelemetryPlugin.name, async (compilation, callback)=>{
compilation.hooks.finishModules.tapAsync(TelemetryPlugin.name, async (modules, modulesFinish)=>{
for (const module of modules){
const feature = findFeatureInModule(module);
if (!feature) {
continue;
}
const connections = compilation.moduleGraph.getIncomingConnections(module);
const originModules = findUniqueOriginModulesInConnections(connections, module);
this.usageTracker.get(feature).invocationCount = originModules.size;
}
modulesFinish();
});
callback();
});
if (compiler.options.mode === "production" && !compiler.watchMode) {
compiler.hooks.compilation.tap(TelemetryPlugin.name, (compilation)=>{
const moduleHooks = NormalModule.getCompilationHooks(compilation);
moduleHooks.loader.tap(TelemetryPlugin.name, (loaderContext)=>{
loaderContext.eliminatedPackages = ELIMINATED_PACKAGES;
});
});
}
}
usages() {
return [
...this.usageTracker.values()
];
}
packagesUsedInServerSideProps() {
return Array.from(ELIMINATED_PACKAGES);
}
}
//# sourceMappingURL=telemetry-plugin.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../src/build/webpack/plugins/telemetry-plugin.ts"],"names":["NormalModule","FEATURE_MODULE_MAP","Map","FEATURE_MODULE_REGEXP_MAP","BUILD_FEATURES","ELIMINATED_PACKAGES","Set","findFeatureInModule","module","type","normalizedIdentifier","identifier","replace","feature","path","endsWith","regexp","test","findUniqueOriginModulesInConnections","connections","originModule","originModules","connection","has","add","TelemetryPlugin","constructor","buildFeaturesMap","usageTracker","featureName","set","invocationCount","get","keys","apply","compiler","hooks","make","tapAsync","name","compilation","callback","finishModules","modules","modulesFinish","moduleGraph","getIncomingConnections","size","options","mode","watchMode","tap","moduleHooks","getCompilationHooks","loader","loaderContext","eliminatedPackages","usages","values","packagesUsedInServerSideProps","Array","from"],"mappings":"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"}

View File

@@ -0,0 +1,219 @@
import * as path from "path";
import { webpack, ModuleFilenameHelpers, sources } from "next/dist/compiled/webpack/webpack";
import pLimit from "next/dist/compiled/p-limit";
import { Worker } from "next/dist/compiled/jest-worker";
import { spans } from "../../profiling-plugin";
function getEcmaVersion(environment) {
// ES 6th
if (environment.arrowFunction || environment.const || environment.destructuring || environment.forOf || environment.module) {
return 2015;
}
// ES 11th
if (environment.bigIntLiteral || environment.dynamicImport) {
return 2020;
}
return 5;
}
function buildError(error, file) {
if (error.line) {
return new Error(`${file} from Terser\n${error.message} [${file}:${error.line},${error.col}]${error.stack ? `\n${error.stack.split("\n").slice(1).join("\n")}` : ""}`);
}
if (error.stack) {
return new Error(`${file} from Terser\n${error.message}\n${error.stack}`);
}
return new Error(`${file} from Terser\n${error.message}`);
}
const debugMinify = process.env.NEXT_DEBUG_MINIFY;
export class TerserPlugin {
constructor(options = {}){
const { terserOptions = {}, parallel, swcMinify } = options;
this.options = {
swcMinify,
parallel,
terserOptions
};
}
async optimize(compiler, compilation, assets, optimizeOptions, cache, { SourceMapSource, RawSource }) {
const compilationSpan = spans.get(compilation) || spans.get(compiler);
const terserSpan = compilationSpan.traceChild("terser-webpack-plugin-optimize");
terserSpan.setAttribute("compilationName", compilation.name);
terserSpan.setAttribute("swcMinify", this.options.swcMinify);
return terserSpan.traceAsyncFn(async ()=>{
let numberOfAssetsForMinify = 0;
const assetsList = Object.keys(assets);
const assetsForMinify = await Promise.all(assetsList.filter((name)=>{
if (!ModuleFilenameHelpers.matchObject.bind(// eslint-disable-next-line no-undefined
undefined, {
test: /\.[cm]?js(\?.*)?$/i
})(name)) {
return false;
}
const res = compilation.getAsset(name);
if (!res) {
console.log(name);
return false;
}
// don't minify _middleware as it can break in some cases
// and doesn't provide too much of a benefit as it's server-side
if (name.match(/(edge-runtime-webpack\.js|edge-chunks|middleware\.js$)/)) {
return false;
}
const { info } = res;
// Skip double minimize assets from child compilation
if (info.minimized) {
return false;
}
return true;
}).map(async (name)=>{
const { info, source } = compilation.getAsset(name);
const eTag = cache.getLazyHashedEtag(source);
const output = await cache.getPromise(name, eTag);
if (!output) {
numberOfAssetsForMinify += 1;
}
if (debugMinify && debugMinify === "1") {
console.dir({
name,
source: source.source().toString()
}, {
breakLength: Infinity,
maxStringLength: Infinity
});
}
return {
name,
info,
inputSource: source,
output,
eTag
};
}));
const numberOfWorkers = Math.min(numberOfAssetsForMinify, optimizeOptions.availableNumberOfCores);
let initializedWorker;
// eslint-disable-next-line consistent-return
const getWorker = ()=>{
if (this.options.swcMinify) {
return {
minify: async (options)=>{
const result = await require("../../../../swc").minify(options.input, {
...options.inputSourceMap ? {
sourceMap: {
content: JSON.stringify(options.inputSourceMap)
}
} : {},
compress: true,
mangle: true
});
return result;
}
};
}
if (initializedWorker) {
return initializedWorker;
}
initializedWorker = new Worker(path.join(__dirname, "./minify.js"), {
numWorkers: numberOfWorkers,
enableWorkerThreads: true
});
initializedWorker.getStdout().pipe(process.stdout);
initializedWorker.getStderr().pipe(process.stderr);
return initializedWorker;
};
const limit = pLimit(// When using the SWC minifier the limit will be handled by Node.js
this.options.swcMinify ? Infinity : numberOfAssetsForMinify > 0 ? numberOfWorkers : Infinity);
const scheduledTasks = [];
for (const asset of assetsForMinify){
scheduledTasks.push(limit(async ()=>{
const { name, inputSource, info, eTag } = asset;
let { output } = asset;
const minifySpan = terserSpan.traceChild("minify-js");
minifySpan.setAttribute("name", name);
minifySpan.setAttribute("cache", typeof output === "undefined" ? "MISS" : "HIT");
return minifySpan.traceAsyncFn(async ()=>{
if (!output) {
const { source: sourceFromInputSource, map: inputSourceMap } = inputSource.sourceAndMap();
const input = Buffer.isBuffer(sourceFromInputSource) ? sourceFromInputSource.toString() : sourceFromInputSource;
const options = {
name,
input,
inputSourceMap,
terserOptions: {
...this.options.terserOptions
}
};
if (typeof options.terserOptions.module === "undefined") {
if (typeof info.javascriptModule !== "undefined") {
options.terserOptions.module = info.javascriptModule;
} else if (/\.mjs(\?.*)?$/i.test(name)) {
options.terserOptions.module = true;
} else if (/\.cjs(\?.*)?$/i.test(name)) {
options.terserOptions.module = false;
}
}
try {
output = await getWorker().minify(options);
} catch (error) {
compilation.errors.push(buildError(error, name));
return;
}
if (output.map) {
output.source = new SourceMapSource(output.code, name, output.map, input, inputSourceMap, true);
} else {
output.source = new RawSource(output.code);
}
await cache.storePromise(name, eTag, {
source: output.source
});
}
const newInfo = {
minimized: true
};
const { source } = output;
compilation.updateAsset(name, source, newInfo);
});
}));
}
await Promise.all(scheduledTasks);
if (initializedWorker) {
await initializedWorker.end();
}
});
}
apply(compiler) {
var _compiler_webpack;
const { SourceMapSource, RawSource } = (compiler == null ? void 0 : (_compiler_webpack = compiler.webpack) == null ? void 0 : _compiler_webpack.sources) || sources;
const { output } = compiler.options;
if (typeof this.options.terserOptions.ecma === "undefined") {
this.options.terserOptions.ecma = getEcmaVersion(output.environment || {});
}
const pluginName = this.constructor.name;
const availableNumberOfCores = this.options.parallel;
compiler.hooks.thisCompilation.tap(pluginName, (compilation)=>{
const cache = compilation.getCache("TerserWebpackPlugin");
const handleHashForChunk = (hash, _chunk)=>{
// increment 'c' to invalidate cache
hash.update("c");
};
const JSModulesHooks = webpack.javascript.JavascriptModulesPlugin.getCompilationHooks(compilation);
JSModulesHooks.chunkHash.tap(pluginName, (chunk, hash)=>{
if (!chunk.hasRuntime()) return;
return handleHashForChunk(hash, chunk);
});
compilation.hooks.processAssets.tapPromise({
name: pluginName,
stage: webpack.Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE_SIZE
}, (assets)=>this.optimize(compiler, compilation, assets, {
availableNumberOfCores
}, cache, {
SourceMapSource,
RawSource
}));
compilation.hooks.statsPrinter.tap(pluginName, (stats)=>{
stats.hooks.print.for("asset.info.minimized").tap("terser-webpack-plugin", (minimized, { green, formatFlag })=>// eslint-disable-next-line no-undefined
minimized ? green(formatFlag("minimized")) : undefined);
});
});
}
}
//# sourceMappingURL=index.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,42 @@
import terser from "next/dist/compiled/terser";
function buildTerserOptions(terserOptions = {}) {
return {
...terserOptions,
mangle: terserOptions.mangle == null ? true : typeof terserOptions.mangle === "boolean" ? terserOptions.mangle : {
...terserOptions.mangle
},
// Ignoring sourceMap from options
// eslint-disable-next-line no-undefined
sourceMap: undefined,
// the `output` option is deprecated
...terserOptions.format ? {
format: {
beautify: false,
...terserOptions.format
}
} : {
output: {
beautify: false,
...terserOptions.output
}
}
};
}
export async function minify(options) {
const { name, input, inputSourceMap, terserOptions } = options;
// Copy terser options
const opts = buildTerserOptions(terserOptions);
// Let terser generate a SourceMap
if (inputSourceMap) {
// @ts-ignore
opts.sourceMap = {
asObject: true
};
}
const result = await terser.minify({
[name]: input
}, opts);
return result;
}
//# sourceMappingURL=minify.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../../../src/build/webpack/plugins/terser-webpack-plugin/src/minify.ts"],"names":["terser","buildTerserOptions","terserOptions","mangle","sourceMap","undefined","format","beautify","output","minify","options","name","input","inputSourceMap","opts","asObject","result"],"mappings":"AAAA,OAAOA,YAAY,4BAA2B;AAE9C,SAASC,mBAAmBC,gBAAqB,CAAC,CAAC;IACjD,OAAO;QACL,GAAGA,aAAa;QAChBC,QACED,cAAcC,MAAM,IAAI,OACpB,OACA,OAAOD,cAAcC,MAAM,KAAK,YAChCD,cAAcC,MAAM,GACpB;YAAE,GAAGD,cAAcC,MAAM;QAAC;QAChC,kCAAkC;QAClC,wCAAwC;QACxCC,WAAWC;QACX,oCAAoC;QACpC,GAAIH,cAAcI,MAAM,GACpB;YAAEA,QAAQ;gBAAEC,UAAU;gBAAO,GAAGL,cAAcI,MAAM;YAAC;QAAE,IACvD;YAAEE,QAAQ;gBAAED,UAAU;gBAAO,GAAGL,cAAcM,MAAM;YAAC;QAAE,CAAC;IAC9D;AACF;AAEA,OAAO,eAAeC,OAAOC,OAAY;IACvC,MAAM,EAAEC,IAAI,EAAEC,KAAK,EAAEC,cAAc,EAAEX,aAAa,EAAE,GAAGQ;IACvD,sBAAsB;IACtB,MAAMI,OAAOb,mBAAmBC;IAEhC,kCAAkC;IAClC,IAAIW,gBAAgB;QAClB,aAAa;QACbC,KAAKV,SAAS,GAAG;YAAEW,UAAU;QAAK;IACpC;IAEA,MAAMC,SAAS,MAAMhB,OAAOS,MAAM,CAAC;QAAE,CAACE,KAAK,EAAEC;IAAM,GAAGE;IACtD,OAAOE;AACT"}

View File

@@ -0,0 +1,62 @@
import loaderUtils from "next/dist/compiled/loader-utils3";
import { relative } from "path";
function formatModule(compiler, module) {
const relativePath = relative(compiler.context, module.resource).replace(/\?.+$/, "");
return loaderUtils.isUrlRequest(relativePath) ? loaderUtils.urlToRequest(relativePath) : relativePath;
}
export function formatModuleTrace(compiler, moduleTrace) {
let importTrace = [];
let firstExternalModule;
for(let i = moduleTrace.length - 1; i >= 0; i--){
const mod = moduleTrace[i];
if (!mod.resource) continue;
if (!mod.resource.includes("node_modules/")) {
importTrace.unshift(formatModule(compiler, mod));
} else {
firstExternalModule = mod;
break;
}
}
let invalidImportMessage = "";
if (firstExternalModule) {
var _firstExternalModule_resourceResolveData_descriptionFileData, _firstExternalModule_resourceResolveData;
const firstExternalPackageName = (_firstExternalModule_resourceResolveData = firstExternalModule.resourceResolveData) == null ? void 0 : (_firstExternalModule_resourceResolveData_descriptionFileData = _firstExternalModule_resourceResolveData.descriptionFileData) == null ? void 0 : _firstExternalModule_resourceResolveData_descriptionFileData.name;
if (firstExternalPackageName === "styled-jsx") {
invalidImportMessage += `\n\nThe error was caused by using 'styled-jsx' in '${importTrace[0]}'. It only works in a Client Component but none of its parents are marked with "use client", so they're Server Components by default.`;
} else {
let formattedExternalFile = firstExternalModule.resource.split("node_modules");
formattedExternalFile = formattedExternalFile[formattedExternalFile.length - 1];
invalidImportMessage += `\n\nThe error was caused by importing '${formattedExternalFile.slice(1)}' in '${importTrace[0]}'.`;
}
}
return {
lastInternalFileName: importTrace[0],
invalidImportMessage,
formattedModuleTrace: `${importTrace.map((mod)=>" " + mod).join("\n")}`
};
}
export function getModuleTrace(module, compilation, compiler) {
// Get the module trace:
// https://cs.github.com/webpack/webpack/blob/9fcaa243573005d6fdece9a3f8d89a0e8b399613/lib/stats/DefaultStatsFactoryPlugin.js#L414
const visitedModules = new Set();
const moduleTrace = [];
let current = module;
let isPagesDir = false;
while(current){
if (visitedModules.has(current)) break;
if (/[\\/]pages/.test(current.resource.replace(compiler.context, ""))) {
isPagesDir = true;
}
visitedModules.add(current);
moduleTrace.push(current);
const origin = compilation.moduleGraph.getIssuer(current);
if (!origin) break;
current = origin;
}
return {
moduleTrace,
isPagesDir
};
}
//# sourceMappingURL=getModuleTrace.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../../src/build/webpack/plugins/wellknown-errors-plugin/getModuleTrace.ts"],"names":["loaderUtils","relative","formatModule","compiler","module","relativePath","context","resource","replace","isUrlRequest","urlToRequest","formatModuleTrace","moduleTrace","importTrace","firstExternalModule","i","length","mod","includes","unshift","invalidImportMessage","firstExternalPackageName","resourceResolveData","descriptionFileData","name","formattedExternalFile","split","slice","lastInternalFileName","formattedModuleTrace","map","join","getModuleTrace","compilation","visitedModules","Set","current","isPagesDir","has","test","add","push","origin","moduleGraph","getIssuer"],"mappings":"AACA,OAAOA,iBAAiB,mCAAkC;AAC1D,SAASC,QAAQ,QAAQ,OAAM;AAE/B,SAASC,aAAaC,QAA0B,EAAEC,MAAW;IAC3D,MAAMC,eAAeJ,SAASE,SAASG,OAAO,EAAEF,OAAOG,QAAQ,EAAEC,OAAO,CACtE,SACA;IAEF,OAAOR,YAAYS,YAAY,CAACJ,gBAC5BL,YAAYU,YAAY,CAACL,gBACzBA;AACN;AAEA,OAAO,SAASM,kBACdR,QAA0B,EAC1BS,WAAkB;IAElB,IAAIC,cAAwB,EAAE;IAC9B,IAAIC;IACJ,IAAK,IAAIC,IAAIH,YAAYI,MAAM,GAAG,GAAGD,KAAK,GAAGA,IAAK;QAChD,MAAME,MAAML,WAAW,CAACG,EAAE;QAC1B,IAAI,CAACE,IAAIV,QAAQ,EAAE;QAEnB,IAAI,CAACU,IAAIV,QAAQ,CAACW,QAAQ,CAAC,kBAAkB;YAC3CL,YAAYM,OAAO,CAACjB,aAAaC,UAAUc;QAC7C,OAAO;YACLH,sBAAsBG;YACtB;QACF;IACF;IAEA,IAAIG,uBAAuB;IAC3B,IAAIN,qBAAqB;YAErBA,8DAAAA;QADF,MAAMO,4BACJP,2CAAAA,oBAAoBQ,mBAAmB,sBAAvCR,+DAAAA,yCAAyCS,mBAAmB,qBAA5DT,6DAA8DU,IAAI;QAEpE,IAAIH,6BAA6B,cAAc;YAC7CD,wBAAwB,CAAC,mDAAmD,EAAEP,WAAW,CAAC,EAAE,CAAC,qIAAqI,CAAC;QACrO,OAAO;YACL,IAAIY,wBACFX,oBAAoBP,QAAQ,CAACmB,KAAK,CAAC;YACrCD,wBACEA,qBAAqB,CAACA,sBAAsBT,MAAM,GAAG,EAAE;YAEzDI,wBAAwB,CAAC,uCAAuC,EAAEK,sBAAsBE,KAAK,CAC3F,GACA,MAAM,EAAEd,WAAW,CAAC,EAAE,CAAC,EAAE,CAAC;QAC9B;IACF;IAEA,OAAO;QACLe,sBAAsBf,WAAW,CAAC,EAAE;QACpCO;QACAS,sBAAsB,CAAC,EAAEhB,YAAYiB,GAAG,CAAC,CAACb,MAAQ,OAAOA,KAAKc,IAAI,CAAC,MAAM,CAAC;IAC5E;AACF;AAEA,OAAO,SAASC,eACd5B,MAAW,EACX6B,WAAgC,EAChC9B,QAA0B;IAE1B,wBAAwB;IACxB,kIAAkI;IAClI,MAAM+B,iBAAiB,IAAIC;IAC3B,MAAMvB,cAAc,EAAE;IAEtB,IAAIwB,UAAUhC;IACd,IAAIiC,aAAa;IACjB,MAAOD,QAAS;QACd,IAAIF,eAAeI,GAAG,CAACF,UAAU;QACjC,IAAI,aAAaG,IAAI,CAACH,QAAQ7B,QAAQ,CAACC,OAAO,CAACL,SAASG,OAAO,EAAE,MAAM;YACrE+B,aAAa;QACf;QACAH,eAAeM,GAAG,CAACJ;QACnBxB,YAAY6B,IAAI,CAACL;QACjB,MAAMM,SAAST,YAAYU,WAAW,CAACC,SAAS,CAACR;QACjD,IAAI,CAACM,QAAQ;QACbN,UAAUM;IACZ;IAEA,OAAO;QACL9B;QACAyB;IACF;AACF"}

View File

@@ -0,0 +1,25 @@
import { getModuleBuildError } from "./webpackModuleError";
const NAME = "WellKnownErrorsPlugin";
export class WellKnownErrorsPlugin {
apply(compiler) {
compiler.hooks.compilation.tap(NAME, (compilation)=>{
compilation.hooks.afterSeal.tapPromise(NAME, async ()=>{
var _compilation_errors;
if ((_compilation_errors = compilation.errors) == null ? void 0 : _compilation_errors.length) {
await Promise.all(compilation.errors.map(async (err, i)=>{
try {
const moduleError = await getModuleBuildError(compiler, compilation, err);
if (moduleError !== false) {
compilation.errors[i] = moduleError;
}
} catch (e) {
console.log(e);
}
}));
}
});
});
}
}
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../../src/build/webpack/plugins/wellknown-errors-plugin/index.ts"],"names":["getModuleBuildError","NAME","WellKnownErrorsPlugin","apply","compiler","hooks","compilation","tap","afterSeal","tapPromise","errors","length","Promise","all","map","err","i","moduleError","e","console","log"],"mappings":"AAEA,SAASA,mBAAmB,QAAQ,uBAAsB;AAE1D,MAAMC,OAAO;AACb,OAAO,MAAMC;IACXC,MAAMC,QAA0B,EAAE;QAChCA,SAASC,KAAK,CAACC,WAAW,CAACC,GAAG,CAACN,MAAM,CAACK;YACpCA,YAAYD,KAAK,CAACG,SAAS,CAACC,UAAU,CAACR,MAAM;oBACvCK;gBAAJ,KAAIA,sBAAAA,YAAYI,MAAM,qBAAlBJ,oBAAoBK,MAAM,EAAE;oBAC9B,MAAMC,QAAQC,GAAG,CACfP,YAAYI,MAAM,CAACI,GAAG,CAAC,OAAOC,KAAKC;wBACjC,IAAI;4BACF,MAAMC,cAAc,MAAMjB,oBACxBI,UACAE,aACAS;4BAEF,IAAIE,gBAAgB,OAAO;gCACzBX,YAAYI,MAAM,CAACM,EAAE,GAAGC;4BAC1B;wBACF,EAAE,OAAOC,GAAG;4BACVC,QAAQC,GAAG,CAACF;wBACd;oBACF;gBAEJ;YACF;QACF;IACF;AACF"}

View File

@@ -0,0 +1,22 @@
import Chalk from "next/dist/compiled/chalk";
import { SimpleWebpackError } from "./simpleWebpackError";
const chalk = new Chalk.constructor({
enabled: true
});
export function getBabelError(fileName, err) {
if (err.code !== "BABEL_PARSE_ERROR") {
return false;
}
// https://github.com/babel/babel/blob/34693d6024da3f026534dd8d569f97ac0109602e/packages/babel-core/src/parser/index.js
if (err.loc) {
const lineNumber = Math.max(1, err.loc.line);
const column = Math.max(1, err.loc.column);
let message = err.message// Remove file information, which instead is provided by webpack.
.replace(/^.+?: /, "")// Remove column information from message
.replace(new RegExp(`[^\\S\\r\\n]*\\(${lineNumber}:${column}\\)[^\\S\\r\\n]*`), "");
return new SimpleWebpackError(`${chalk.cyan(fileName)}:${chalk.yellow(lineNumber.toString())}:${chalk.yellow(column.toString())}`, chalk.red.bold("Syntax error").concat(`: ${message}`));
}
return false;
}
//# sourceMappingURL=parseBabel.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../../src/build/webpack/plugins/wellknown-errors-plugin/parseBabel.ts"],"names":["Chalk","SimpleWebpackError","chalk","constructor","enabled","getBabelError","fileName","err","code","loc","lineNumber","Math","max","line","column","message","replace","RegExp","cyan","yellow","toString","red","bold","concat"],"mappings":"AAAA,OAAOA,WAAW,2BAA0B;AAC5C,SAASC,kBAAkB,QAAQ,uBAAsB;AAEzD,MAAMC,QAAQ,IAAIF,MAAMG,WAAW,CAAC;IAAEC,SAAS;AAAK;AAEpD,OAAO,SAASC,cACdC,QAAgB,EAChBC,GAGC;IAED,IAAIA,IAAIC,IAAI,KAAK,qBAAqB;QACpC,OAAO;IACT;IAEA,uHAAuH;IACvH,IAAID,IAAIE,GAAG,EAAE;QACX,MAAMC,aAAaC,KAAKC,GAAG,CAAC,GAAGL,IAAIE,GAAG,CAACI,IAAI;QAC3C,MAAMC,SAASH,KAAKC,GAAG,CAAC,GAAGL,IAAIE,GAAG,CAACK,MAAM;QAEzC,IAAIC,UAAUR,IAAIQ,OAAO,AACvB,iEAAiE;SAChEC,OAAO,CAAC,UAAU,GACnB,yCAAyC;SACxCA,OAAO,CACN,IAAIC,OAAO,CAAC,gBAAgB,EAAEP,WAAW,CAAC,EAAEI,OAAO,gBAAgB,CAAC,GACpE;QAGJ,OAAO,IAAIb,mBACT,CAAC,EAAEC,MAAMgB,IAAI,CAACZ,UAAU,CAAC,EAAEJ,MAAMiB,MAAM,CACrCT,WAAWU,QAAQ,IACnB,CAAC,EAAElB,MAAMiB,MAAM,CAACL,OAAOM,QAAQ,IAAI,CAAC,EACtClB,MAAMmB,GAAG,CAACC,IAAI,CAAC,gBAAgBC,MAAM,CAAC,CAAC,EAAE,EAAER,QAAQ,CAAC;IAExD;IAEA,OAAO;AACT"}

View File

@@ -0,0 +1,22 @@
import Chalk from "next/dist/compiled/chalk";
import { SimpleWebpackError } from "./simpleWebpackError";
const chalk = new Chalk.constructor({
enabled: true
});
const regexCssError = /^(?:CssSyntaxError|SyntaxError)\n\n\((\d+):(\d*)\) (.*)$/s;
export function getCssError(fileName, err) {
if (!((err.name === "CssSyntaxError" || err.name === "SyntaxError") && err.stack === false && !(err instanceof SyntaxError))) {
return false;
}
// https://github.com/postcss/postcss-loader/blob/d6931da177ac79707bd758436e476036a55e4f59/src/Error.js
const res = regexCssError.exec(err.message);
if (res) {
const [, _lineNumber, _column, reason] = res;
const lineNumber = Math.max(1, parseInt(_lineNumber, 10));
const column = Math.max(1, parseInt(_column, 10));
return new SimpleWebpackError(`${chalk.cyan(fileName)}:${chalk.yellow(lineNumber.toString())}:${chalk.yellow(column.toString())}`, chalk.red.bold("Syntax error").concat(`: ${reason}`));
}
return false;
}
//# sourceMappingURL=parseCss.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../../src/build/webpack/plugins/wellknown-errors-plugin/parseCss.ts"],"names":["Chalk","SimpleWebpackError","chalk","constructor","enabled","regexCssError","getCssError","fileName","err","name","stack","SyntaxError","res","exec","message","_lineNumber","_column","reason","lineNumber","Math","max","parseInt","column","cyan","yellow","toString","red","bold","concat"],"mappings":"AAAA,OAAOA,WAAW,2BAA0B;AAC5C,SAASC,kBAAkB,QAAQ,uBAAsB;AAEzD,MAAMC,QAAQ,IAAIF,MAAMG,WAAW,CAAC;IAAEC,SAAS;AAAK;AACpD,MAAMC,gBACJ;AAEF,OAAO,SAASC,YACdC,QAAgB,EAChBC,GAAU;IAEV,IACE,CACE,CAAA,AAACA,CAAAA,IAAIC,IAAI,KAAK,oBAAoBD,IAAIC,IAAI,KAAK,aAAY,KAC3D,AAACD,IAAYE,KAAK,KAAK,SACvB,CAAEF,CAAAA,eAAeG,WAAU,CAAC,GAE9B;QACA,OAAO;IACT;IAEA,uGAAuG;IAEvG,MAAMC,MAAMP,cAAcQ,IAAI,CAACL,IAAIM,OAAO;IAC1C,IAAIF,KAAK;QACP,MAAM,GAAGG,aAAaC,SAASC,OAAO,GAAGL;QACzC,MAAMM,aAAaC,KAAKC,GAAG,CAAC,GAAGC,SAASN,aAAa;QACrD,MAAMO,SAASH,KAAKC,GAAG,CAAC,GAAGC,SAASL,SAAS;QAE7C,OAAO,IAAIf,mBACT,CAAC,EAAEC,MAAMqB,IAAI,CAAChB,UAAU,CAAC,EAAEL,MAAMsB,MAAM,CACrCN,WAAWO,QAAQ,IACnB,CAAC,EAAEvB,MAAMsB,MAAM,CAACF,OAAOG,QAAQ,IAAI,CAAC,EACtCvB,MAAMwB,GAAG,CAACC,IAAI,CAAC,gBAAgBC,MAAM,CAAC,CAAC,EAAE,EAAEX,OAAO,CAAC;IAEvD;IAEA,OAAO;AACT"}

View File

@@ -0,0 +1,15 @@
import { relative } from "path";
import { SimpleWebpackError } from "./simpleWebpackError";
export function getNextAppLoaderError(err, module, compiler) {
try {
if (!module.loaders[0].loader.includes("next-app-loader.js")) {
return false;
}
const file = relative(compiler.context, module.buildInfo.route.absolutePagePath);
return new SimpleWebpackError(file, err.message);
} catch {
return false;
}
}
//# sourceMappingURL=parseNextAppLoaderError.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../../src/build/webpack/plugins/wellknown-errors-plugin/parseNextAppLoaderError.ts"],"names":["relative","SimpleWebpackError","getNextAppLoaderError","err","module","compiler","loaders","loader","includes","file","context","buildInfo","route","absolutePagePath","message"],"mappings":"AACA,SAASA,QAAQ,QAAQ,OAAM;AAC/B,SAASC,kBAAkB,QAAQ,uBAAsB;AAEzD,OAAO,SAASC,sBACdC,GAAU,EACVC,MAAW,EACXC,QAA0B;IAE1B,IAAI;QACF,IAAI,CAACD,OAAOE,OAAO,CAAC,EAAE,CAACC,MAAM,CAACC,QAAQ,CAAC,uBAAuB;YAC5D,OAAO;QACT;QAEA,MAAMC,OAAOT,SACXK,SAASK,OAAO,EAChBN,OAAOO,SAAS,CAACC,KAAK,CAACC,gBAAgB;QAGzC,OAAO,IAAIZ,mBAAmBQ,MAAMN,IAAIW,OAAO;IACjD,EAAE,OAAM;QACN,OAAO;IACT;AACF"}

View File

@@ -0,0 +1,23 @@
import { SimpleWebpackError } from "./simpleWebpackError";
export function getNextFontError(err, module) {
try {
const resourceResolveData = module.resourceResolveData;
if (!module.loaders.find((loader)=>/next-font-loader[/\\]index.js/.test(loader.loader))) {
return false;
}
// Parse the query and get the path of the file where the font function was called.
// provided by next-swc next-transform-font
const file = JSON.parse(resourceResolveData.query.slice(1)).path;
if (err.name === "NextFontError") {
// Known error thrown by @next/font, display the error message
return new SimpleWebpackError(file, `\`next/font\` error:\n${err.message}`);
} else {
// Unknown error thrown by @next/font
return new SimpleWebpackError(file, `An error occured in \`next/font\`.\n\n${err.stack}`);
}
} catch {
return false;
}
}
//# sourceMappingURL=parseNextFontError.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../../src/build/webpack/plugins/wellknown-errors-plugin/parseNextFontError.ts"],"names":["SimpleWebpackError","getNextFontError","err","module","resourceResolveData","loaders","find","loader","test","file","JSON","parse","query","slice","path","name","message","stack"],"mappings":"AAAA,SAASA,kBAAkB,QAAQ,uBAAsB;AAEzD,OAAO,SAASC,iBACdC,GAAU,EACVC,MAAW;IAEX,IAAI;QACF,MAAMC,sBAAsBD,OAAOC,mBAAmB;QACtD,IACE,CAACD,OAAOE,OAAO,CAACC,IAAI,CAAC,CAACC,SACpB,gCAAgCC,IAAI,CAACD,OAAOA,MAAM,IAEpD;YACA,OAAO;QACT;QAEA,mFAAmF;QACnF,2CAA2C;QAC3C,MAAME,OAAOC,KAAKC,KAAK,CAACP,oBAAoBQ,KAAK,CAACC,KAAK,CAAC,IAAIC,IAAI;QAEhE,IAAIZ,IAAIa,IAAI,KAAK,iBAAiB;YAChC,8DAA8D;YAC9D,OAAO,IAAIf,mBACTS,MACA,CAAC,sBAAsB,EAAEP,IAAIc,OAAO,CAAC,CAAC;QAE1C,OAAO;YACL,qCAAqC;YACrC,OAAO,IAAIhB,mBACTS,MACA,CAAC,sCAAsC,EAAEP,IAAIe,KAAK,CAAC,CAAC;QAExD;IACF,EAAE,OAAM;QACN,OAAO;IACT;AACF"}

View File

@@ -0,0 +1,16 @@
import { formatModuleTrace, getModuleTrace } from "./getModuleTrace";
import { SimpleWebpackError } from "./simpleWebpackError";
export function getNextInvalidImportError(err, module, compilation, compiler) {
try {
if (!module.loaders.find((loader)=>loader.loader.includes("next-invalid-import-error-loader.js"))) {
return false;
}
const { moduleTrace } = getModuleTrace(module, compilation, compiler);
const { formattedModuleTrace, lastInternalFileName, invalidImportMessage } = formatModuleTrace(compiler, moduleTrace);
return new SimpleWebpackError(lastInternalFileName, err.message + invalidImportMessage + "\n\nImport trace for requested module:\n" + formattedModuleTrace);
} catch {
return false;
}
}
//# sourceMappingURL=parseNextInvalidImportError.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../../src/build/webpack/plugins/wellknown-errors-plugin/parseNextInvalidImportError.ts"],"names":["formatModuleTrace","getModuleTrace","SimpleWebpackError","getNextInvalidImportError","err","module","compilation","compiler","loaders","find","loader","includes","moduleTrace","formattedModuleTrace","lastInternalFileName","invalidImportMessage","message"],"mappings":"AACA,SAASA,iBAAiB,EAAEC,cAAc,QAAQ,mBAAkB;AACpE,SAASC,kBAAkB,QAAQ,uBAAsB;AAEzD,OAAO,SAASC,0BACdC,GAAU,EACVC,MAAW,EACXC,WAAgC,EAChCC,QAA0B;IAE1B,IAAI;QACF,IACE,CAACF,OAAOG,OAAO,CAACC,IAAI,CAAC,CAACC,SACpBA,OAAOA,MAAM,CAACC,QAAQ,CAAC,yCAEzB;YACA,OAAO;QACT;QAEA,MAAM,EAAEC,WAAW,EAAE,GAAGX,eAAeI,QAAQC,aAAaC;QAC5D,MAAM,EAAEM,oBAAoB,EAAEC,oBAAoB,EAAEC,oBAAoB,EAAE,GACxEf,kBAAkBO,UAAUK;QAE9B,OAAO,IAAIV,mBACTY,sBACAV,IAAIY,OAAO,GACTD,uBACA,6CACAF;IAEN,EAAE,OAAM;QACN,OAAO;IACT;AACF"}

View File

@@ -0,0 +1,127 @@
import Chalk from "next/dist/compiled/chalk";
import { SimpleWebpackError } from "./simpleWebpackError";
import { createOriginalStackFrame } from "next/dist/compiled/@next/react-dev-overlay/dist/middleware";
const chalk = new Chalk.constructor({
enabled: true
});
// Based on https://github.com/webpack/webpack/blob/fcdd04a833943394bbb0a9eeb54a962a24cc7e41/lib/stats/DefaultStatsFactoryPlugin.js#L422-L431
/*
Copyright JS Foundation and other contributors
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 SOFTWARE.
*/ function getModuleTrace(input, compilation) {
const visitedModules = new Set();
const moduleTrace = [];
let current = input.module;
while(current){
if (visitedModules.has(current)) break; // circular (technically impossible, but who knows)
visitedModules.add(current);
const origin = compilation.moduleGraph.getIssuer(current);
if (!origin) break;
moduleTrace.push({
origin,
module: current
});
current = origin;
}
return moduleTrace;
}
async function getSourceFrame(input, fileName, compilation) {
try {
var _result_originalStackFrame_lineNumber, _result_originalStackFrame, _result_originalStackFrame_column, _result_originalStackFrame1;
const loc = input.loc ? input.loc : input.dependencies.map((d)=>d.loc).filter(Boolean)[0];
const originalSource = input.module.originalSource();
const result = await createOriginalStackFrame({
line: loc.start.line,
column: loc.start.column,
source: originalSource,
rootDirectory: compilation.options.context,
modulePath: fileName,
frame: {}
});
return {
frame: (result == null ? void 0 : result.originalCodeFrame) ?? "",
lineNumber: (result == null ? void 0 : (_result_originalStackFrame = result.originalStackFrame) == null ? void 0 : (_result_originalStackFrame_lineNumber = _result_originalStackFrame.lineNumber) == null ? void 0 : _result_originalStackFrame_lineNumber.toString()) ?? "",
column: (result == null ? void 0 : (_result_originalStackFrame1 = result.originalStackFrame) == null ? void 0 : (_result_originalStackFrame_column = _result_originalStackFrame1.column) == null ? void 0 : _result_originalStackFrame_column.toString()) ?? ""
};
} catch {
return {
frame: "",
lineNumber: "",
column: ""
};
}
}
function getFormattedFileName(fileName, module, lineNumber, column) {
var _module_loaders;
if ((_module_loaders = module.loaders) == null ? void 0 : _module_loaders.find((loader)=>/next-font-loader[/\\]index.js/.test(loader.loader))) {
// Parse the query and get the path of the file where the font function was called.
// provided by next-swc next-transform-font
return JSON.parse(module.resourceResolveData.query.slice(1)).path;
} else {
let formattedFileName = chalk.cyan(fileName);
if (lineNumber && column) {
formattedFileName += `:${chalk.yellow(lineNumber)}:${chalk.yellow(column)}`;
}
return formattedFileName;
}
}
export async function getNotFoundError(compilation, input, fileName, module) {
if (input.name !== "ModuleNotFoundError" && !(input.name === "ModuleBuildError" && /Error: Can't resolve '.+' in /.test(input.message))) {
return false;
}
try {
const { frame, lineNumber, column } = await getSourceFrame(input, fileName, compilation);
const errorMessage = input.error.message.replace(/ in '.*?'/, "").replace(/Can't resolve '(.*)'/, `Can't resolve '${chalk.green("$1")}'`);
const importTrace = ()=>{
const moduleTrace = getModuleTrace(input, compilation).map(({ origin })=>origin.readableIdentifier(compilation.requestShortener)).filter((name)=>name && !/next-(app|middleware|client-pages|route|flight-(client|server|client-entry))-loader\.js/.test(name) && !/next-route-loader\/index\.js/.test(name) && !/css-loader.+\.js/.test(name));
if (moduleTrace.length === 0) return "";
return `\nImport trace for requested module:\n${moduleTrace.join("\n")}`;
};
let message = chalk.red.bold("Module not found") + `: ${errorMessage}` + "\n" + frame + (frame !== "" ? "\n" : "") + "\nhttps://nextjs.org/docs/messages/module-not-found\n" + importTrace();
const formattedFileName = getFormattedFileName(fileName, module, lineNumber, column);
return new SimpleWebpackError(formattedFileName, message);
} catch (err) {
// Don't fail on failure to resolve sourcemaps
return input;
}
}
export async function getImageError(compilation, input, err) {
if (err.name !== "InvalidImageFormatError") {
return false;
}
const moduleTrace = getModuleTrace(input, compilation);
const { origin, module } = moduleTrace[0] || {};
if (!origin || !module) {
return false;
}
const page = origin.rawRequest.replace(/^private-next-pages/, "./pages");
const importedFile = module.rawRequest;
const source = origin.originalSource().buffer().toString("utf8");
let lineNumber = -1;
source.split("\n").some((line)=>{
lineNumber++;
return line.includes(importedFile);
});
return new SimpleWebpackError(`${chalk.cyan(page)}:${chalk.yellow(lineNumber.toString())}`, chalk.red.bold("Error").concat(`: Image import "${importedFile}" is not a valid image file. The image may be corrupted or an unsupported format.`));
}
//# sourceMappingURL=parseNotFoundError.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../../src/build/webpack/plugins/wellknown-errors-plugin/parseNotFoundError.ts"],"names":["Chalk","SimpleWebpackError","createOriginalStackFrame","chalk","constructor","enabled","getModuleTrace","input","compilation","visitedModules","Set","moduleTrace","current","module","has","add","origin","moduleGraph","getIssuer","push","getSourceFrame","fileName","result","loc","dependencies","map","d","filter","Boolean","originalSource","line","start","column","source","rootDirectory","options","context","modulePath","frame","originalCodeFrame","lineNumber","originalStackFrame","toString","getFormattedFileName","loaders","find","loader","test","JSON","parse","resourceResolveData","query","slice","path","formattedFileName","cyan","yellow","getNotFoundError","name","message","errorMessage","error","replace","green","importTrace","readableIdentifier","requestShortener","length","join","red","bold","err","getImageError","page","rawRequest","importedFile","buffer","split","some","includes","concat"],"mappings":"AAAA,OAAOA,WAAW,2BAA0B;AAC5C,SAASC,kBAAkB,QAAQ,uBAAsB;AACzD,SAASC,wBAAwB,QAAQ,6DAA4D;AAGrG,MAAMC,QAAQ,IAAIH,MAAMI,WAAW,CAAC;IAAEC,SAAS;AAAK;AAEpD,6IAA6I;AAC7I;;;;;;;;;;;;;;;;;;;;;;AAsBA,GACA,SAASC,eAAeC,KAAU,EAAEC,WAAgB;IAClD,MAAMC,iBAAiB,IAAIC;IAC3B,MAAMC,cAAc,EAAE;IACtB,IAAIC,UAAUL,MAAMM,MAAM;IAC1B,MAAOD,QAAS;QACd,IAAIH,eAAeK,GAAG,CAACF,UAAU,OAAM,mDAAmD;QAC1FH,eAAeM,GAAG,CAACH;QACnB,MAAMI,SAASR,YAAYS,WAAW,CAACC,SAAS,CAACN;QACjD,IAAI,CAACI,QAAQ;QACbL,YAAYQ,IAAI,CAAC;YAAEH;YAAQH,QAAQD;QAAQ;QAC3CA,UAAUI;IACZ;IAEA,OAAOL;AACT;AAEA,eAAeS,eACbb,KAAU,EACVc,QAAa,EACbb,WAAgB;IAEhB,IAAI;YAiBYc,uCAAAA,4BACJA,mCAAAA;QAjBV,MAAMC,MAAMhB,MAAMgB,GAAG,GACjBhB,MAAMgB,GAAG,GACThB,MAAMiB,YAAY,CAACC,GAAG,CAAC,CAACC,IAAWA,EAAEH,GAAG,EAAEI,MAAM,CAACC,QAAQ,CAAC,EAAE;QAChE,MAAMC,iBAAiBtB,MAAMM,MAAM,CAACgB,cAAc;QAElD,MAAMP,SAAS,MAAMpB,yBAAyB;YAC5C4B,MAAMP,IAAIQ,KAAK,CAACD,IAAI;YACpBE,QAAQT,IAAIQ,KAAK,CAACC,MAAM;YACxBC,QAAQJ;YACRK,eAAe1B,YAAY2B,OAAO,CAACC,OAAO;YAC1CC,YAAYhB;YACZiB,OAAO,CAAC;QACV;QAEA,OAAO;YACLA,OAAOhB,CAAAA,0BAAAA,OAAQiB,iBAAiB,KAAI;YACpCC,YAAYlB,CAAAA,2BAAAA,6BAAAA,OAAQmB,kBAAkB,sBAA1BnB,wCAAAA,2BAA4BkB,UAAU,qBAAtClB,sCAAwCoB,QAAQ,OAAM;YAClEV,QAAQV,CAAAA,2BAAAA,8BAAAA,OAAQmB,kBAAkB,sBAA1BnB,oCAAAA,4BAA4BU,MAAM,qBAAlCV,kCAAoCoB,QAAQ,OAAM;QAC5D;IACF,EAAE,OAAM;QACN,OAAO;YAAEJ,OAAO;YAAIE,YAAY;YAAIR,QAAQ;QAAG;IACjD;AACF;AAEA,SAASW,qBACPtB,QAAgB,EAChBR,MAAW,EACX2B,UAAmB,EACnBR,MAAe;QAGbnB;IADF,KACEA,kBAAAA,OAAO+B,OAAO,qBAAd/B,gBAAgBgC,IAAI,CAAC,CAACC,SACpB,gCAAgCC,IAAI,CAACD,OAAOA,MAAM,IAEpD;QACA,mFAAmF;QACnF,2CAA2C;QAC3C,OAAOE,KAAKC,KAAK,CAACpC,OAAOqC,mBAAmB,CAACC,KAAK,CAACC,KAAK,CAAC,IAAIC,IAAI;IACnE,OAAO;QACL,IAAIC,oBAA4BnD,MAAMoD,IAAI,CAAClC;QAC3C,IAAImB,cAAcR,QAAQ;YACxBsB,qBAAqB,CAAC,CAAC,EAAEnD,MAAMqD,MAAM,CAAChB,YAAY,CAAC,EAAErC,MAAMqD,MAAM,CAC/DxB,QACA,CAAC;QACL;QAEA,OAAOsB;IACT;AACF;AAEA,OAAO,eAAeG,iBACpBjD,WAAgC,EAChCD,KAAU,EACVc,QAAgB,EAChBR,MAAW;IAEX,IACEN,MAAMmD,IAAI,KAAK,yBACf,CACEnD,CAAAA,MAAMmD,IAAI,KAAK,sBACf,gCAAgCX,IAAI,CAACxC,MAAMoD,OAAO,CAAA,GAEpD;QACA,OAAO;IACT;IAEA,IAAI;QACF,MAAM,EAAErB,KAAK,EAAEE,UAAU,EAAER,MAAM,EAAE,GAAG,MAAMZ,eAC1Cb,OACAc,UACAb;QAGF,MAAMoD,eAAerD,MAAMsD,KAAK,CAACF,OAAO,CACrCG,OAAO,CAAC,aAAa,IACrBA,OAAO,CAAC,wBAAwB,CAAC,eAAe,EAAE3D,MAAM4D,KAAK,CAAC,MAAM,CAAC,CAAC;QAEzE,MAAMC,cAAc;YAClB,MAAMrD,cAAcL,eAAeC,OAAOC,aACvCiB,GAAG,CAAC,CAAC,EAAET,MAAM,EAAE,GACdA,OAAOiD,kBAAkB,CAACzD,YAAY0D,gBAAgB,GAEvDvC,MAAM,CACL,CAAC+B,OACCA,QACA,CAAC,0FAA0FX,IAAI,CAC7FW,SAEF,CAAC,+BAA+BX,IAAI,CAACW,SACrC,CAAC,mBAAmBX,IAAI,CAACW;YAE/B,IAAI/C,YAAYwD,MAAM,KAAK,GAAG,OAAO;YAErC,OAAO,CAAC,sCAAsC,EAAExD,YAAYyD,IAAI,CAAC,MAAM,CAAC;QAC1E;QAEA,IAAIT,UACFxD,MAAMkE,GAAG,CAACC,IAAI,CAAC,sBACf,CAAC,EAAE,EAAEV,aAAa,CAAC,GACnB,OACAtB,QACCA,CAAAA,UAAU,KAAK,OAAO,EAAC,IACxB,0DACA0B;QAEF,MAAMV,oBAAoBX,qBACxBtB,UACAR,QACA2B,YACAR;QAGF,OAAO,IAAI/B,mBAAmBqD,mBAAmBK;IACnD,EAAE,OAAOY,KAAK;QACZ,8CAA8C;QAC9C,OAAOhE;IACT;AACF;AAEA,OAAO,eAAeiE,cACpBhE,WAAgB,EAChBD,KAAU,EACVgE,GAAU;IAEV,IAAIA,IAAIb,IAAI,KAAK,2BAA2B;QAC1C,OAAO;IACT;IAEA,MAAM/C,cAAcL,eAAeC,OAAOC;IAC1C,MAAM,EAAEQ,MAAM,EAAEH,MAAM,EAAE,GAAGF,WAAW,CAAC,EAAE,IAAI,CAAC;IAC9C,IAAI,CAACK,UAAU,CAACH,QAAQ;QACtB,OAAO;IACT;IACA,MAAM4D,OAAOzD,OAAO0D,UAAU,CAACZ,OAAO,CAAC,uBAAuB;IAC9D,MAAMa,eAAe9D,OAAO6D,UAAU;IACtC,MAAMzC,SAASjB,OAAOa,cAAc,GAAG+C,MAAM,GAAGlC,QAAQ,CAAC;IACzD,IAAIF,aAAa,CAAC;IAClBP,OAAO4C,KAAK,CAAC,MAAMC,IAAI,CAAC,CAAChD;QACvBU;QACA,OAAOV,KAAKiD,QAAQ,CAACJ;IACvB;IACA,OAAO,IAAI1E,mBACT,CAAC,EAAEE,MAAMoD,IAAI,CAACkB,MAAM,CAAC,EAAEtE,MAAMqD,MAAM,CAAChB,WAAWE,QAAQ,IAAI,CAAC,EAC5DvC,MAAMkE,GAAG,CACNC,IAAI,CAAC,SACLU,MAAM,CACL,CAAC,gBAAgB,EAAEL,aAAa,iFAAiF,CAAC;AAG1H"}

View File

@@ -0,0 +1,89 @@
import { getModuleTrace, formatModuleTrace } from "./getModuleTrace";
import { SimpleWebpackError } from "./simpleWebpackError";
function formatRSCErrorMessage(message, isPagesDir, fileName) {
let formattedMessage = message;
let formattedVerboseMessage = "";
// Comes from the "React Server Components" transform in SWC, always
// attach the module trace.
const NEXT_RSC_ERR_REACT_API = /.+NEXT_RSC_ERR_REACT_API: (.*?)\n/s;
const NEXT_RSC_ERR_SERVER_IMPORT = /.+NEXT_RSC_ERR_SERVER_IMPORT: (.*?)\n/s;
const NEXT_RSC_ERR_CLIENT_IMPORT = /.+NEXT_RSC_ERR_CLIENT_IMPORT: (.*?)\n/s;
const NEXT_RSC_ERR_CLIENT_METADATA_EXPORT = /.+NEXT_RSC_ERR_CLIENT_METADATA_EXPORT: (.*?)\n/s;
const NEXT_RSC_ERR_CONFLICT_METADATA_EXPORT = /NEXT_RSC_ERR_CONFLICT_METADATA_EXPORT/s;
const NEXT_RSC_ERR_CLIENT_DIRECTIVE = /.+NEXT_RSC_ERR_CLIENT_DIRECTIVE\n/s;
const NEXT_RSC_ERR_CLIENT_DIRECTIVE_PAREN = /.+NEXT_RSC_ERR_CLIENT_DIRECTIVE_PAREN\n/s;
const NEXT_RSC_ERR_INVALID_API = /.+NEXT_RSC_ERR_INVALID_API: (.*?)\n/s;
const NEXT_RSC_ERR_ERROR_FILE_SERVER_COMPONENT = /.+NEXT_RSC_ERR_ERROR_FILE_SERVER_COMPONENT/;
if (NEXT_RSC_ERR_REACT_API.test(message)) {
const matches = message.match(NEXT_RSC_ERR_REACT_API);
if (matches && matches[1] === "Component") {
formattedMessage = `\n\nYoure importing a class component. It only works in a Client Component but none of its parents are marked with "use client", so they're Server Components by default.\nLearn more: https://nextjs.org/docs/getting-started/react-essentials#client-components\n\n`;
} else {
formattedMessage = message.replace(NEXT_RSC_ERR_REACT_API, `\n\nYou're importing a component that needs $1. It only works in a Client Component but none of its parents are marked with "use client", so they're Server Components by default.\nLearn more: https://nextjs.org/docs/getting-started/react-essentials\n\n`);
}
formattedVerboseMessage = '\n\nMaybe one of these should be marked as a client entry with "use client":\n';
} else if (NEXT_RSC_ERR_SERVER_IMPORT.test(message)) {
let shouldAddUseClient = true;
const matches = message.match(NEXT_RSC_ERR_SERVER_IMPORT);
switch(matches && matches[1]){
case "react-dom/server":
// If importing "react-dom/server", we should show a different error.
formattedMessage = `\n\nYou're importing a component that imports react-dom/server. To fix it, render or return the content directly as a Server Component instead for perf and security.\nLearn more: https://nextjs.org/docs/getting-started/react-essentials`;
break;
case "next/router":
// If importing "next/router", we should tell them to use "next/navigation".
formattedMessage = `\n\nYou have a Server Component that imports next/router. Use next/navigation instead.\nLearn more: https://nextjs.org/docs/app/api-reference/functions/use-router`;
shouldAddUseClient = false;
break;
default:
formattedMessage = message.replace(NEXT_RSC_ERR_SERVER_IMPORT, `\n\nYou're importing a component that imports $1. It only works in a Client Component but none of its parents are marked with "use client", so they're Server Components by default.\nLearn more: https://nextjs.org/docs/getting-started/react-essentials\n\n`);
}
formattedVerboseMessage = shouldAddUseClient ? '\n\nMaybe one of these should be marked as a client entry "use client":\n' : "\n\nImport trace:\n";
} else if (NEXT_RSC_ERR_CLIENT_IMPORT.test(message)) {
if (isPagesDir) {
formattedMessage = message.replace(NEXT_RSC_ERR_CLIENT_IMPORT, `\n\nYou're importing a component that needs $1. That only works in a Server Component which is not supported in the pages/ directory. Read more: https://nextjs.org/docs/getting-started/react-essentials#server-components\n\n`);
formattedVerboseMessage = "\n\nImport trace for requested module:\n";
} else {
formattedMessage = message.replace(NEXT_RSC_ERR_CLIENT_IMPORT, `\n\nYou're importing a component that needs $1. That only works in a Server Component but one of its parents is marked with "use client", so it's a Client Component.\nLearn more: https://nextjs.org/docs/getting-started/react-essentials\n\n`);
formattedVerboseMessage = '\n\nOne of these is marked as a client entry with "use client":\n';
}
} else if (NEXT_RSC_ERR_CLIENT_DIRECTIVE.test(message)) {
formattedMessage = message.replace(NEXT_RSC_ERR_CLIENT_DIRECTIVE, `\n\nThe "use client" directive must be placed before other expressions. Move it to the top of the file to resolve this issue.\n\n`);
formattedVerboseMessage = "\n\nImport path:\n";
} else if (NEXT_RSC_ERR_CLIENT_DIRECTIVE_PAREN.test(message)) {
formattedMessage = message.replace(NEXT_RSC_ERR_CLIENT_DIRECTIVE_PAREN, `\n\n"use client" must be a directive, and placed before other expressions. Remove the parentheses and move it to the top of the file to resolve this issue.\nLearn more: https://nextjs.org/docs/getting-started/react-essentials#the-use-client-directive\n\n`);
formattedVerboseMessage = "\n\nImport path:\n";
} else if (NEXT_RSC_ERR_INVALID_API.test(message)) {
formattedMessage = message.replace(NEXT_RSC_ERR_INVALID_API, `\n\n"$1" is not supported in app/. Read more: https://nextjs.org/docs/app/building-your-application/data-fetching\n\n`);
formattedVerboseMessage = "\n\nFile path:\n";
} else if (NEXT_RSC_ERR_ERROR_FILE_SERVER_COMPONENT.test(message)) {
formattedMessage = message.replace(NEXT_RSC_ERR_ERROR_FILE_SERVER_COMPONENT, `\n\n${fileName} must be a Client Component. Add the "use client" directive the top of the file to resolve this issue.\nLearn more: https://nextjs.org/docs/getting-started/react-essentials#client-components\n\n`);
formattedVerboseMessage = "\n\nImport path:\n";
} else if (NEXT_RSC_ERR_CLIENT_METADATA_EXPORT.test(message)) {
formattedMessage = message.replace(NEXT_RSC_ERR_CLIENT_METADATA_EXPORT, `\n\nYou are attempting to export "$1" from a component marked with "use client", which is disallowed. Either remove the export, or the "use client" directive. Read more: https://nextjs.org/docs/getting-started/react-essentials#the-use-client-directive\n\n`);
formattedVerboseMessage = "\n\nFile path:\n";
} else if (NEXT_RSC_ERR_CONFLICT_METADATA_EXPORT.test(message)) {
formattedMessage = message.replace(NEXT_RSC_ERR_CONFLICT_METADATA_EXPORT, `\n\n"metadata" and "generateMetadata" cannot be exported at the same time, please keep one of them. Read more: https://nextjs.org/docs/app/api-reference/file-conventions/metadata\n\n`);
formattedVerboseMessage = "\n\nFile path:\n";
}
return [
formattedMessage,
formattedVerboseMessage
];
}
// Check if the error is specifically related to React Server Components.
// If so, we'll format the error message to be more helpful.
export function getRscError(fileName, err, module, compilation, compiler) {
if (!err.message || !/NEXT_RSC_ERR_/.test(err.message)) {
return false;
}
const { isPagesDir, moduleTrace } = getModuleTrace(module, compilation, compiler);
const formattedError = formatRSCErrorMessage(err.message, isPagesDir, fileName);
const { formattedModuleTrace, lastInternalFileName, invalidImportMessage } = formatModuleTrace(compiler, moduleTrace);
const error = new SimpleWebpackError(lastInternalFileName, "ReactServerComponentsError:\n" + formattedError[0] + invalidImportMessage + formattedError[1] + formattedModuleTrace);
// Delete the stack because it's created here.
error.stack = "";
return error;
}
//# sourceMappingURL=parseRSC.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../../src/build/webpack/plugins/wellknown-errors-plugin/parseRSC.ts"],"names":["getModuleTrace","formatModuleTrace","SimpleWebpackError","formatRSCErrorMessage","message","isPagesDir","fileName","formattedMessage","formattedVerboseMessage","NEXT_RSC_ERR_REACT_API","NEXT_RSC_ERR_SERVER_IMPORT","NEXT_RSC_ERR_CLIENT_IMPORT","NEXT_RSC_ERR_CLIENT_METADATA_EXPORT","NEXT_RSC_ERR_CONFLICT_METADATA_EXPORT","NEXT_RSC_ERR_CLIENT_DIRECTIVE","NEXT_RSC_ERR_CLIENT_DIRECTIVE_PAREN","NEXT_RSC_ERR_INVALID_API","NEXT_RSC_ERR_ERROR_FILE_SERVER_COMPONENT","test","matches","match","replace","shouldAddUseClient","getRscError","err","module","compilation","compiler","moduleTrace","formattedError","formattedModuleTrace","lastInternalFileName","invalidImportMessage","error","stack"],"mappings":"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"}

View File

@@ -0,0 +1,35 @@
import Chalk from "next/dist/compiled/chalk";
import { SimpleWebpackError } from "./simpleWebpackError";
const chalk = new Chalk.constructor({
enabled: true
});
const regexScssError = /SassError: (.+)\n\s+on line (\d+) [\s\S]*?>> (.+)\n\s*(-+)\^$/m;
export function getScssError(fileName, fileContent, err) {
if (err.name !== "SassError") {
return false;
}
const res = regexScssError.exec(err.message);
if (res) {
const [, reason, _lineNumer, backupFrame, columnString] = res;
const lineNumber = Math.max(1, parseInt(_lineNumer, 10));
const column = (columnString == null ? void 0 : columnString.length) ?? 1;
let frame;
if (fileContent) {
try {
const { codeFrameColumns } = require("next/dist/compiled/babel/code-frame");
frame = codeFrameColumns(fileContent, {
start: {
line: lineNumber,
column
}
}, {
forceColor: true
});
} catch {}
}
return new SimpleWebpackError(`${chalk.cyan(fileName)}:${chalk.yellow(lineNumber.toString())}:${chalk.yellow(column.toString())}`, chalk.red.bold("Syntax error").concat(`: ${reason}\n\n${frame ?? backupFrame}`));
}
return false;
}
//# sourceMappingURL=parseScss.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../../src/build/webpack/plugins/wellknown-errors-plugin/parseScss.ts"],"names":["Chalk","SimpleWebpackError","chalk","constructor","enabled","regexScssError","getScssError","fileName","fileContent","err","name","res","exec","message","reason","_lineNumer","backupFrame","columnString","lineNumber","Math","max","parseInt","column","length","frame","codeFrameColumns","require","start","line","forceColor","cyan","yellow","toString","red","bold","concat"],"mappings":"AAAA,OAAOA,WAAW,2BAA0B;AAC5C,SAASC,kBAAkB,QAAQ,uBAAsB;AAEzD,MAAMC,QAAQ,IAAIF,MAAMG,WAAW,CAAC;IAAEC,SAAS;AAAK;AACpD,MAAMC,iBACJ;AAEF,OAAO,SAASC,aACdC,QAAgB,EAChBC,WAA0B,EAC1BC,GAAU;IAEV,IAAIA,IAAIC,IAAI,KAAK,aAAa;QAC5B,OAAO;IACT;IAEA,MAAMC,MAAMN,eAAeO,IAAI,CAACH,IAAII,OAAO;IAC3C,IAAIF,KAAK;QACP,MAAM,GAAGG,QAAQC,YAAYC,aAAaC,aAAa,GAAGN;QAC1D,MAAMO,aAAaC,KAAKC,GAAG,CAAC,GAAGC,SAASN,YAAY;QACpD,MAAMO,SAASL,CAAAA,gCAAAA,aAAcM,MAAM,KAAI;QAEvC,IAAIC;QACJ,IAAIhB,aAAa;YACf,IAAI;gBACF,MAAM,EACJiB,gBAAgB,EACjB,GAAGC,QAAQ;gBACZF,QAAQC,iBACNjB,aACA;oBAAEmB,OAAO;wBAAEC,MAAMV;wBAAYI;oBAAO;gBAAE,GACtC;oBAAEO,YAAY;gBAAK;YAEvB,EAAE,OAAM,CAAC;QACX;QAEA,OAAO,IAAI5B,mBACT,CAAC,EAAEC,MAAM4B,IAAI,CAACvB,UAAU,CAAC,EAAEL,MAAM6B,MAAM,CACrCb,WAAWc,QAAQ,IACnB,CAAC,EAAE9B,MAAM6B,MAAM,CAACT,OAAOU,QAAQ,IAAI,CAAC,EACtC9B,MAAM+B,GAAG,CACNC,IAAI,CAAC,gBACLC,MAAM,CAAC,CAAC,EAAE,EAAErB,OAAO,IAAI,EAAEU,SAASR,YAAY,CAAC;IAEtD;IAEA,OAAO;AACT"}

View File

@@ -0,0 +1,11 @@
// This class creates a simplified webpack error that formats nicely based on
// webpack's build in serializer.
// https://github.com/webpack/webpack/blob/c9d4ff7b054fc581c96ce0e53432d44f9dd8ca72/lib/Stats.js#L294-L356
export class SimpleWebpackError extends Error {
constructor(file, message){
super(message);
this.file = file;
}
}
//# sourceMappingURL=simpleWebpackError.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../../src/build/webpack/plugins/wellknown-errors-plugin/simpleWebpackError.ts"],"names":["SimpleWebpackError","Error","constructor","file","message"],"mappings":"AAEA,6EAA6E;AAC7E,iCAAiC;AACjC,0GAA0G;AAC1G,OAAO,MAAMA,2BAA4BC;IAGvCC,YAAYC,IAAY,EAAEC,OAAe,CAAE;QACzC,KAAK,CAACA;QACN,IAAI,CAACD,IAAI,GAAGA;IACd;AACF"}

View File

@@ -0,0 +1,87 @@
import { readFileSync } from "fs";
import * as path from "path";
import { getBabelError } from "./parseBabel";
import { getCssError } from "./parseCss";
import { getScssError } from "./parseScss";
import { getNotFoundError, getImageError } from "./parseNotFoundError";
import isError from "../../../../lib/is-error";
import { getRscError } from "./parseRSC";
import { getNextFontError } from "./parseNextFontError";
import { getNextAppLoaderError } from "./parseNextAppLoaderError";
import { getNextInvalidImportError } from "./parseNextInvalidImportError";
function getFileData(compilation, m) {
var _compilation_compiler;
let resolved;
let ctx = ((_compilation_compiler = compilation.compiler) == null ? void 0 : _compilation_compiler.context) ?? null;
if (ctx !== null && typeof m.resource === "string") {
const res = path.relative(ctx, m.resource).replace(/\\/g, path.posix.sep);
resolved = res.startsWith(".") ? res : `.${path.posix.sep}${res}`;
} else {
const requestShortener = compilation.requestShortener;
if (typeof (m == null ? void 0 : m.readableIdentifier) === "function") {
resolved = m.readableIdentifier(requestShortener);
} else {
resolved = m.request ?? m.userRequest;
}
}
if (resolved) {
let content = null;
try {
content = readFileSync(ctx ? path.resolve(ctx, resolved) : resolved, "utf8");
} catch {}
return [
resolved,
content
];
}
return [
"<unknown>",
null
];
}
export async function getModuleBuildError(compiler, compilation, input) {
if (!(typeof input === "object" && ((input == null ? void 0 : input.name) === "ModuleBuildError" || (input == null ? void 0 : input.name) === "ModuleNotFoundError") && Boolean(input.module) && isError(input.error))) {
return false;
}
const err = input.error;
const [sourceFilename, sourceContent] = getFileData(compilation, input.module);
const notFoundError = await getNotFoundError(compilation, input, sourceFilename, input.module);
if (notFoundError !== false) {
return notFoundError;
}
const imageError = await getImageError(compilation, input, err);
if (imageError !== false) {
return imageError;
}
const babel = getBabelError(sourceFilename, err);
if (babel !== false) {
return babel;
}
const css = getCssError(sourceFilename, err);
if (css !== false) {
return css;
}
const scss = getScssError(sourceFilename, sourceContent, err);
if (scss !== false) {
return scss;
}
const rsc = getRscError(sourceFilename, err, input.module, compilation, compiler);
if (rsc !== false) {
return rsc;
}
const nextFont = getNextFontError(err, input.module);
if (nextFont !== false) {
return nextFont;
}
const nextAppLoader = getNextAppLoaderError(err, input.module, compiler);
if (nextAppLoader !== false) {
return nextAppLoader;
}
const invalidImportError = getNextInvalidImportError(err, input.module, compilation, compiler);
if (invalidImportError !== false) {
return invalidImportError;
}
return false;
}
//# sourceMappingURL=webpackModuleError.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../../src/build/webpack/plugins/wellknown-errors-plugin/webpackModuleError.ts"],"names":["readFileSync","path","getBabelError","getCssError","getScssError","getNotFoundError","getImageError","isError","getRscError","getNextFontError","getNextAppLoaderError","getNextInvalidImportError","getFileData","compilation","m","resolved","ctx","compiler","context","resource","res","relative","replace","posix","sep","startsWith","requestShortener","readableIdentifier","request","userRequest","content","resolve","getModuleBuildError","input","name","Boolean","module","error","err","sourceFilename","sourceContent","notFoundError","imageError","babel","css","scss","rsc","nextFont","nextAppLoader","invalidImportError"],"mappings":"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"}