feat(blog): add file-based blog with dynamic slugs, MDX content and layout shell

- Introduced blog routing using Next.js App Router
- Implemented dynamic [slug] pages for blog posts
- Added MDX-based content loading via lib/posts
- Integrated shared TopBar layout with navigation
- Established clear content, lib and component separation
This commit is contained in:
PascalSchattenburg
2026-01-22 14:14:15 +01:00
parent b717952234
commit d147843c76
10412 changed files with 2475583 additions and 0 deletions

View File

@@ -0,0 +1,18 @@
import type { CustomRoutes, Rewrite } from '../../../lib/load-custom-routes';
import type { BuildManifest } from '../../../server/get-page-files';
export type ClientBuildManifest = {
[key: string]: string[];
};
export declare const srcEmptySsgManifest = "self.__SSG_MANIFEST=new Set;self.__SSG_MANIFEST_CB&&self.__SSG_MANIFEST_CB()";
export declare const processRoute: (r: Rewrite) => {
source: string;
destination: string;
basePath?: false;
locale?: false;
has?: import("../../../lib/load-custom-routes").RouteHas[];
missing?: import("../../../lib/load-custom-routes").RouteHas[];
internal?: boolean;
regex?: string;
};
export declare function normalizeRewritesForBuildManifest(rewrites: CustomRoutes['rewrites']): CustomRoutes['rewrites'];
export declare function createEdgeRuntimeManifest(originAssetMap: Partial<BuildManifest>): string;

View File

@@ -0,0 +1,79 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
0 && (module.exports = {
createEdgeRuntimeManifest: null,
normalizeRewritesForBuildManifest: null,
processRoute: null,
srcEmptySsgManifest: null
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
createEdgeRuntimeManifest: function() {
return createEdgeRuntimeManifest;
},
normalizeRewritesForBuildManifest: function() {
return normalizeRewritesForBuildManifest;
},
processRoute: function() {
return processRoute;
},
srcEmptySsgManifest: function() {
return srcEmptySsgManifest;
}
});
const srcEmptySsgManifest = `self.__SSG_MANIFEST=new Set;self.__SSG_MANIFEST_CB&&self.__SSG_MANIFEST_CB()`;
function normalizeRewrite(item) {
return {
has: item.has,
source: item.source,
destination: item.destination
};
}
const processRoute = (r)=>{
var _rewrite_destination;
const rewrite = {
...r
};
// omit external rewrite destinations since these aren't
// handled client-side
if (!(rewrite == null ? void 0 : (_rewrite_destination = rewrite.destination) == null ? void 0 : _rewrite_destination.startsWith('/'))) {
delete rewrite.destination;
}
return rewrite;
};
function normalizeRewritesForBuildManifest(rewrites) {
var _rewrites_afterFiles_map, _rewrites_afterFiles, _rewrites_beforeFiles_map, _rewrites_beforeFiles, _rewrites_fallback_map, _rewrites_fallback;
return {
afterFiles: (_rewrites_afterFiles = rewrites.afterFiles) == null ? void 0 : (_rewrites_afterFiles_map = _rewrites_afterFiles.map(processRoute)) == null ? void 0 : _rewrites_afterFiles_map.map((item)=>normalizeRewrite(item)),
beforeFiles: (_rewrites_beforeFiles = rewrites.beforeFiles) == null ? void 0 : (_rewrites_beforeFiles_map = _rewrites_beforeFiles.map(processRoute)) == null ? void 0 : _rewrites_beforeFiles_map.map((item)=>normalizeRewrite(item)),
fallback: (_rewrites_fallback = rewrites.fallback) == null ? void 0 : (_rewrites_fallback_map = _rewrites_fallback.map(processRoute)) == null ? void 0 : _rewrites_fallback_map.map((item)=>normalizeRewrite(item))
};
}
function createEdgeRuntimeManifest(originAssetMap) {
const manifestFilenames = [
'_buildManifest.js',
'_ssgManifest.js'
];
const assetMap = {
...originAssetMap,
lowPriorityFiles: []
};
// we use globalThis here because middleware can be node
// which doesn't have "self"
const manifestDefCode = `globalThis.__BUILD_MANIFEST = ${JSON.stringify(assetMap, null, 2)};\n`;
// edge lowPriorityFiles item: '"/static/" + process.env.__NEXT_BUILD_ID + "/low-priority.js"'.
// Since lowPriorityFiles is not fixed and relying on `process.env.__NEXT_BUILD_ID`, we'll produce code creating it dynamically.
const lowPriorityFilesCode = `globalThis.__BUILD_MANIFEST.lowPriorityFiles = [\n` + manifestFilenames.map((filename)=>{
return `"/static/" + process.env.__NEXT_BUILD_ID + "/${filename}"`;
}).join(',\n') + `\n];`;
return manifestDefCode + lowPriorityFilesCode;
}
//# sourceMappingURL=build-manifest-plugin-utils.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../src/build/webpack/plugins/build-manifest-plugin-utils.ts"],"sourcesContent":["import type { CustomRoutes, Rewrite } from '../../../lib/load-custom-routes'\nimport type { BuildManifest } from '../../../server/get-page-files'\n\nexport type ClientBuildManifest = {\n [key: string]: string[]\n}\n\n// Add the runtime ssg manifest file as a lazy-loaded file dependency.\n// We also stub this file out for development mode (when it is not\n// generated).\nexport const srcEmptySsgManifest = `self.__SSG_MANIFEST=new Set;self.__SSG_MANIFEST_CB&&self.__SSG_MANIFEST_CB()`\n\nfunction normalizeRewrite(item: {\n source: string\n destination: string\n has?: any\n}): CustomRoutes['rewrites']['beforeFiles'][0] {\n return {\n has: item.has,\n source: item.source,\n destination: item.destination,\n }\n}\n\nexport const processRoute = (r: Rewrite) => {\n const rewrite = { ...r }\n\n // omit external rewrite destinations since these aren't\n // handled client-side\n if (!rewrite?.destination?.startsWith('/')) {\n delete (rewrite as any).destination\n }\n return rewrite\n}\n\nexport function normalizeRewritesForBuildManifest(\n rewrites: CustomRoutes['rewrites']\n): CustomRoutes['rewrites'] {\n return {\n afterFiles: rewrites.afterFiles\n ?.map(processRoute)\n ?.map((item) => normalizeRewrite(item)),\n beforeFiles: rewrites.beforeFiles\n ?.map(processRoute)\n ?.map((item) => normalizeRewrite(item)),\n fallback: rewrites.fallback\n ?.map(processRoute)\n ?.map((item) => normalizeRewrite(item)),\n }\n}\n\nexport function createEdgeRuntimeManifest(\n originAssetMap: Partial<BuildManifest>\n): string {\n const manifestFilenames = ['_buildManifest.js', '_ssgManifest.js']\n\n const assetMap: Partial<BuildManifest> = {\n ...originAssetMap,\n lowPriorityFiles: [],\n }\n\n // we use globalThis here because middleware can be node\n // which doesn't have \"self\"\n const manifestDefCode = `globalThis.__BUILD_MANIFEST = ${JSON.stringify(\n assetMap,\n null,\n 2\n )};\\n`\n // edge lowPriorityFiles item: '\"/static/\" + process.env.__NEXT_BUILD_ID + \"/low-priority.js\"'.\n // Since lowPriorityFiles is not fixed and relying on `process.env.__NEXT_BUILD_ID`, we'll produce code creating it dynamically.\n const lowPriorityFilesCode =\n `globalThis.__BUILD_MANIFEST.lowPriorityFiles = [\\n` +\n manifestFilenames\n .map((filename) => {\n return `\"/static/\" + process.env.__NEXT_BUILD_ID + \"/${filename}\"`\n })\n .join(',\\n') +\n `\\n];`\n\n return manifestDefCode + lowPriorityFilesCode\n}\n"],"names":["createEdgeRuntimeManifest","normalizeRewritesForBuildManifest","processRoute","srcEmptySsgManifest","normalizeRewrite","item","has","source","destination","r","rewrite","startsWith","rewrites","afterFiles","map","beforeFiles","fallback","originAssetMap","manifestFilenames","assetMap","lowPriorityFiles","manifestDefCode","JSON","stringify","lowPriorityFilesCode","filename","join"],"mappings":";;;;;;;;;;;;;;;;;IAmDgBA,yBAAyB;eAAzBA;;IAhBAC,iCAAiC;eAAjCA;;IAXHC,YAAY;eAAZA;;IAdAC,mBAAmB;eAAnBA;;;AAAN,MAAMA,sBAAsB,CAAC,4EAA4E,CAAC;AAEjH,SAASC,iBAAiBC,IAIzB;IACC,OAAO;QACLC,KAAKD,KAAKC,GAAG;QACbC,QAAQF,KAAKE,MAAM;QACnBC,aAAaH,KAAKG,WAAW;IAC/B;AACF;AAEO,MAAMN,eAAe,CAACO;QAKtBC;IAJL,MAAMA,UAAU;QAAE,GAAGD,CAAC;IAAC;IAEvB,wDAAwD;IACxD,sBAAsB;IACtB,IAAI,EAACC,4BAAAA,uBAAAA,QAASF,WAAW,qBAApBE,qBAAsBC,UAAU,CAAC,OAAM;QAC1C,OAAO,AAACD,QAAgBF,WAAW;IACrC;IACA,OAAOE;AACT;AAEO,SAAST,kCACdW,QAAkC;QAGpBA,0BAAAA,sBAGCA,2BAAAA,uBAGHA,wBAAAA;IAPZ,OAAO;QACLC,UAAU,GAAED,uBAAAA,SAASC,UAAU,sBAAnBD,2BAAAA,qBACRE,GAAG,CAACZ,kCADIU,yBAERE,GAAG,CAAC,CAACT,OAASD,iBAAiBC;QACnCU,WAAW,GAAEH,wBAAAA,SAASG,WAAW,sBAApBH,4BAAAA,sBACTE,GAAG,CAACZ,kCADKU,0BAETE,GAAG,CAAC,CAACT,OAASD,iBAAiBC;QACnCW,QAAQ,GAAEJ,qBAAAA,SAASI,QAAQ,sBAAjBJ,yBAAAA,mBACNE,GAAG,CAACZ,kCADEU,uBAENE,GAAG,CAAC,CAACT,OAASD,iBAAiBC;IACrC;AACF;AAEO,SAASL,0BACdiB,cAAsC;IAEtC,MAAMC,oBAAoB;QAAC;QAAqB;KAAkB;IAElE,MAAMC,WAAmC;QACvC,GAAGF,cAAc;QACjBG,kBAAkB,EAAE;IACtB;IAEA,wDAAwD;IACxD,4BAA4B;IAC5B,MAAMC,kBAAkB,CAAC,8BAA8B,EAAEC,KAAKC,SAAS,CACrEJ,UACA,MACA,GACA,GAAG,CAAC;IACN,+FAA+F;IAC/F,gIAAgI;IAChI,MAAMK,uBACJ,CAAC,kDAAkD,CAAC,GACpDN,kBACGJ,GAAG,CAAC,CAACW;QACJ,OAAO,CAAC,6CAA6C,EAAEA,SAAS,CAAC,CAAC;IACpE,GACCC,IAAI,CAAC,SACR,CAAC,IAAI,CAAC;IAER,OAAOL,kBAAkBG;AAC3B","ignoreList":[0]}

View File

@@ -0,0 +1,25 @@
import type { BloomFilter } from '../../../shared/lib/bloom-filter';
import type { CustomRoutes } from '../../../lib/load-custom-routes';
import { webpack } from 'next/dist/compiled/webpack/webpack';
import type { BuildManifest } from '../../../server/get-page-files';
export declare function generateClientManifest(assetMap: BuildManifest, rewrites: CustomRoutes['rewrites'], clientRouterFilters?: {
staticFilter: ReturnType<BloomFilter['export']>;
dynamicFilter: ReturnType<BloomFilter['export']>;
}, compiler?: any, compilation?: any): string | undefined;
export declare function getEntrypointFiles(entrypoint: any): string[];
export default class BuildManifestPlugin {
private buildId;
private rewrites;
private isDevFallback;
private appDirEnabled;
private clientRouterFilters?;
constructor(options: {
buildId: string;
rewrites: CustomRoutes['rewrites'];
isDevFallback?: boolean;
appDirEnabled: boolean;
clientRouterFilters?: Parameters<typeof generateClientManifest>[2];
});
createAssets(compiler: any, compilation: any): void;
apply(compiler: webpack.Compiler): void;
}

View File

@@ -0,0 +1,183 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
0 && (module.exports = {
default: null,
generateClientManifest: null,
getEntrypointFiles: null
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
// 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
default: function() {
return BuildManifestPlugin;
},
generateClientManifest: function() {
return generateClientManifest;
},
getEntrypointFiles: function() {
return getEntrypointFiles;
}
});
const _devalue = /*#__PURE__*/ _interop_require_default(require("next/dist/compiled/devalue"));
const _webpack = require("next/dist/compiled/webpack/webpack");
const _constants = require("../../../shared/lib/constants");
const _getroutefromentrypoint = /*#__PURE__*/ _interop_require_default(require("../../../server/get-route-from-entrypoint"));
const _utils = require("../../../shared/lib/router/utils");
const _trace = require("../../../trace");
const _utils1 = require("../utils");
const _buildmanifestpluginutils = require("./build-manifest-plugin-utils");
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
// nodejs: '/static/<build id>/low-priority.js'
function buildNodejsLowPriorityPath(filename, buildId) {
return `${_constants.CLIENT_STATIC_FILES_PATH}/${buildId}/${filename}`;
}
function generateClientManifest(assetMap, rewrites, clientRouterFilters, compiler, compilation) {
const compilationSpan = compilation ? (0, _utils1.getCompilationSpan)(compilation) : compiler ? (0, _utils1.getCompilationSpan)(compiler) : new _trace.Span({
name: 'client-manifest'
});
const genClientManifestSpan = compilationSpan == null ? void 0 : compilationSpan.traceChild('NextJsBuildManifest-generateClientManifest');
return genClientManifestSpan == null ? void 0 : genClientManifestSpan.traceFn(()=>{
const clientManifest = {
__rewrites: (0, _buildmanifestpluginutils.normalizeRewritesForBuildManifest)(rewrites),
__routerFilterStatic: clientRouterFilters == null ? void 0 : clientRouterFilters.staticFilter,
__routerFilterDynamic: clientRouterFilters == null ? void 0 : clientRouterFilters.dynamicFilter
};
const appDependencies = new Set(assetMap.pages['/_app']);
const sortedPageKeys = (0, _utils.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 (0, _devalue.default)(clientManifest);
});
}
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, '/'))) ?? [];
}
class BuildManifestPlugin {
constructor(options){
this.buildId = options.buildId;
this.isDevFallback = !!options.isDevFallback;
this.rewrites = {
beforeFiles: [],
afterFiles: [],
fallback: []
};
this.appDirEnabled = options.appDirEnabled;
this.clientRouterFilters = options.clientRouterFilters;
this.rewrites.beforeFiles = options.rewrites.beforeFiles.map(_buildmanifestpluginutils.processRoute);
this.rewrites.afterFiles = options.rewrites.afterFiles.map(_buildmanifestpluginutils.processRoute);
this.rewrites.fallback = options.rewrites.fallback.map(_buildmanifestpluginutils.processRoute);
}
createAssets(compiler, compilation) {
const compilationSpan = (0, _utils1.getCompilationSpan)(compilation) ?? (0, _utils1.getCompilationSpan)(compiler);
if (!compilationSpan) {
throw Object.defineProperty(new Error('No span found for compilation'), "__NEXT_ERROR_CODE", {
value: "E646",
enumerable: false,
configurable: true
});
}
const createAssetsSpan = compilationSpan.traceChild('NextJsBuildManifest-createassets');
return createAssetsSpan.traceFn(()=>{
const entrypoints = compilation.entrypoints;
const assetMap = {
polyfillFiles: [],
devFiles: [],
lowPriorityFiles: [],
rootMainFiles: [],
rootMainFilesTree: {},
pages: {
'/_app': []
}
};
const mainFiles = new Set(getEntrypointFiles(entrypoints.get(_constants.CLIENT_STATIC_FILES_RUNTIME_MAIN)));
if (this.appDirEnabled) {
assetMap.rootMainFiles = [
...new Set(getEntrypointFiles(entrypoints.get(_constants.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 && _constants.CLIENT_STATIC_FILES_RUNTIME_POLYFILLS_SYMBOL in p.info;
}).map((v)=>v.name);
assetMap.devFiles = getEntrypointFiles(entrypoints.get(_constants.CLIENT_STATIC_FILES_RUNTIME_REACT_REFRESH)).filter((file)=>!mainFiles.has(file));
for (const entrypoint of compilation.entrypoints.values()){
if (_constants.SYSTEM_ENTRYPOINTS.has(entrypoint.name)) continue;
const pagePath = (0, _getroutefromentrypoint.default)(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.
const buildManifestPath = buildNodejsLowPriorityPath('_buildManifest.js', this.buildId);
const ssgManifestPath = buildNodejsLowPriorityPath('_ssgManifest.js', this.buildId);
assetMap.lowPriorityFiles.push(buildManifestPath, ssgManifestPath);
compilation.emitAsset(ssgManifestPath, new _webpack.sources.RawSource(_buildmanifestpluginutils.srcEmptySsgManifest));
}
assetMap.pages = Object.keys(assetMap.pages).sort().reduce(// eslint-disable-next-line
(a, c)=>(a[c] = assetMap.pages[c], a), {});
let buildManifestName = _constants.BUILD_MANIFEST;
if (this.isDevFallback) {
buildManifestName = `fallback-${_constants.BUILD_MANIFEST}`;
}
compilation.emitAsset(buildManifestName, new _webpack.sources.RawSource(JSON.stringify(assetMap, null, 2)));
compilation.emitAsset(`server/${_constants.MIDDLEWARE_BUILD_MANIFEST}.js`, new _webpack.sources.RawSource(`${(0, _buildmanifestpluginutils.createEdgeRuntimeManifest)(assetMap)}`));
if (!this.isDevFallback) {
compilation.emitAsset(`${_constants.CLIENT_STATIC_FILES_PATH}/${this.buildId}/_buildManifest.js`, new _webpack.sources.RawSource(`self.__BUILD_MANIFEST = ${generateClientManifest(assetMap, this.rewrites, this.clientRouterFilters, compiler, compilation)};self.__BUILD_MANIFEST_CB && self.__BUILD_MANIFEST_CB()`));
}
});
}
apply(compiler) {
compiler.hooks.make.tap('NextJsBuildManifest', (compilation)=>{
compilation.hooks.processAssets.tap({
name: 'NextJsBuildManifest',
stage: _webpack.webpack.Compilation.PROCESS_ASSETS_STAGE_ADDITIONS
}, ()=>{
this.createAssets(compiler, compilation);
});
});
return;
}
}
//# sourceMappingURL=build-manifest-plugin.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,15 @@
import { webpack } from 'next/dist/compiled/webpack/webpack';
export declare class CopyFilePlugin {
private filePath;
private name;
private cacheKey;
private info?;
constructor({ filePath, cacheKey, name, info, }: {
filePath: string;
cacheKey: string;
name: string;
minimize: boolean;
info?: object;
});
apply(compiler: webpack.Compiler): void;
}

View File

@@ -0,0 +1,67 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "CopyFilePlugin", {
enumerable: true,
get: function() {
return CopyFilePlugin;
}
});
const _fs = require("fs");
const _loaderutils3 = /*#__PURE__*/ _interop_require_default(require("next/dist/compiled/loader-utils3"));
const _webpack = require("next/dist/compiled/webpack/webpack");
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
const PLUGIN_NAME = 'CopyFilePlugin';
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.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.promises.readFile(this.filePath, 'utf8');
const file = _loaderutils3.default.interpolateName({
resourcePath: this.filePath
}, this.name, {
content,
context: compiler.context
});
const source = new _webpack.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"],"sourcesContent":["import { promises as fs } from 'fs'\nimport loaderUtils from 'next/dist/compiled/loader-utils3'\nimport { sources, webpack } from 'next/dist/compiled/webpack/webpack'\n\nconst PLUGIN_NAME = 'CopyFilePlugin'\n\nexport class CopyFilePlugin {\n private filePath: string\n private name: string\n private cacheKey: string\n private info?: object\n\n constructor({\n filePath,\n cacheKey,\n name,\n info,\n }: {\n filePath: string\n cacheKey: string\n name: string\n minimize: boolean\n info?: object\n }) {\n this.filePath = filePath\n this.cacheKey = cacheKey\n this.name = name\n this.info = info\n }\n\n apply(compiler: webpack.Compiler) {\n compiler.hooks.thisCompilation.tap(PLUGIN_NAME, (compilation: any) => {\n const cache = compilation.getCache('CopyFilePlugin')\n const hook = compilation.hooks.processAssets\n hook.tapPromise(\n {\n name: PLUGIN_NAME,\n stage: webpack.Compilation.PROCESS_ASSETS_STAGE_ADDITIONS,\n },\n async () => {\n if (cache) {\n const cachedResult = await cache.getPromise(\n this.filePath,\n this.cacheKey\n )\n if (cachedResult) {\n const { file, source } = cachedResult\n compilation.emitAsset(file, source, {\n ...this.info,\n })\n return\n }\n }\n const content = await fs.readFile(this.filePath, 'utf8')\n\n const file = loaderUtils.interpolateName(\n { resourcePath: this.filePath },\n this.name,\n { content, context: compiler.context }\n )\n\n const source = new sources.RawSource(content)\n\n if (cache) {\n await cache.storePromise(this.filePath, this.cacheKey, {\n file,\n source,\n })\n }\n\n compilation.emitAsset(file, source, {\n ...this.info,\n })\n }\n )\n })\n }\n}\n"],"names":["CopyFilePlugin","PLUGIN_NAME","constructor","filePath","cacheKey","name","info","apply","compiler","hooks","thisCompilation","tap","compilation","cache","getCache","hook","processAssets","tapPromise","stage","webpack","Compilation","PROCESS_ASSETS_STAGE_ADDITIONS","cachedResult","getPromise","file","source","emitAsset","content","fs","readFile","loaderUtils","interpolateName","resourcePath","context","sources","RawSource","storePromise"],"mappings":";;;;+BAMaA;;;eAAAA;;;oBANkB;qEACP;yBACS;;;;;;AAEjC,MAAMC,cAAc;AAEb,MAAMD;IAMXE,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,CAACV,aAAa,CAACW;YAC/C,MAAMC,QAAQD,YAAYE,QAAQ,CAAC;YACnC,MAAMC,OAAOH,YAAYH,KAAK,CAACO,aAAa;YAC5CD,KAAKE,UAAU,CACb;gBACEZ,MAAMJ;gBACNiB,OAAOC,gBAAO,CAACC,WAAW,CAACC,8BAA8B;YAC3D,GACA;gBACE,IAAIR,OAAO;oBACT,MAAMS,eAAe,MAAMT,MAAMU,UAAU,CACzC,IAAI,CAACpB,QAAQ,EACb,IAAI,CAACC,QAAQ;oBAEf,IAAIkB,cAAc;wBAChB,MAAM,EAAEE,IAAI,EAAEC,MAAM,EAAE,GAAGH;wBACzBV,YAAYc,SAAS,CAACF,MAAMC,QAAQ;4BAClC,GAAG,IAAI,CAACnB,IAAI;wBACd;wBACA;oBACF;gBACF;gBACA,MAAMqB,UAAU,MAAMC,YAAE,CAACC,QAAQ,CAAC,IAAI,CAAC1B,QAAQ,EAAE;gBAEjD,MAAMqB,OAAOM,qBAAW,CAACC,eAAe,CACtC;oBAAEC,cAAc,IAAI,CAAC7B,QAAQ;gBAAC,GAC9B,IAAI,CAACE,IAAI,EACT;oBAAEsB;oBAASM,SAASzB,SAASyB,OAAO;gBAAC;gBAGvC,MAAMR,SAAS,IAAIS,gBAAO,CAACC,SAAS,CAACR;gBAErC,IAAId,OAAO;oBACT,MAAMA,MAAMuB,YAAY,CAAC,IAAI,CAACjC,QAAQ,EAAE,IAAI,CAACC,QAAQ,EAAE;wBACrDoB;wBACAC;oBACF;gBACF;gBAEAb,YAAYc,SAAS,CAACF,MAAMC,QAAQ;oBAClC,GAAG,IAAI,CAACnB,IAAI;gBACd;YACF;QAEJ;IACF;AACF","ignoreList":[0]}

View File

@@ -0,0 +1,6 @@
import type { Compiler } from 'webpack';
export declare class CssChunkingPlugin {
private strict;
constructor(strict: boolean);
apply(compiler: Compiler): void;
}

View File

@@ -0,0 +1,277 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "CssChunkingPlugin", {
enumerable: true,
get: function() {
return CssChunkingPlugin;
}
});
const PLUGIN_NAME = 'CssChunkingPlugin';
/**
* Merge chunks until they are bigger than the target size.
*/ const MIN_CSS_CHUNK_SIZE = 30 * 1024;
/**
* Avoid merging chunks when they would be bigger than this size.
*/ const MAX_CSS_CHUNK_SIZE = 100 * 1024;
function isGlobalCss(module) {
return !/\.module\.(css|scss|sass)$/.test(module.nameForCondition() || '');
}
class CssChunkingPlugin {
constructor(strict){
this.strict = strict;
}
apply(compiler) {
const strict = this.strict;
const summary = !!process.env.CSS_CHUNKING_SUMMARY;
compiler.hooks.thisCompilation.tap(PLUGIN_NAME, (compilation)=>{
let once = false;
compilation.hooks.optimizeChunks.tap({
name: PLUGIN_NAME,
stage: 5
}, ()=>{
if (once) {
return;
}
once = true;
const chunkGraph = compilation.chunkGraph;
let changed = undefined;
const chunkStates = new Map();
const chunkStatesByModule = new Map();
// Collect all css modules in chunks and the execpted order of them
for (const chunk of compilation.chunks){
var _chunk_name;
if ((_chunk_name = chunk.name) == null ? void 0 : _chunk_name.startsWith('pages/')) continue;
const modules = [];
for (const module of chunkGraph.getChunkModulesIterable(chunk)){
var _module_type;
if (!((_module_type = module.type) == null ? void 0 : _module_type.startsWith('css'))) continue;
modules.push(module);
}
if (!modules.length) continue;
const chunkState = {
chunk,
modules,
order: 0,
requests: modules.length
};
chunkStates.set(chunk, chunkState);
for(let i = 0; i < modules.length; i++){
const module = modules[i];
let moduleChunkStates = chunkStatesByModule.get(module);
if (!moduleChunkStates) {
moduleChunkStates = new Map();
chunkStatesByModule.set(module, moduleChunkStates);
}
moduleChunkStates.set(chunkState, i);
chunkStatesByModule.set(module, moduleChunkStates);
}
}
// Sort modules by their index sum
const orderedModules = [];
for (const [module, moduleChunkStates] of chunkStatesByModule){
let sum = 0;
for (const i of moduleChunkStates.values()){
sum += i;
}
orderedModules.push({
module,
sum
});
}
orderedModules.sort((a, b)=>a.sum - b.sum);
// A queue of modules that still need to be processed
const remainingModules = new Set(orderedModules.map(({ module })=>module));
// In loose mode we guess the dependents of modules from the order
// assuming that when a module is a dependency of another module
// it will always appear before it in every chunk.
const allDependents = new Map();
if (!this.strict) {
for (const b of remainingModules){
const dependent = new Set();
loop: for (const a of remainingModules){
if (a === b) continue;
// check if a depends on b
for (const [chunkState, ia] of chunkStatesByModule.get(a)){
const bChunkStates = chunkStatesByModule.get(b);
const ib = bChunkStates.get(chunkState);
if (ib === undefined) {
continue loop;
}
if (ib > ia) {
continue loop;
}
}
dependent.add(a);
}
if (dependent.size > 0) allDependents.set(b, dependent);
}
}
// Stores the new chunk for every module
const newChunksByModule = new Map();
// Process through all modules
for (const startModule of remainingModules){
let globalCssMode = isGlobalCss(startModule);
// The current position of processing in all selected chunks
let allChunkStates = new Map(chunkStatesByModule.get(startModule));
// The list of modules that goes into the new chunk
const newChunkModules = new Set([
startModule
]);
// The current size of the new chunk
let currentSize = startModule.size();
// A pool of potential modules where the next module is selected from.
// It's filled from the next module of the selected modules in every chunk.
// It also keeps some metadata to improve performance [size, chunkStates].
const potentialNextModules = new Map();
for (const [chunkState, i] of allChunkStates){
const nextModule = chunkState.modules[i + 1];
if (nextModule && remainingModules.has(nextModule)) {
potentialNextModules.set(nextModule, [
nextModule.size(),
chunkStatesByModule.get(nextModule)
]);
}
}
// Try to add modules to the chunk until a break condition is met
let cont;
do {
cont = false;
// We try to select a module that reduces request count and
// has the highest number of requests
const orderedPotentialNextModules = [];
for (const [nextModule, [size, nextChunkStates]] of potentialNextModules){
let maxRequests = 0;
for (const chunkState of nextChunkStates.keys()){
// There is always some overlap
if (allChunkStates.has(chunkState)) {
maxRequests = Math.max(maxRequests, chunkState.requests);
}
}
orderedPotentialNextModules.push([
nextModule,
size,
nextChunkStates,
maxRequests
]);
}
orderedPotentialNextModules.sort((a, b)=>b[3] - a[3] || (a[0].identifier() < b[0].identifier() ? -1 : 1));
// Try every potential module
loop: for (const [nextModule, size, nextChunkStates] of orderedPotentialNextModules){
if (currentSize + size > MAX_CSS_CHUNK_SIZE) {
continue;
}
if (!strict) {
// In loose mode we only check if the dependencies are not violated
const dependent = allDependents.get(nextModule);
if (dependent) {
for (const dep of dependent){
if (newChunkModules.has(dep)) {
continue loop;
}
}
}
} else {
// In strict mode we check that none of the order in any chunk is changed by adding the module
for (const [chunkState, i] of nextChunkStates){
const prevState = allChunkStates.get(chunkState);
if (prevState === undefined) {
// New chunk group, can add it, but should we?
// We only add that if below min size
if (currentSize < MIN_CSS_CHUNK_SIZE) {
continue;
} else {
continue loop;
}
} else if (prevState + 1 === i) {
continue;
} else {
continue loop;
}
}
}
// Global CSS must not leak into unrelated chunks
const nextIsGlobalCss = isGlobalCss(nextModule);
if (nextIsGlobalCss && globalCssMode) {
if (allChunkStates.size !== nextChunkStates.size) {
continue;
}
}
if (globalCssMode) {
for (const chunkState of nextChunkStates.keys()){
if (!allChunkStates.has(chunkState)) {
continue loop;
}
}
}
if (nextIsGlobalCss) {
for (const chunkState of allChunkStates.keys()){
if (!nextChunkStates.has(chunkState)) {
continue loop;
}
}
}
potentialNextModules.delete(nextModule);
currentSize += size;
if (nextIsGlobalCss) {
globalCssMode = true;
}
for (const [chunkState, i] of nextChunkStates){
if (allChunkStates.has(chunkState)) {
// This reduces the request count of the chunk group
chunkState.requests--;
}
allChunkStates.set(chunkState, i);
const newNextModule = chunkState.modules[i + 1];
if (newNextModule && remainingModules.has(newNextModule) && !newChunkModules.has(newNextModule)) {
potentialNextModules.set(newNextModule, [
newNextModule.size(),
chunkStatesByModule.get(newNextModule)
]);
}
}
newChunkModules.add(nextModule);
cont = true;
break;
}
}while (cont);
const newChunk = compilation.addChunk();
newChunk.preventIntegration = true;
newChunk.idNameHints.add('css');
for (const module of newChunkModules){
remainingModules.delete(module);
chunkGraph.connectChunkAndModule(newChunk, module);
newChunksByModule.set(module, newChunk);
}
changed = true;
}
for (const { chunk, modules } of chunkStates.values()){
const chunks = new Set();
for (const module of modules){
const newChunk = newChunksByModule.get(module);
if (newChunk) {
chunkGraph.disconnectChunkAndModule(chunk, module);
if (chunks.has(newChunk)) continue;
chunks.add(newChunk);
chunk.split(newChunk);
}
}
}
if (summary) {
console.log('Top 20 chunks by request count:');
const orderedChunkStates = [
...chunkStates.values()
];
orderedChunkStates.sort((a, b)=>b.requests - a.requests);
for (const { chunk, modules, requests } of orderedChunkStates.slice(0, 20)){
console.log(`- ${requests} requests for ${chunk.name} (has ${modules.length} modules)`);
}
}
return changed;
});
});
}
}
//# sourceMappingURL=css-chunking-plugin.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,18 @@
import { webpack, sources } from 'next/dist/compiled/webpack/webpack';
type CssMinimizerPluginOptions = {
postcssOptions: {
map: false | {
prev?: string | false;
inline: boolean;
annotation: boolean;
};
};
};
export declare class CssMinimizerPlugin {
__next_css_remove: boolean;
private options;
constructor(options: CssMinimizerPluginOptions);
optimizeAsset(file: string, asset: any): Promise<sources.SourceMapSource | sources.RawSource>;
apply(compiler: webpack.Compiler): void;
}
export {};

View File

@@ -0,0 +1,92 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "CssMinimizerPlugin", {
enumerable: true,
get: function() {
return CssMinimizerPlugin;
}
});
const _cssnanosimple = /*#__PURE__*/ _interop_require_default(require("next/dist/compiled/cssnano-simple"));
const _postcssscss = /*#__PURE__*/ _interop_require_default(require("next/dist/compiled/postcss-scss"));
const _postcss = /*#__PURE__*/ _interop_require_default(require("postcss"));
const _webpack = require("next/dist/compiled/webpack/webpack");
const _utils = require("../utils");
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
// https://github.com/NMFR/optimize-css-assets-webpack-plugin/blob/0a410a9bf28c7b0e81a3470a13748e68ca2f50aa/src/index.js#L20
const CSS_REGEX = /\.css(\?.*)?$/i;
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.default
};
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 (0, _postcss.default)([
(0, _cssnanosimple.default)({
colormin: false
}, _postcss.default)
]).process(input, postcssOptions).then((res)=>{
if (res.map) {
return new _webpack.sources.SourceMapSource(res.css, file, res.map.toJSON());
} else {
return new _webpack.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.webpack.Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE_SIZE
}, async (assets)=>{
const compilationSpan = (0, _utils.getCompilationSpan)(compilation) || (0, _utils.getCompilationSpan)(compiler);
const cssMinimizerSpan = compilationSpan.traceChild('css-minimizer-plugin');
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 assetSource = compilation.getAsset(file).source;
const etag = cache.getLazyHashedEtag(assetSource);
const cachedResult = await cache.getPromise(file, etag);
assetSpan.setAttribute('cache', cachedResult ? 'HIT' : 'MISS');
if (cachedResult) {
compilation.updateAsset(file, cachedResult);
return;
}
const result = await this.optimizeAsset(file, assetSource);
await cache.storePromise(file, etag, result);
compilation.updateAsset(file, result);
});
}));
});
});
});
}
}
//# sourceMappingURL=css-minimizer-plugin.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,20 @@
import { webpack } from 'next/dist/compiled/webpack/webpack';
interface PluginOptions {
shouldIgnorePath?: (path: string) => boolean;
isSourceMapAsset?: (name: string) => boolean;
}
interface ValidatedOptions extends PluginOptions {
shouldIgnorePath: Required<PluginOptions>['shouldIgnorePath'];
isSourceMapAsset: Required<PluginOptions>['isSourceMapAsset'];
}
/**
* This plugin adds a field to source maps that identifies which sources are
* vendored or runtime-injected (aka third-party) sources. These are consumed by
* Chrome DevTools to automatically ignore-list sources.
*/
export default class DevToolsIgnorePlugin {
options: ValidatedOptions;
constructor(options?: PluginOptions);
apply(compiler: webpack.Compiler): void;
}
export {};

View File

@@ -0,0 +1,78 @@
// Source: https://github.com/mondaychen/devtools-ignore-webpack-plugin/blob/e35ce41d9606a92a455ef247f509a1c2ccab5778/src/index.ts
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, /**
* This plugin adds a field to source maps that identifies which sources are
* vendored or runtime-injected (aka third-party) sources. These are consumed by
* Chrome DevTools to automatically ignore-list sources.
*/ "default", {
enumerable: true,
get: function() {
return DevToolsIgnorePlugin;
}
});
const _webpack = require("next/dist/compiled/webpack/webpack");
// Following the naming conventions from
// https://tc39.es/source-map/#source-map-format
const IGNORE_LIST = 'ignoreList';
const PLUGIN_NAME = 'devtools-ignore-plugin';
function defaultShouldIgnorePath(path) {
return path.includes('/node_modules/') || path.includes('/webpack/');
}
function defaultIsSourceMapAsset(name) {
return name.endsWith('.map');
}
function isWebpackRuntimeModule(modulePath) {
// webpack:///webpack/bootstrap
// webpack://_N_E/webpack/
// webpack://someOtherLibrary/webpack/
return /^webpack:\/\/([^/]*)\/webpack/.test(modulePath);
}
class DevToolsIgnorePlugin {
constructor(options = {}){
this.options = {
shouldIgnorePath: options.shouldIgnorePath ?? defaultShouldIgnorePath,
isSourceMapAsset: options.isSourceMapAsset ?? defaultIsSourceMapAsset
};
}
apply(compiler) {
const { RawSource } = compiler.webpack.sources;
compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation)=>{
compilation.hooks.processAssets.tap({
name: PLUGIN_NAME,
stage: _webpack.webpack.Compilation.PROCESS_ASSETS_STAGE_DEV_TOOLING,
additionalAssets: true
}, (assets)=>{
for (const [name, asset] of Object.entries(assets)){
// Instead of using `asset.map()` to fetch the source maps from
// SourceMapSource assets, process them directly as a RawSource.
// This is because `.map()` is slow and can take several seconds.
if (!this.options.isSourceMapAsset(name)) {
continue;
}
const mapContent = asset.source().toString();
if (!mapContent) {
continue;
}
const sourcemap = JSON.parse(mapContent);
const ignoreList = [];
for (const [index, path] of sourcemap.sources.entries()){
if (this.options.shouldIgnorePath(path)) {
ignoreList.push(index);
} else if (isWebpackRuntimeModule(path)) {
// Just like our EvalSourceMapDevToolPlugin ignore-lists Webpack
// runtime by default, we do the same here.
ignoreList.push(index);
}
}
sourcemap[IGNORE_LIST] = ignoreList;
compilation.updateAsset(name, new RawSource(JSON.stringify(sourcemap)));
}
});
});
}
}
//# sourceMappingURL=devtools-ignore-list-plugin.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,20 @@
import { type webpack, type SourceMapDevToolPluginOptions } from 'next/dist/compiled/webpack/webpack';
export interface EvalSourceMapDevToolPluginOptions extends SourceMapDevToolPluginOptions {
shouldIgnorePath?: (modulePath: string) => boolean;
}
export default class EvalSourceMapDevToolPlugin {
sourceMapComment: string;
moduleFilenameTemplate: NonNullable<EvalSourceMapDevToolPluginOptions['moduleFilenameTemplate']>;
namespace: NonNullable<EvalSourceMapDevToolPluginOptions['namespace']>;
options: EvalSourceMapDevToolPluginOptions;
shouldIgnorePath: (modulePath: string) => boolean;
/**
* @param inputOptions Options object
*/
constructor(inputOptions: EvalSourceMapDevToolPluginOptions);
/**
* Apply the plugin
* @param compiler the compiler instance
*/
apply(compiler: webpack.Compiler): void;
}

View File

@@ -0,0 +1,191 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
Forked to add support for `ignoreList`.
*/ "use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, // Fork of webpack's EvalSourceMapDevToolPlugin with support for adding `ignoreList`.
// https://github.com/webpack/webpack/blob/e237b580e2bda705c5ab39973f786f7c5a7026bc/lib/EvalSourceMapDevToolPlugin.js#L37
"default", {
enumerable: true,
get: function() {
return EvalSourceMapDevToolPlugin;
}
});
const _webpack = require("next/dist/compiled/webpack/webpack");
const cache = new WeakMap();
const devtoolWarningMessage = `/*
* ATTENTION: An "eval-source-map" devtool has been used.
* This devtool is neither made for production nor for readable output files.
* It uses "eval()" calls to create a separate source file with attached SourceMaps in the browser devtools.
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
* or disable the default devtool with "devtool: false".
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
*/
`;
class EvalSourceMapDevToolPlugin {
/**
* @param inputOptions Options object
*/ constructor(inputOptions){
let options;
if (typeof inputOptions === 'string') {
options = {
append: inputOptions
};
} else {
options = inputOptions;
}
this.sourceMapComment = options.append && typeof options.append !== 'function' ? options.append : '//# sourceURL=[module]\n//# sourceMappingURL=[url]';
this.moduleFilenameTemplate = options.moduleFilenameTemplate || 'webpack://[namespace]/[resource-path]?[hash]';
this.namespace = options.namespace || '';
this.options = options;
// fork
this.shouldIgnorePath = options.shouldIgnorePath ?? (()=>false);
}
/**
* Apply the plugin
* @param compiler the compiler instance
*/ apply(compiler) {
const options = this.options;
compiler.hooks.compilation.tap('NextJSEvalSourceMapDevToolPlugin', (compilation)=>{
const { JavascriptModulesPlugin } = compiler.webpack.javascript;
const { RawSource, ConcatSource } = compiler.webpack.sources;
const devtoolWarning = new RawSource(devtoolWarningMessage);
const hooks = JavascriptModulesPlugin.getCompilationHooks(compilation);
new _webpack.SourceMapDevToolModuleOptionsPlugin(options).apply(compilation);
const matchModule = _webpack.ModuleFilenameHelpers.matchObject.bind(_webpack.ModuleFilenameHelpers, options);
hooks.renderModuleContent.tap('NextJSEvalSourceMapDevToolPlugin', (source, m, { chunk, runtimeTemplate, chunkGraph })=>{
const cachedSource = cache.get(source);
if (cachedSource !== undefined) {
return cachedSource;
}
const result = (r)=>{
cache.set(source, r);
return r;
};
if (m instanceof _webpack.NormalModule) {
const module = m;
if (!matchModule(module.resource)) {
return result(source);
}
} else if (m instanceof _webpack.ConcatenatedModule) {
const concatModule = m;
if (concatModule.rootModule instanceof _webpack.NormalModule) {
const module = concatModule.rootModule;
if (!matchModule(module.resource)) {
return result(source);
}
} else {
return result(source);
}
} else {
return result(source);
}
const namespace = compilation.getPath(this.namespace, {
chunk
});
let sourceMap;
let content;
if (source.sourceAndMap) {
const sourceAndMap = source.sourceAndMap(options);
sourceMap = sourceAndMap.map;
content = sourceAndMap.source;
} else {
sourceMap = source.map(options);
content = source.source();
}
if (!sourceMap) {
return result(source);
}
// Clone (flat) the sourcemap to ensure that the mutations below do not persist.
sourceMap = {
...sourceMap
};
const context = compiler.options.context;
const root = compiler.root;
const modules = sourceMap.sources.map((sourceMapSource)=>{
if (!sourceMapSource.startsWith('webpack://')) return sourceMapSource;
sourceMapSource = (0, _webpack.makePathsAbsolute)(context, sourceMapSource.slice(10), root);
const module = compilation.findModule(sourceMapSource);
return module || sourceMapSource;
});
let moduleFilenames = modules.map((module)=>_webpack.ModuleFilenameHelpers.createFilename(module, {
moduleFilenameTemplate: this.moduleFilenameTemplate,
namespace
}, {
requestShortener: runtimeTemplate.requestShortener,
chunkGraph,
hashFunction: compilation.outputOptions.hashFunction
}));
moduleFilenames = _webpack.ModuleFilenameHelpers.replaceDuplicates(moduleFilenames, (filename, _i, n)=>{
for(let j = 0; j < n; j++)filename += '*';
return filename;
});
sourceMap.sources = moduleFilenames;
sourceMap.ignoreList = [];
for(let index = 0; index < moduleFilenames.length; index++){
if (this.shouldIgnorePath(moduleFilenames[index])) {
sourceMap.ignoreList.push(index);
}
}
if (options.noSources) {
sourceMap.sourcesContent = undefined;
}
sourceMap.sourceRoot = options.sourceRoot || '';
const moduleId = chunkGraph.getModuleId(m);
if (moduleId) {
sourceMap.file = typeof moduleId === 'number' ? `${moduleId}.js` : moduleId;
}
const footer = `${this.sourceMapComment.replace(/\[url\]/g, `data:application/json;charset=utf-8;base64,${Buffer.from(JSON.stringify(sourceMap), 'utf8').toString('base64')}`)}\n//# sourceURL=webpack-internal:///${moduleId}\n` // workaround for chrome bug
;
return result(new RawSource(`eval(${compilation.outputOptions.trustedTypes ? `${_webpack.RuntimeGlobals.createScript}(${JSON.stringify(content + footer)})` : JSON.stringify(content + footer)});`));
});
hooks.inlineInRuntimeBailout.tap('EvalDevToolModulePlugin', ()=>'the eval-source-map devtool is used.');
hooks.render.tap('EvalSourceMapDevToolPlugin', (source, context)=>{
if (context.chunk.id === 'webpack' || context.chunk.id === 'webpack-runtime') {
const sourceURL = new URL('webpack-internal://nextjs/' + context.chunk.id + '.js');
// Webpack runtime chunks are not sourcemapped.
// We insert a dummy source map that ignore-lists everything.
// The mappings will be incorrect but end-users will almost never interact
// with the webpack runtime. Users who do, can follow the instructions
// in the sources content and disable sourcemaps in their debugger.
const sourceMappingURL = new URL('data:application/json;charset=utf-8;base64,' + Buffer.from(JSON.stringify({
version: 3,
ignoreList: [
0
],
// Minimal, parseable mappings.
mappings: 'AAAA',
sources: [
// TODO: This should be the original source URL so that CTRL+Click works in the terminal.
sourceURL.toString()
],
sourcesContent: [
'' + '// This source was generated by Next.js based off of the generated Webpack runtime.\n' + '// The mappings are incorrect.\n' + '// To get the correct line/column mappings, turn off sourcemaps in your debugger.\n' + '\n' + source.source()
]
})).toString('base64'));
return new ConcatSource(source, new RawSource('\n//# sourceMappingURL=' + sourceMappingURL + // Webpack will add a trailing semicolon. Adding a newline
// ensures the semicolon is not part of the sourceURL and actually
// terminates the previous statement.
'\n'));
} else {
return new ConcatSource(devtoolWarning, source);
}
});
hooks.chunkHash.tap('EvalSourceMapDevToolPlugin', (_chunk, hash)=>{
hash.update('EvalSourceMapDevToolPlugin');
hash.update('2');
});
if (compilation.outputOptions.trustedTypes) {
compilation.hooks.additionalModuleRuntimeRequirements.tap('EvalSourceMapDevToolPlugin', (_module, set, _context)=>{
set.add(_webpack.RuntimeGlobals.createScript);
});
}
});
}
}
//# sourceMappingURL=eval-source-map-dev-tool-plugin.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,87 @@
import type { CssImports, ClientComponentImports } from '../loaders/next-flight-client-entry-loader';
import { webpack } from 'next/dist/compiled/webpack/webpack';
interface Options {
dev: boolean;
appDir: string;
isEdgeServer: boolean;
encryptionKey: string;
}
type Actions = {
[actionId: string]: {
exportedName?: string;
filename?: string;
workers: {
[name: string]: {
moduleId: string | number;
async: boolean;
};
};
layer: {
[name: string]: string;
};
};
};
type ActionIdNamePair = {
id: string;
exportedName?: string;
filename?: string;
};
export type ActionManifest = {
encryptionKey: string;
node: Actions;
edge: Actions;
};
export interface ModuleInfo {
moduleId: string | number;
async: boolean;
}
export declare class FlightClientEntryPlugin {
dev: boolean;
appDir: string;
projectDir: string;
encryptionKey: string;
isEdgeServer: boolean;
assetPrefix: string;
webpackRuntime: string;
constructor(options: Options);
apply(compiler: webpack.Compiler): void;
createClientEntries(compiler: webpack.Compiler, compilation: webpack.Compilation): Promise<void>;
collectClientActionsFromDependencies({ compilation, dependencies, }: {
compilation: webpack.Compilation;
dependencies: ReturnType<typeof webpack.EntryPlugin.createDependency>[];
}): Map<string, ActionIdNamePair[]>;
collectComponentInfoFromServerEntryDependency({ entryRequest, compilation, resolvedModule, }: {
entryRequest: string;
compilation: webpack.Compilation;
resolvedModule: any;
}): {
cssImports: CssImports;
clientComponentImports: ClientComponentImports;
actionImports: [string, ActionIdNamePair[]][];
};
injectClientEntryAndSSRModules({ compiler, compilation, entryName, clientImports, bundlePath, absolutePagePath, }: {
compiler: webpack.Compiler;
compilation: webpack.Compilation;
entryName: string;
clientImports: ClientComponentImports;
bundlePath: string;
absolutePagePath?: string;
}): [
shouldInvalidate: boolean,
addSSREntryPromise: Promise<void>,
addRSCEntryPromise: Promise<void>,
ssrDep: ReturnType<typeof webpack.EntryPlugin.createDependency>
];
injectActionEntry({ compiler, compilation, actions, entryName, bundlePath, fromClient, createdActionIds, }: {
compiler: webpack.Compiler;
compilation: webpack.Compilation;
actions: Map<string, ActionIdNamePair[]>;
entryName: string;
bundlePath: string;
createdActionIds: Set<string>;
fromClient?: boolean;
}): Promise<any>;
addEntry(compilation: webpack.Compilation, context: string, dependency: webpack.Dependency, options: webpack.EntryOptions): Promise<any>;
createActionAssets(compilation: webpack.Compilation): Promise<void>;
}
export {};

View File

@@ -0,0 +1,793 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "FlightClientEntryPlugin", {
enumerable: true,
get: function() {
return FlightClientEntryPlugin;
}
});
const _webpack = require("next/dist/compiled/webpack/webpack");
const _querystring = require("querystring");
const _path = /*#__PURE__*/ _interop_require_default(require("path"));
const _ondemandentryhandler = require("../../../server/dev/on-demand-entry-handler");
const _constants = require("../../../lib/constants");
const _constants1 = require("../../../shared/lib/constants");
const _entryconstants = require("../../../shared/lib/entry-constants");
const _utils = require("../loaders/utils");
const _utils1 = require("../utils");
const _normalizepathsep = require("../../../shared/lib/page-path/normalize-path-sep");
const _buildcontext = require("../../build-context");
const _pagetypes = require("../../../lib/page-types");
const _getmodulebuildinfo = require("../loaders/get-module-build-info");
const _nextflightloader = require("../loaders/next-flight-loader");
const _isapprouteroute = require("../../../lib/is-app-route-route");
const _ismetadataroute = require("../../../lib/metadata/is-metadata-route");
const _getwebpackbundler = /*#__PURE__*/ _interop_require_default(require("../../../shared/lib/get-webpack-bundler"));
const _utils2 = require("../../utils");
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
const PLUGIN_NAME = 'FlightClientEntryPlugin';
const pluginState = (0, _buildcontext.getProxiedPluginState)({
// A map to track "action" -> "list of bundles".
serverActions: {},
edgeServerActions: {},
serverActionModules: {},
edgeServerActionModules: {},
ssrModules: {},
edgeSsrModules: {},
rscModules: {},
edgeRscModules: {},
injectedClientEntries: {}
});
const POSSIBLE_SHARED_CONVENTIONS = [
'template',
'layout'
];
const STANDALONE_BUNDLE_CONVENTION = 'global-not-found';
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.default.parse(aPath).name;
const bName = _path.default.parse(bPath).name;
const indexA = POSSIBLE_SHARED_CONVENTIONS.indexOf(aName);
const indexB = POSSIBLE_SHARED_CONVENTIONS.indexOf(bName);
if (indexA === -1) return 1;
if (indexB === -1) return -1;
return indexA - indexB;
});
const dedupedCSSImports = {};
const trackedCSSImports = new Set();
for (const [entryFilePath, cssImports] of sortedCSSImports){
const entryConventionName = _path.default.parse(entryFilePath).name;
for (const cssImport of cssImports){
// If the CSS import is already tracked, we can skip it.
// Or if it's any standalone entry such as `global-not-found`, it won't share any resources with other entry, skip it.
if (trackedCSSImports.has(cssImport) && STANDALONE_BUNDLE_CONVENTION !== entryConventionName) {
continue;
}
// Only track CSS imports that are in files that can inherit CSS.
if (POSSIBLE_SHARED_CONVENTIONS.includes(entryConventionName)) {
trackedCSSImports.add(cssImport);
}
if (!dedupedCSSImports[entryFilePath]) {
dedupedCSSImports[entryFilePath] = [];
}
dedupedCSSImports[entryFilePath].push(cssImport);
}
}
return dedupedCSSImports;
}
class FlightClientEntryPlugin {
constructor(options){
this.dev = options.dev;
this.appDir = options.appDir;
this.projectDir = _path.default.join(options.appDir, '..');
this.isEdgeServer = options.isEdgeServer;
this.assetPrefix = !this.dev && !this.isEdgeServer ? '../' : '';
this.encryptionKey = options.encryptionKey;
this.webpackRuntime = this.isEdgeServer ? _constants1.EDGE_RUNTIME_WEBPACK : _constants1.DEFAULT_RUNTIME_WEBPACK;
}
apply(compiler) {
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 necessary to add it for matchResource or mod.resourceResolveData
const modResource = modPath ? modPath.startsWith(_constants1.BARREL_OPTIMIZATION_PREFIX) ? (0, _utils1.formatBarrelOptimizedResource)(mod.resource, modPath) : modPath + modQuery : mod.resource;
if (typeof modId !== 'undefined' && modResource) {
if (mod.layer === _constants.WEBPACK_LAYERS.reactServerComponents) {
const key = _path.default.relative(compiler.context, modResource).replace(/\/next\/dist\/esm\//, '/next/dist/');
const moduleInfo = {
moduleId: modId,
async: compilation.moduleGraph.isAsync(mod)
};
if (this.isEdgeServer) {
pluginState.edgeRscModules[key] = moduleInfo;
} else {
pluginState.rscModules[key] = moduleInfo;
}
}
}
if (mod.layer !== _constants.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.default.relative(compiler.context, modResource);
if (!ssrNamedModuleId.startsWith('.')) {
// TODO use getModuleId instead
ssrNamedModuleId = `./${(0, _normalizepathsep.normalizePathSep)(ssrNamedModuleId)}`;
}
const moduleInfo = {
moduleId: modId,
async: compilation.moduleGraph.isAsync(mod)
};
if (this.isEdgeServer) {
pluginState.edgeSsrModules[ssrNamedModuleId.replace(/\/next\/dist\/esm\//, '/next/dist/')] = moduleInfo;
} else {
pluginState.ssrModules[ssrNamedModuleId] = moduleInfo;
}
}
};
(0, _utils1.traverseModules)(compilation, (mod, _chunk, _chunkGroup, modId)=>{
if (modId) recordModule(modId, mod);
});
});
compiler.hooks.make.tap(PLUGIN_NAME, (compilation)=>{
compilation.hooks.processAssets.tapPromise({
name: PLUGIN_NAME,
stage: _webpack.webpack.Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE_HASH
}, ()=>this.createActionAssets(compilation));
});
}
async createClientEntries(compiler, compilation) {
const addClientEntryAndSSRModulesList = [];
const createdSSRDependenciesForEntry = {};
const addActionEntryList = [];
const actionMapsPerEntry = {};
const createdActionIds = new Set();
// For each SC server compilation entry, we need to create its corresponding
// client component entry.
(0, _utils1.forEachEntryModule)(compilation, ({ name, entryModule })=>{
const internalClientComponentEntryImports = {};
const actionEntryImports = new Map();
const clientEntriesToInject = [];
const mergedCSSimports = {};
const moduleReferences = (0, _utils1.getModuleReferencesInOrder)(entryModule, compilation.moduleGraph);
for (const connection of moduleReferences){
// Entry can be any user defined entry files such as layout, page, error, loading, etc.
let entryRequest = connection.dependency.request;
if (entryRequest.endsWith(_constants.WEBPACK_RESOURCE_QUERIES.metadataRoute)) {
const { filePath, isDynamicRouteExtension } = getMetadataRouteResource(entryRequest);
if (isDynamicRouteExtension === '1') {
entryRequest = filePath;
}
}
const { clientComponentImports, actionImports, cssImports } = this.collectComponentInfoFromServerEntryDependency({
entryRequest,
compilation,
resolvedModule: connection.resolvedModule
});
actionImports.forEach(([dep, actions])=>actionEntryImports.set(dep, actions));
const isAbsoluteRequest = _path.default.isAbsolute(entryRequest);
const isAppRouterBuiltinPage = (0, _utils2.isAppBuiltinPage)(entryRequest);
// Next.js internals are put into a separate entry.
if (!isAbsoluteRequest) {
Object.keys(clientComponentImports).forEach((value)=>internalClientComponentEntryImports[value] = new Set());
if (!isAppRouterBuiltinPage) {
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 && !isAppRouterBuiltinPage ? _path.default.relative(compilation.options.context, entryRequest) : entryRequest;
// Replace file suffix as `.js` will be added.
// bundlePath will have app/ prefix but not src/.
// e.g. src/app/foo/page.js -> app/foo/page
let bundlePath = (0, _normalizepathsep.normalizePathSep)(relativeRequest.replace(/\.[^.\\/]+$/, '').replace(/^src[\\/]/, ''));
// For metadata routes, the entry name can be used as the bundle path,
// as it has been normalized already.
// e.g.
// When `relativeRequest` is 'src/app/sitemap.js',
// `appDirRelativeRequest` will be '/sitemap.js'
// then `isMetadataEntryFile` will be `true`
const appDirRelativeRequest = relativeRequest.replace(/^src[\\/]/, '').replace(/^app[\\/]/, '/');
const isMetadataEntryFile = (0, _ismetadataroute.isMetadataRouteFile)(appDirRelativeRequest, _ismetadataroute.DEFAULT_METADATA_ROUTE_EXTENSIONS, true);
if (isMetadataEntryFile) {
bundlePath = name;
}
Object.assign(mergedCSSimports, cssImports);
clientEntriesToInject.push({
compiler,
compilation,
entryName: name,
clientComponentImports,
bundlePath,
absolutePagePath: entryRequest
});
// The webpack implementation of writing the client reference manifest relies on all entrypoints writing a page.js even when there is no client components in the page.
// It needs the file in order to write the reference manifest for the path in the `.next/server` folder.
// TODO-APP: This could be better handled, however Turbopack does not have the same problem as we resolve client components in a single graph.
if (name === `app${_entryconstants.UNDERSCORE_NOT_FOUND_ROUTE_ENTRY}` && bundlePath === 'app/not-found') {
clientEntriesToInject.push({
compiler,
compilation,
entryName: name,
clientComponentImports: {},
bundlePath: `app${_entryconstants.UNDERSCORE_NOT_FOUND_ROUTE_ENTRY}`,
absolutePagePath: entryRequest
});
}
if (name === `app${_entryconstants.UNDERSCORE_NOT_FOUND_ROUTE_ENTRY}` && bundlePath === 'app/global-not-found') {
clientEntriesToInject.push({
compiler,
compilation,
entryName: name,
clientComponentImports,
bundlePath: `app${_entryconstants.UNDERSCORE_NOT_FOUND_ROUTE_ENTRY}`,
absolutePagePath: entryRequest
});
}
if (name === `app${_entryconstants.UNDERSCORE_GLOBAL_ERROR_ROUTE_ENTRY}`) {
clientEntriesToInject.push({
compiler,
compilation,
entryName: name,
clientComponentImports,
bundlePath: `app${_entryconstants.UNDERSCORE_GLOBAL_ERROR_ROUTE_ENTRY}`,
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] || []).reduce((res, curr)=>{
res[curr] = new Set();
return res;
}, {})
}
});
// Track all created SSR dependencies for each entry from the server layer.
if (!createdSSRDependenciesForEntry[clientEntryToInject.entryName]) {
createdSSRDependenciesForEntry[clientEntryToInject.entryName] = [];
}
createdSSRDependenciesForEntry[clientEntryToInject.entryName].push(injected[3]);
addClientEntryAndSSRModulesList.push(injected);
}
if (!(0, _isapprouteroute.isAppRouteRoute)(name)) {
// Create internal app
addClientEntryAndSSRModulesList.push(this.injectClientEntryAndSSRModules({
compiler,
compilation,
entryName: name,
clientImports: {
...internalClientComponentEntryImports
},
bundlePath: _constants1.APP_CLIENT_INTERNALS
}));
}
if (actionEntryImports.size > 0) {
if (!actionMapsPerEntry[name]) {
actionMapsPerEntry[name] = new Map();
}
actionMapsPerEntry[name] = new Map([
...actionMapsPerEntry[name],
...actionEntryImports
]);
}
});
for (const [name, actionEntryImports] of Object.entries(actionMapsPerEntry)){
addActionEntryList.push(this.injectActionEntry({
compiler,
compilation,
actions: actionEntryImports,
entryName: name,
bundlePath: name,
createdActionIds
}));
}
// Invalidate in development to trigger recompilation
const invalidator = (0, _ondemandentryhandler.getInvalidator)(compiler.outputPath);
// Check if any of the entry injections need an invalidation
if (invalidator && addClientEntryAndSSRModulesList.some(([shouldInvalidate])=>shouldInvalidate === true)) {
invalidator.invalidate([
_constants1.COMPILER_NAMES.client
]);
}
// Client compiler is invalidated before awaiting the compilation of the SSR
// and RSC client component entries so that the client compiler is running
// in parallel to the server compiler.
await Promise.all(addClientEntryAndSSRModulesList.flatMap((addClientEntryAndSSRModules)=>[
addClientEntryAndSSRModules[1],
addClientEntryAndSSRModules[2]
]));
// Wait for action entries to be added.
await Promise.all(addActionEntryList);
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, ssrEntryDependencies] of Object.entries(createdSSRDependenciesForEntry)){
// Collect from all entries, e.g. layout.js, page.js, loading.js, ...
// add aggregate them.
const actionEntryImports = this.collectClientActionsFromDependencies({
compilation,
dependencies: ssrEntryDependencies
});
if (actionEntryImports.size > 0) {
if (!actionMapsPerClientEntry[name]) {
actionMapsPerClientEntry[name] = new Map();
}
actionMapsPerClientEntry[name] = new Map([
...actionMapsPerClientEntry[name],
...actionEntryImports
]);
}
}
for (const [entryName, 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, actions] of actionEntryImports){
const remainingActionNames = [];
for (const action of actions){
if (!createdActionIds.has(entryName + '@' + action.id)) {
remainingActionNames.push(action);
}
}
if (remainingActionNames.length > 0) {
remainingActionEntryImports.set(dep, remainingActionNames);
remainingClientImportedActions = true;
}
}
if (remainingClientImportedActions) {
addedClientActionEntryList.push(this.injectActionEntry({
compiler,
compilation,
actions: remainingActionEntryImports,
entryName,
bundlePath: entryName,
fromClient: true,
createdActionIds
}));
}
}
await Promise.all(addedClientActionEntryList);
}
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 _getModuleBuildInfo_rsc;
if (!mod) return;
const modResource = getModuleResource(mod);
if (!modResource) return;
if (visitedModule.has(modResource)) return;
visitedModule.add(modResource);
const actionIds = (_getModuleBuildInfo_rsc = (0, _getmodulebuildinfo.getModuleBuildInfo)(mod).rsc) == null ? void 0 : _getModuleBuildInfo_rsc.actionIds;
if (actionIds) {
collectedActions.set(modResource, Object.entries(actionIds).map(([id, exportedName])=>({
id,
exportedName,
filename: _path.default.posix.relative(this.projectDir, modResource)
})));
}
// Collect used exported actions transversely.
(0, _utils1.getModuleReferencesInOrder)(mod, compilation.moduleGraph).forEach((connection)=>{
collectActionsInDep(connection.resolvedModule);
});
};
// Don't traverse the module graph anymore once hitting the action layer.
if (entryRequest && !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 (0, _utils1.getModuleReferencesInOrder)(ssrEntryModule, compilation.moduleGraph)){
const depModule = connection.dependency;
const request = depModule.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 visitedOfClientComponentsTraverse = new Set();
// Info to collect.
const clientComponentImports = {};
const actionImports = [];
const CSSImports = new Set();
const filterClientComponents = (mod, importedIdentifiers)=>{
var _getModuleBuildInfo_rsc;
if (!mod) return;
const modResource = getModuleResource(mod);
if (!modResource) return;
if (visitedOfClientComponentsTraverse.has(modResource)) {
if (clientComponentImports[modResource]) {
addClientImport(mod, modResource, clientComponentImports, importedIdentifiers, false);
}
return;
}
visitedOfClientComponentsTraverse.add(modResource);
const actionIds = (_getModuleBuildInfo_rsc = (0, _getmodulebuildinfo.getModuleBuildInfo)(mod).rsc) == null ? void 0 : _getModuleBuildInfo_rsc.actionIds;
if (actionIds) {
actionImports.push([
modResource,
Object.entries(actionIds).map(([id, exportedName])=>({
id,
exportedName,
filename: _path.default.posix.relative(this.projectDir, modResource)
}))
]);
}
if ((0, _utils.isCSSMod)(mod)) {
const sideEffectFree = mod.factoryMeta && mod.factoryMeta.sideEffectFree;
if (sideEffectFree) {
const unused = !compilation.moduleGraph.getExportsInfo(mod).isModuleUsed(this.webpackRuntime);
if (unused) return;
}
CSSImports.add(modResource);
} else if ((0, _utils.isClientComponentEntryModule)(mod)) {
if (!clientComponentImports[modResource]) {
clientComponentImports[modResource] = new Set();
}
addClientImport(mod, modResource, clientComponentImports, importedIdentifiers, true);
return;
}
(0, _utils1.getModuleReferencesInOrder)(mod, compilation.moduleGraph).forEach((connection)=>{
var _connection_dependency;
let dependencyIds = [];
// `ids` are the identifiers that are imported from the dependency,
// if it's present, it's an array of strings.
if ((_connection_dependency = connection.dependency) == null ? void 0 : _connection_dependency.ids) {
dependencyIds.push(...connection.dependency.ids);
} else {
dependencyIds = [
'*'
];
}
filterClientComponents(connection.resolvedModule, dependencyIds);
});
};
// 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 }) {
const bundler = (0, _getwebpackbundler.default)();
let shouldInvalidate = false;
const modules = Object.keys(clientImports).sort((a, b)=>_utils.regexCSS.test(b) ? 1 : a.localeCompare(b)).map((clientImportPath)=>({
request: clientImportPath,
ids: [
...clientImports[clientImportPath]
]
}));
// 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 clientBrowserLoader = `next-flight-client-entry-loader?${(0, _querystring.stringify)({
modules: (this.isEdgeServer ? modules.map(({ request, ids })=>({
request: request.replace(/[\\/]next[\\/]dist[\\/]esm[\\/]/, '/next/dist/'.replace(/\//g, _path.default.sep)),
ids
})) : modules).map((x)=>JSON.stringify(x)),
server: false
})}!`;
const clientServerLoader = `next-flight-client-entry-loader?${(0, _querystring.stringify)({
modules: modules.map((x)=>JSON.stringify(x)),
server: true
})}!`;
// Add for the client compilation
// Inject the entry to the client compiler.
if (this.dev) {
const entries = (0, _ondemandentryhandler.getEntries)(compiler.outputPath);
const pageKey = (0, _ondemandentryhandler.getEntryKey)(_constants1.COMPILER_NAMES.client, _pagetypes.PAGE_TYPES.APP, bundlePath);
if (!entries[pageKey]) {
entries[pageKey] = {
type: _ondemandentryhandler.EntryTypes.CHILD_ENTRY,
parentEntries: new Set([
entryName
]),
absoluteEntryFilePath: absolutePagePath,
bundlePath,
request: clientBrowserLoader,
dispose: false,
lastActiveTime: Date.now()
};
shouldInvalidate = true;
} else {
const entryData = entries[pageKey];
// New version of the client loader
if (entryData.request !== clientBrowserLoader) {
entryData.request = clientBrowserLoader;
shouldInvalidate = true;
}
if (entryData.type === _ondemandentryhandler.EntryTypes.CHILD_ENTRY) {
entryData.parentEntries.add(entryName);
}
entryData.dispose = false;
entryData.lastActiveTime = Date.now();
}
} else {
pluginState.injectedClientEntries[bundlePath] = clientBrowserLoader;
}
const clientComponentSSREntryDep = bundler.EntryPlugin.createDependency(clientServerLoader, {
name: bundlePath
});
const clientComponentRSCEntryDep = bundler.EntryPlugin.createDependency(clientServerLoader, {
name: bundlePath
});
return [
shouldInvalidate,
// Add the entries to the server compiler for the SSR and RSC layers. The
// promises are awaited later using `Promise.all` in order to parallelize
// adding the entries.
this.addEntry(compilation, compiler.context, clientComponentSSREntryDep, {
name: entryName,
layer: _constants.WEBPACK_LAYERS.serverSideRendering
}),
this.addEntry(compilation, compiler.context, clientComponentRSCEntryDep, {
name: entryName,
layer: _constants.WEBPACK_LAYERS.reactServerComponents
}),
clientComponentSSREntryDep
];
}
injectActionEntry({ compiler, compilation, actions, entryName, bundlePath, fromClient, createdActionIds }) {
const bundler = (0, _getwebpackbundler.default)();
const actionsArray = Array.from(actions.entries());
for (const [, actionsFromModule] of actions){
for (const { id } of actionsFromModule){
createdActionIds.add(entryName + '@' + id);
}
}
if (actionsArray.length === 0) {
return Promise.resolve();
}
const actionLoader = `next-flight-action-entry-loader?${(0, _querystring.stringify)({
actions: JSON.stringify(actionsArray),
__client_imported__: fromClient
})}!`;
const currentCompilerServerActions = this.isEdgeServer ? pluginState.edgeServerActions : pluginState.serverActions;
for (const [, actionsFromModule] of actionsArray){
for (const { id, exportedName, filename } of actionsFromModule){
if (typeof currentCompilerServerActions[id] === 'undefined') {
currentCompilerServerActions[id] = {
workers: {},
layer: {},
filename,
exportedName
};
}
currentCompilerServerActions[id].workers[bundlePath] = {
moduleId: '',
async: false
};
currentCompilerServerActions[id].layer[bundlePath] = fromClient ? _constants.WEBPACK_LAYERS.actionBrowser : _constants.WEBPACK_LAYERS.reactServerComponents;
}
}
// Inject the entry to the server compiler
const actionEntryDep = bundler.EntryPlugin.createDependency(actionLoader, {
name: bundlePath
});
return this.addEntry(compilation, // Reuse compilation context.
compiler.context, actionEntryDep, {
name: entryName,
layer: fromClient ? _constants.WEBPACK_LAYERS.actionBrowser : _constants.WEBPACK_LAYERS.reactServerComponents
});
}
addEntry(compilation, context, dependency, options) /* Promise<module> */ {
return new Promise((resolve, reject)=>{
if ('rspack' in compilation.compiler) {
compilation.addInclude(context, dependency, options, (err, module)=>{
if (err) {
return reject(err);
}
compilation.moduleGraph.getExportsInfo(module).setUsedInUnknownWay(this.isEdgeServer ? _constants1.EDGE_RUNTIME_WEBPACK : _constants1.DEFAULT_RUNTIME_WEBPACK);
return resolve(module);
});
} else {
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);
compilation.moduleGraph.getExportsInfo(module).setUsedInUnknownWay(this.isEdgeServer ? _constants1.EDGE_RUNTIME_WEBPACK : _constants1.DEFAULT_RUNTIME_WEBPACK);
return resolve(module);
});
}
});
}
async createActionAssets(compilation) {
const serverActions = {};
const edgeServerActions = {};
(0, _utils1.traverseModules)(compilation, (mod, _chunk, chunkGroup, modId)=>{
// Go through all action entries and record the module ID for each entry.
if (chunkGroup.name && mod.request && modId && /next-flight-action-entry-loader/.test(mod.request)) {
const fromClient = /&__client_imported__=true/.test(mod.request);
const mapping = this.isEdgeServer ? pluginState.edgeServerActionModules : pluginState.serverActionModules;
if (!mapping[chunkGroup.name]) {
mapping[chunkGroup.name] = {};
}
mapping[chunkGroup.name][fromClient ? 'client' : 'server'] = {
moduleId: modId,
async: compilation.moduleGraph.isAsync(mod)
};
}
});
for(let id in pluginState.serverActions){
const action = pluginState.serverActions[id];
for(let name in action.workers){
const modId = pluginState.serverActionModules[name][action.layer[name] === _constants.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.edgeServerActionModules[name][action.layer[name] === _constants.WEBPACK_LAYERS.actionBrowser ? 'client' : 'server'];
action.workers[name] = modId;
}
edgeServerActions[id] = action;
}
const serverManifest = {
node: serverActions,
edge: edgeServerActions,
encryptionKey: this.encryptionKey
};
const edgeServerManifest = {
...serverManifest,
encryptionKey: 'process.env.NEXT_SERVER_ACTIONS_ENCRYPTION_KEY'
};
const json = JSON.stringify(serverManifest, null, this.dev ? 2 : undefined);
const edgeJson = JSON.stringify(edgeServerManifest, null, this.dev ? 2 : undefined);
compilation.emitAsset(`${this.assetPrefix}${_constants1.SERVER_REFERENCE_MANIFEST}.js`, new _webpack.sources.RawSource(`self.__RSC_SERVER_MANIFEST=${JSON.stringify(edgeJson)}`));
compilation.emitAsset(`${this.assetPrefix}${_constants1.SERVER_REFERENCE_MANIFEST}.json`, new _webpack.sources.RawSource(json));
}
}
function addClientImport(mod, modRequest, clientComponentImports, importedIdentifiers, isFirstVisitModule) {
var _getModuleBuildInfo_rsc;
const clientEntryType = (_getModuleBuildInfo_rsc = (0, _getmodulebuildinfo.getModuleBuildInfo)(mod).rsc) == null ? void 0 : _getModuleBuildInfo_rsc.clientEntryType;
const isCjsModule = clientEntryType === 'cjs';
const assumedSourceType = (0, _nextflightloader.getAssumedSourceType)(mod, isCjsModule ? 'commonjs' : 'auto');
const clientImportsSet = clientComponentImports[modRequest];
if (importedIdentifiers[0] === '*') {
// If there's collected import path with named import identifiers,
// or there's nothing in collected imports are empty.
// we should include the whole module.
if (!isFirstVisitModule && [
...clientImportsSet
][0] !== '*') {
clientComponentImports[modRequest] = new Set([
'*'
]);
}
} else {
const isAutoModuleSourceType = assumedSourceType === 'auto';
if (isAutoModuleSourceType) {
clientComponentImports[modRequest] = new Set([
'*'
]);
} else {
// If it's not analyzed as named ESM exports, e.g. if it's mixing `export *` with named exports,
// We'll include all modules since it's not able to do tree-shaking.
for (const name of importedIdentifiers){
// For cjs module default import, we include the whole module since
const isCjsDefaultImport = isCjsModule && name === 'default';
// Always include __esModule along with cjs module default export,
// to make sure it work with client module proxy from React.
if (isCjsDefaultImport) {
clientComponentImports[modRequest].add('__esModule');
}
clientComponentImports[modRequest].add(name);
}
}
}
}
function getModuleResource(mod) {
var _mod_resourceResolveData, _mod_resourceResolveData1, _mod_matchResource;
const modPath = ((_mod_resourceResolveData = mod.resourceResolveData) == null ? void 0 : _mod_resourceResolveData.path) || '';
const modQuery = ((_mod_resourceResolveData1 = mod.resourceResolveData) == null ? void 0 : _mod_resourceResolveData1.query) || '';
// 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 modResource = modPath + modQuery;
// Context modules don't have a resource path, we use the identifier instead.
if (mod.constructor.name === 'ContextModule') {
modResource = mod.identifier();
}
// For the barrel optimization, we need to use the match resource instead
// because there will be 2 modules for the same file (same resource path)
// but they're different modules and can't be deduped via `visitedModule`.
// The first module is a virtual re-export module created by the loader.
if ((_mod_matchResource = mod.matchResource) == null ? void 0 : _mod_matchResource.startsWith(_constants1.BARREL_OPTIMIZATION_PREFIX)) {
modResource = mod.matchResource + ':' + modResource;
}
if (mod.resource === `?${_constants.WEBPACK_RESOURCE_QUERIES.metadataRoute}`) {
return getMetadataRouteResource(mod.rawRequest).filePath;
}
return modResource;
}
function getMetadataRouteResource(request) {
// e.g. next-metadata-route-loader?filePath=<some-url-encoded-path>&isDynamicRouteExtension=1!?__next_metadata_route__
const query = request.split('!')[0].split('next-metadata-route-loader?')[1];
return (0, _querystring.parse)(query);
}
//# sourceMappingURL=flight-client-entry-plugin.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,84 @@
/**
* 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 { webpack } from 'next/dist/compiled/webpack/webpack';
interface Options {
dev: boolean;
appDir: string;
experimentalInlineCss: boolean;
}
/**
* Webpack module id
*/
type ModuleId = string | number;
export type ManifestChunks = ReadonlyArray<string>;
export interface ManifestNode {
[moduleExport: string]: {
/**
* Webpack module id
*/
id: ModuleId;
/**
* Export name
*/
name: string;
/**
* Chunks for the module. JS and CSS.
*/
chunks: ManifestChunks;
/**
* If chunk contains async module
*/
async?: boolean;
};
}
export interface ClientReferenceManifestForRsc {
clientModules: ManifestNode;
rscModuleMapping: {
[moduleId: string]: ManifestNode;
};
edgeRscModuleMapping: {
[moduleId: string]: ManifestNode;
};
}
export type CssResource = InlinedCssFile | UninlinedCssFile;
interface InlinedCssFile {
path: string;
inlined: true;
content: string;
}
interface UninlinedCssFile {
path: string;
inlined: false;
}
export interface ClientReferenceManifest extends ClientReferenceManifestForRsc {
readonly moduleLoading: {
prefix: string;
crossOrigin?: 'use-credentials' | '';
};
ssrModuleMapping: {
[moduleId: string]: ManifestNode;
};
edgeSSRModuleMapping: {
[moduleId: string]: ManifestNode;
};
entryCSSFiles: {
[entry: string]: CssResource[];
};
entryJSFiles?: {
[entry: string]: string[];
};
}
export declare class ClientReferenceManifestPlugin {
dev: Options['dev'];
appDir: Options['appDir'];
appDirBase: string;
experimentalInlineCss: Options['experimentalInlineCss'];
constructor(options: Options);
apply(compiler: webpack.Compiler): void;
createAsset(compilation: webpack.Compilation, context: string): void;
}
export {};

View File

@@ -0,0 +1,420 @@
/**
* 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.
*/ "use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "ClientReferenceManifestPlugin", {
enumerable: true,
get: function() {
return ClientReferenceManifestPlugin;
}
});
const _path = /*#__PURE__*/ _interop_require_wildcard(require("path"));
const _webpack = require("next/dist/compiled/webpack/webpack");
const _constants = require("../../../shared/lib/constants");
const _buildcontext = require("../../build-context");
const _constants1 = require("../../../lib/constants");
const _normalizepagepath = require("../../../shared/lib/page-path/normalize-page-path");
const _deploymentid = require("../../../shared/lib/deployment-id");
const _utils = require("../utils");
const _encodeuripath = require("../../../shared/lib/encode-uri-path");
function _getRequireWildcardCache(nodeInterop) {
if (typeof WeakMap !== "function") return null;
var cacheBabelInterop = new WeakMap();
var cacheNodeInterop = new WeakMap();
return (_getRequireWildcardCache = function(nodeInterop) {
return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
})(nodeInterop);
}
function _interop_require_wildcard(obj, nodeInterop) {
if (!nodeInterop && obj && obj.__esModule) {
return obj;
}
if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
return {
default: obj
};
}
var cache = _getRequireWildcardCache(nodeInterop);
if (cache && cache.has(obj)) {
return cache.get(obj);
}
var newObj = {
__proto__: null
};
var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
for(var key in obj){
if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
if (desc && (desc.get || desc.set)) {
Object.defineProperty(newObj, key, desc);
} else {
newObj[key] = obj[key];
}
}
}
newObj.default = obj;
if (cache) {
cache.set(obj, newObj);
}
return newObj;
}
const pluginState = (0, _buildcontext.getProxiedPluginState)({
ssrModules: {},
edgeSsrModules: {},
rscModules: {},
edgeRscModules: {}
});
function getAppPathRequiredChunks(chunkGroup, excludedFiles) {
const deploymentIdChunkQuery = (0, _deploymentid.getDeploymentIdQueryOrEmptyString)();
const chunks = [];
chunkGroup.chunks.forEach((chunk)=>{
if (_constants.SYSTEM_ENTRYPOINTS.has(chunk.name || '')) {
return null;
}
// Get the actual chunk file names from the chunk file list.
if (chunk.id != null) {
const chunkId = '' + chunk.id;
chunk.files.forEach((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;
if (excludedFiles.has(file)) return null;
// We encode the file as a URI because our server (and many other services such as S3)
// expect to receive reserved characters such as `[` and `]` as encoded. This was
// previously done for dynamic chunks by patching the webpack runtime but we want
// these filenames to be managed by React's Flight runtime instead and so we need
// to implement any special handling of the file name here.
return chunks.push(chunkId, (0, _encodeuripath.encodeURIPath)(file) + deploymentIdChunkQuery);
});
}
});
return chunks;
}
// 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
// - app/[...catchAll]/page -> app
// - app/foo/@slot/[...catchAll]/page -> app/foo
function entryNameToGroupName(entryName) {
let groupName = entryName.slice(0, entryName.lastIndexOf('/'))// Remove slots
.replace(/\/@[^/]+/g, '')// Remove the group with lookahead to make sure it's not interception route
.replace(/\/\([^/]+\)(?=(\/|$))/g, '')// Remove catch-all routes since they should be part of the parent group that the catch-all would apply to.
// This is necessary to support parallel routes since multiple page components can be rendered on the same page.
// In order to do that, we need to ensure that the manifests are merged together by putting them in the same group.
.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);
Object.assign(manifest.rscModuleMapping, manifestToMerge.rscModuleMapping);
Object.assign(manifest.edgeRscModuleMapping, manifestToMerge.edgeRscModuleMapping);
}
const PLUGIN_NAME = 'ClientReferenceManifestPlugin';
class ClientReferenceManifestPlugin {
constructor(options){
this.dev = false;
this.dev = options.dev;
this.appDir = options.appDir;
this.appDirBase = _path.default.dirname(this.appDir) + _path.default.sep;
this.experimentalInlineCss = options.experimentalInlineCss;
}
apply(compiler) {
compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation)=>{
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.webpack.Compilation.PROCESS_ASSETS_STAGE_ANALYSE
}, ()=>this.createAsset(compilation, compiler.context));
});
}
createAsset(compilation, context) {
var _compilation_entrypoints_get;
const manifestsPerGroup = new Map();
const manifestEntryFiles = [];
const configuredCrossOriginLoading = compilation.outputOptions.crossOriginLoading;
const crossOriginMode = typeof configuredCrossOriginLoading === 'string' ? configuredCrossOriginLoading === 'use-credentials' ? configuredCrossOriginLoading : '' // === 'anonymous'
: undefined;
if (typeof compilation.outputOptions.publicPath !== 'string') {
throw Object.defineProperty(new Error('Expected webpack publicPath to be a string when using App Router. To customize where static assets are loaded from, use the `assetPrefix` option in next.config.js. If you are customizing your webpack config please make sure you are not modifying or removing the publicPath configuration option'), "__NEXT_ERROR_CODE", {
value: "E136",
enumerable: false,
configurable: true
});
}
const prefix = compilation.outputOptions.publicPath || '';
// We want to omit any files that will always be loaded on any App Router page
// because they will already be loaded by the main entrypoint.
const rootMainFiles = new Set();
(_compilation_entrypoints_get = compilation.entrypoints.get(_constants.CLIENT_STATIC_FILES_RUNTIME_MAIN_APP)) == null ? void 0 : _compilation_entrypoints_get.getFiles().forEach((file)=>{
if (/(?<!\.hot-update)\.(js|css)($|\?)/.test(file)) {
rootMainFiles.add(file.replace(/\\/g, '/'));
}
});
for (let [entryName, entrypoint] of compilation.entrypoints){
if (entryName === _constants.CLIENT_STATIC_FILES_RUNTIME_MAIN_APP || entryName === _constants.APP_CLIENT_INTERNALS) {
entryName = '';
} else if (!/^app[\\/]/.test(entryName)) {
continue;
}
const manifest = {
moduleLoading: {
prefix,
crossOrigin: crossOriginMode
},
ssrModuleMapping: {},
edgeSSRModuleMapping: {},
clientModules: {},
entryCSSFiles: {},
rscModuleMapping: {},
edgeRscModuleMapping: {}
};
// Absolute path without the extension
const chunkEntryName = (this.appDirBase + entryName).replace(/[\\/]/g, _path.default.sep);
manifest.entryCSSFiles[chunkEntryName] = entrypoint.getFiles().filter((f)=>!f.startsWith('static/css/pages/') && f.endsWith('.css')).map((file)=>{
const source = compilation.getAsset(file).source.source();
if (this.experimentalInlineCss && // Inline CSS currently does not work properly with HMR, so we only
// inline CSS in production.
!this.dev) {
return {
inlined: true,
path: file,
content: typeof source === 'string' ? source : source.toString()
};
}
return {
inlined: false,
path: file
};
});
const requiredChunks = getAppPathRequiredChunks(entrypoint, rootMainFiles);
const recordModule = (modId, mod)=>{
var _mod_resourceResolveData, _mod_resourceResolveData1, _mod_matchResource;
let 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;
const rscIdMapping = manifest.rscModuleMapping;
const edgeRscIdMapping = manifest.edgeRscModuleMapping;
// 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 = (0, _path.relative)(context, ((_mod_resourceResolveData = mod.resourceResolveData) == null ? void 0 : _mod_resourceResolveData.path) || resource);
const rscNamedModuleId = (0, _path.relative)(context, ((_mod_resourceResolveData1 = mod.resourceResolveData) == null ? void 0 : _mod_resourceResolveData1.path) || resource);
if (!ssrNamedModuleId.startsWith('.')) ssrNamedModuleId = `./${ssrNamedModuleId.replace(/\\/g, '/')}`;
// 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.default.sep)) : null;
// An extra query param is added to the resource key when it's optimized
// through the Barrel Loader. That's because the same file might be created
// as multiple modules (depending on what you import from it).
// See also: webpack/loaders/next-flight-loader/index.ts.
if ((_mod_matchResource = mod.matchResource) == null ? void 0 : _mod_matchResource.startsWith(_constants.BARREL_OPTIMIZATION_PREFIX)) {
ssrNamedModuleId = (0, _utils.formatBarrelOptimizedResource)(ssrNamedModuleId, mod.matchResource);
resource = (0, _utils.formatBarrelOptimizedResource)(resource, mod.matchResource);
}
function addClientReference() {
var _pluginState_ssrModules_ssrNamedModuleId, _pluginState_edgeSsrModules_ssrNamedModuleId;
const isAsync = Boolean(compilation.moduleGraph.isAsync(mod) || ((_pluginState_ssrModules_ssrNamedModuleId = pluginState.ssrModules[ssrNamedModuleId]) == null ? void 0 : _pluginState_ssrModules_ssrNamedModuleId.async) || ((_pluginState_edgeSsrModules_ssrNamedModuleId = pluginState.edgeSsrModules[ssrNamedModuleId]) == null ? void 0 : _pluginState_edgeSsrModules_ssrNamedModuleId.async));
const exportName = resource;
manifest.clientModules[exportName] = {
id: modId,
name: '*',
chunks: requiredChunks,
async: isAsync
};
if (esmResource) {
const edgeExportName = esmResource;
manifest.clientModules[edgeExportName] = manifest.clientModules[exportName];
}
}
function addSSRIdMapping() {
const exportName = resource;
const moduleInfo = pluginState.ssrModules[ssrNamedModuleId];
if (moduleInfo) {
moduleIdMapping[modId] = moduleIdMapping[modId] || {};
moduleIdMapping[modId]['*'] = {
...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: moduleInfo.moduleId,
async: moduleInfo.async
};
}
const edgeModuleInfo = pluginState.edgeSsrModules[ssrNamedModuleId];
if (edgeModuleInfo) {
edgeModuleIdMapping[modId] = edgeModuleIdMapping[modId] || {};
edgeModuleIdMapping[modId]['*'] = {
...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: edgeModuleInfo.moduleId,
async: edgeModuleInfo.async
};
}
}
function addRSCIdMapping() {
const exportName = resource;
const moduleInfo = pluginState.rscModules[rscNamedModuleId];
if (moduleInfo) {
rscIdMapping[modId] = rscIdMapping[modId] || {};
rscIdMapping[modId]['*'] = {
...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: moduleInfo.moduleId,
async: moduleInfo.async
};
}
const edgeModuleInfo = pluginState.ssrModules[rscNamedModuleId];
if (edgeModuleInfo) {
edgeRscIdMapping[modId] = edgeRscIdMapping[modId] || {};
edgeRscIdMapping[modId]['*'] = {
...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: edgeModuleInfo.moduleId,
async: edgeModuleInfo.async
};
}
}
addClientReference();
addSSRIdMapping();
addRSCIdMapping();
manifest.clientModules = moduleReferences;
manifest.ssrModuleMapping = moduleIdMapping;
manifest.edgeSSRModuleMapping = edgeModuleIdMapping;
manifest.rscModuleMapping = rscIdMapping;
manifest.edgeRscModuleMapping = edgeRscIdMapping;
};
const checkedChunkGroups = new Set();
const checkedChunks = new Set();
function recordChunkGroup(chunkGroup) {
// Ensure recursion is stopped if we've already checked this chunk group.
if (checkedChunkGroups.has(chunkGroup)) return;
checkedChunkGroups.add(chunkGroup);
// 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)=>{
// Ensure recursion is stopped if we've already checked this chunk.
if (checkedChunks.has(chunk)) return;
checkedChunks.add(chunk);
const entryMods = compilation.chunkGraph.getChunkEntryModulesIterable(chunk);
for (const mod of entryMods){
if (mod.layer !== _constants1.WEBPACK_LAYERS.appPagesBrowser) continue;
const request = mod.request;
if (!request || !request.includes('next-flight-client-entry-loader.js?')) {
continue;
}
const connections = (0, _utils.getModuleReferencesInOrder)(mod, compilation.moduleGraph);
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);
if (concatenatedModId) {
recordModule(concatenatedModId, clientEntryMod);
}
}
}
}
}
});
// Walk through all children chunk groups too.
for (const child of chunkGroup.childrenIterable){
recordChunkGroup(child);
}
}
recordChunkGroup(entrypoint);
// 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'));
}
// We also need to create manifests for route handler entrypoints to
// enable `'use cache'`.
if (/\/route$/.test(entryName)) {
manifestEntryFiles.push(entryName);
}
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 = {
moduleLoading: {
prefix,
crossOrigin: crossOriginMode
},
ssrModuleMapping: {},
edgeSSRModuleMapping: {},
clientModules: {},
entryCSSFiles: {},
rscModuleMapping: {},
edgeRscModuleMapping: {}
};
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 = (0, _normalizepagepath.normalizePagePath)(pagePath.slice('app'.length));
compilation.emitAsset('server/app' + pageBundlePath + '_' + _constants.CLIENT_REFERENCE_MANIFEST + '.js', new _webpack.sources.RawSource(`globalThis.__RSC_MANIFEST=(globalThis.__RSC_MANIFEST||{});globalThis.__RSC_MANIFEST[${JSON.stringify(pagePath.slice('app'.length))}]=${json}`));
}
}
}
//# sourceMappingURL=flight-manifest-plugin.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,5 @@
import { webpack } from 'next/dist/compiled/webpack/webpack';
export default class ForceCompleteRuntimePlugin {
allSharedRuntimeGlobals: Set<"__webpack_require__.n">;
apply(compiler: webpack.Compiler): void;
}

View File

@@ -0,0 +1,42 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "default", {
enumerable: true,
get: function() {
return ForceCompleteRuntimePlugin;
}
});
const _webpack = require("next/dist/compiled/webpack/webpack");
class ForceCompleteRuntimePlugin {
apply(compiler) {
compiler.hooks.thisCompilation.tap('ForceCompleteRuntimePlugin', (compilation)=>{
// Ensure that each chunk uses the complete Webpack runtime.
// That way soft nav to a new page has the full runtime available
// by the time the chunk loads.
// This is a workaround until we can get Webpack to include runtime updates
// in the Flight response or the Flight Client to wait for HMR updates.
compilation.hooks.afterChunks.tap({
name: 'ForceCompleteRuntimePlugin'
}, (chunks)=>{
for (const chunk of chunks){
compilation.chunkGraph.addChunkRuntimeRequirements(chunk, this.allSharedRuntimeGlobals);
break;
}
});
});
}
constructor(){
this.allSharedRuntimeGlobals = new Set([
// List is incomplete. These are the globals that are not commonly in the
// Webpack runtime but may show up during after Client navs.
// If you ever get "__webpack_require__.X is not a function" or similar,
// check https://github.com/webpack/webpack/blob/0f84d1e3bf69915dc060f23ced9dfa468a884a42/lib/RuntimeGlobals.js
// for which one it is and add it here.
_webpack.webpack.RuntimeGlobals.compatGetDefaultExport
]);
}
}
//# sourceMappingURL=force-complete-runtime.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../src/build/webpack/plugins/force-complete-runtime.ts"],"sourcesContent":["import { webpack } from 'next/dist/compiled/webpack/webpack'\n\nexport default class ForceCompleteRuntimePlugin {\n allSharedRuntimeGlobals = new Set([\n // List is incomplete. These are the globals that are not commonly in the\n // Webpack runtime but may show up during after Client navs.\n // If you ever get \"__webpack_require__.X is not a function\" or similar,\n // check https://github.com/webpack/webpack/blob/0f84d1e3bf69915dc060f23ced9dfa468a884a42/lib/RuntimeGlobals.js\n // for which one it is and add it here.\n webpack.RuntimeGlobals.compatGetDefaultExport,\n ])\n\n apply(compiler: webpack.Compiler) {\n compiler.hooks.thisCompilation.tap(\n 'ForceCompleteRuntimePlugin',\n (compilation) => {\n // Ensure that each chunk uses the complete Webpack runtime.\n // That way soft nav to a new page has the full runtime available\n // by the time the chunk loads.\n // This is a workaround until we can get Webpack to include runtime updates\n // in the Flight response or the Flight Client to wait for HMR updates.\n compilation.hooks.afterChunks.tap(\n { name: 'ForceCompleteRuntimePlugin' },\n (chunks) => {\n for (const chunk of chunks) {\n compilation.chunkGraph.addChunkRuntimeRequirements(\n chunk,\n this.allSharedRuntimeGlobals\n )\n // Just need to add runtime requirements to one chunk since we only\n // have one runtime chunk for all other chunks.\n break\n }\n }\n )\n }\n )\n }\n}\n"],"names":["ForceCompleteRuntimePlugin","apply","compiler","hooks","thisCompilation","tap","compilation","afterChunks","name","chunks","chunk","chunkGraph","addChunkRuntimeRequirements","allSharedRuntimeGlobals","Set","webpack","RuntimeGlobals","compatGetDefaultExport"],"mappings":";;;;+BAEA;;;eAAqBA;;;yBAFG;AAET,MAAMA;IAUnBC,MAAMC,QAA0B,EAAE;QAChCA,SAASC,KAAK,CAACC,eAAe,CAACC,GAAG,CAChC,8BACA,CAACC;YACC,4DAA4D;YAC5D,iEAAiE;YACjE,+BAA+B;YAC/B,2EAA2E;YAC3E,uEAAuE;YACvEA,YAAYH,KAAK,CAACI,WAAW,CAACF,GAAG,CAC/B;gBAAEG,MAAM;YAA6B,GACrC,CAACC;gBACC,KAAK,MAAMC,SAASD,OAAQ;oBAC1BH,YAAYK,UAAU,CAACC,2BAA2B,CAChDF,OACA,IAAI,CAACG,uBAAuB;oBAI9B;gBACF;YACF;QAEJ;IAEJ;;aAlCAA,0BAA0B,IAAIC,IAAI;YAChC,yEAAyE;YACzE,4DAA4D;YAC5D,wEAAwE;YACxE,+GAA+G;YAC/G,uCAAuC;YACvCC,gBAAO,CAACC,cAAc,CAACC,sBAAsB;SAC9C;;AA4BH","ignoreList":[0]}

View File

@@ -0,0 +1,48 @@
import type { webpack } from 'next/dist/compiled/webpack/webpack';
import type { ResolvedBaseUrl } from '../../load-jsconfig';
export interface Pattern {
prefix: string;
suffix: string;
}
export declare function hasZeroOrOneAsteriskCharacter(str: string): boolean;
/**
* Determines whether a path starts with a relative path component (i.e. `.` or `..`).
*/
export declare function pathIsRelative(testPath: string): boolean;
export declare function tryParsePattern(pattern: string): Pattern | undefined;
/** Return the object corresponding to the best pattern to match `candidate`. */
export declare function findBestPatternMatch<T>(values: readonly T[], getPattern: (value: T) => Pattern, candidate: string): T | undefined;
/**
* 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 declare function matchPatternOrExact(patternStrings: readonly string[], candidate: string): string | Pattern | undefined;
/**
* Tests whether a value is string
*/
export declare function isString(text: unknown): text is string;
/**
* Given that candidate matches pattern, returns the text matching the '*'.
* E.g.: matchedText(tryParsePattern("foo*baz"), "foobarbaz") === "bar"
*/
export declare function matchedText(pattern: Pattern, candidate: string): string;
export declare function patternText({ prefix, suffix }: Pattern): string;
type Paths = {
[match: string]: string[];
};
/**
* 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
*/
type NonFunction<T> = T extends Function ? never : T;
type ResolvePluginPlugin = NonFunction<webpack.ResolvePluginInstance>;
export declare class JsConfigPathsPlugin implements ResolvePluginPlugin {
paths: Paths;
resolvedBaseUrl: ResolvedBaseUrl;
jsConfigPlugin: true;
constructor(paths: Paths, resolvedBaseUrl: ResolvedBaseUrl);
apply(resolver: webpack.Resolver): void;
}
export {};

View File

@@ -0,0 +1,219 @@
/**
* 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
*/ "use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
0 && (module.exports = {
JsConfigPathsPlugin: null,
findBestPatternMatch: null,
hasZeroOrOneAsteriskCharacter: null,
isString: null,
matchPatternOrExact: null,
matchedText: null,
pathIsRelative: null,
patternText: null,
tryParsePattern: null
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
JsConfigPathsPlugin: function() {
return JsConfigPathsPlugin;
},
findBestPatternMatch: function() {
return findBestPatternMatch;
},
hasZeroOrOneAsteriskCharacter: function() {
return hasZeroOrOneAsteriskCharacter;
},
isString: function() {
return isString;
},
matchPatternOrExact: function() {
return matchPatternOrExact;
},
matchedText: function() {
return matchedText;
},
pathIsRelative: function() {
return pathIsRelative;
},
patternText: function() {
return patternText;
},
tryParsePattern: function() {
return tryParsePattern;
}
});
const _path = /*#__PURE__*/ _interop_require_default(require("path"));
const _debug = require("next/dist/compiled/debug");
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
const log = (0, _debug.debug)('next:jsconfig-paths-plugin');
const asterisk = 0x2a;
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;
}
function pathIsRelative(testPath) {
return /^\.\.?($|[\\/])/.test(testPath);
}
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);
}
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;
}
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);
}
function isString(text) {
return typeof text === 'string';
}
function matchedText(pattern, candidate) {
return candidate.substring(pattern.prefix.length, candidate.length - pattern.suffix.length);
}
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/;
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 resolvedBaseUrl = this.resolvedBaseUrl;
if (resolvedBaseUrl === undefined) {
return 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.default.posix.isAbsolute(moduleName) || process.platform === 'win32' && _path.default.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.default.join(resolvedBaseUrl.baseUrl, 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

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,12 @@
import type { Compiler } from 'next/dist/compiled/webpack/webpack';
export declare class MemoryWithGcCachePlugin {
/**
* Maximum number of compilations to keep the cache entry around for when it's not used.
* We keep the modules for a few more compilations so that if you comment out a package and bring it back it doesn't need a full compile again.
*/
private maxGenerations;
constructor({ maxGenerations }: {
maxGenerations: number;
});
apply(compiler: Compiler): void;
}

View File

@@ -0,0 +1,114 @@
/*
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.
*/ "use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "MemoryWithGcCachePlugin", {
enumerable: true,
get: function() {
return MemoryWithGcCachePlugin;
}
});
// 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';
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

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,51 @@
import type { AssetBinding } from '../loaders/get-module-build-info';
import type { ProxyMatcher } from '../../analysis/get-page-static-info';
import { webpack } from 'next/dist/compiled/webpack/webpack';
import type { CustomRoutes } from '../../../lib/load-custom-routes';
export interface EdgeFunctionDefinition {
files: string[];
name: string;
page: string;
matchers: ProxyMatcher[];
env: Record<string, string>;
wasm?: AssetBinding[];
assets?: AssetBinding[];
regions?: string[] | string;
}
export interface MiddlewareManifest {
version: 3;
sortedMiddleware: string[];
middleware: {
[page: string]: EdgeFunctionDefinition;
};
functions: {
[page: string]: EdgeFunctionDefinition;
};
}
type EdgeRuntimeEnvironments = Record<string, string> & {
__NEXT_BUILD_ID: string;
NEXT_SERVER_ACTIONS_ENCRYPTION_KEY: string;
};
interface Options {
dev: boolean;
sriEnabled: boolean;
rewrites: CustomRoutes['rewrites'];
edgeEnvironments: EdgeRuntimeEnvironments;
}
export default class MiddlewarePlugin {
private readonly dev;
private readonly sriEnabled;
private readonly rewrites;
private readonly edgeEnvironments;
constructor({ dev, sriEnabled, rewrites, edgeEnvironments }: Options);
apply(compiler: webpack.Compiler): void;
}
export declare const SUPPORTED_NATIVE_MODULES: readonly ["buffer", "events", "assert", "util", "async_hooks"];
export declare function getEdgePolyfilledModules(): Record<string, string>;
export declare function handleWebpackExternalForEdgeRuntime({ request, context, contextInfo, getResolve, }: {
request: string;
context: string;
contextInfo: any;
getResolve: () => any;
}): Promise<string | undefined>;
export {};

View File

@@ -0,0 +1,614 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
0 && (module.exports = {
SUPPORTED_NATIVE_MODULES: null,
default: null,
getEdgePolyfilledModules: null,
handleWebpackExternalForEdgeRuntime: null
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
SUPPORTED_NATIVE_MODULES: function() {
return SUPPORTED_NATIVE_MODULES;
},
default: function() {
return MiddlewarePlugin;
},
getEdgePolyfilledModules: function() {
return getEdgePolyfilledModules;
},
handleWebpackExternalForEdgeRuntime: function() {
return handleWebpackExternalForEdgeRuntime;
}
});
const _routeregex = require("../../../shared/lib/router/utils/route-regex");
const _getmodulebuildinfo = require("../loaders/get-module-build-info");
const _utils = require("../../../shared/lib/router/utils");
const _webpack = require("next/dist/compiled/webpack/webpack");
const _picomatch = /*#__PURE__*/ _interop_require_default(require("next/dist/compiled/picomatch"));
const _path = /*#__PURE__*/ _interop_require_default(require("path"));
const _constants = require("../../../shared/lib/constants");
const _shared = require("../../../trace/shared");
const _events = require("../../../telemetry/events");
const _apppaths = require("../../../shared/lib/router/utils/app-paths");
const _constants1 = require("../../../lib/constants");
const _generateinterceptionroutesrewrites = require("../../../lib/generate-interception-routes-rewrites");
const _parsedynamiccodeevaluationerror = require("./wellknown-errors-plugin/parse-dynamic-code-evaluation-error");
const _utils1 = require("../utils");
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
const KNOWN_SAFE_DYNAMIC_PACKAGES = require('../../../lib/known-edge-safe-packages.json');
const NAME = 'MiddlewarePlugin';
const MANIFEST_VERSION = 3;
/**
* 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: module1, usingIndirectEval, wp } = args;
if (typeof usingIndirectEval === 'boolean') {
return usingIndirectEval;
}
const exportsInfo = moduleGraph.getExportsInfo(module1);
for (const exportName of usingIndirectEval){
if (exportsInfo.getUsed(exportName, runtime) !== wp.UsageState.Unused) {
return true;
}
}
return false;
}
function getEntryFiles(entryFiles, meta, hasInstrumentationHook, opts) {
const files = [];
if (meta.edgeSSR) {
if (meta.edgeSSR.isServerComponent) {
files.push(`server/${_constants.SERVER_REFERENCE_MANIFEST}.js`);
if (opts.sriEnabled) {
files.push(`server/${_constants.SUBRESOURCE_INTEGRITY_MANIFEST}.js`);
}
files.push(...entryFiles.filter((file)=>file.startsWith('app/') && !file.endsWith('.hot-update.js')).map((file)=>'server/' + file.replace(/\.js$/, '_' + _constants.CLIENT_REFERENCE_MANIFEST + '.js')));
}
if (!opts.dev && !meta.edgeSSR.isAppDir) {
files.push(`server/${_constants.DYNAMIC_CSS_MANIFEST}.js`);
}
files.push(`server/${_constants.MIDDLEWARE_BUILD_MANIFEST}.js`, `server/${_constants.MIDDLEWARE_REACT_LOADABLE_MANIFEST}.js`, `server/${_constants.NEXT_FONT_MANIFEST}.js`, `server/${_constants.INTERCEPTION_ROUTE_REWRITE_MANIFEST}.js`);
if (!opts.dev) {
files.push(`${_constants.SERVER_FILES_MANIFEST}.js`);
}
}
if (hasInstrumentationHook) {
files.push(`server/edge-${_constants1.INSTRUMENTATION_HOOK_FILENAME}.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 ()=>{
const middlewareManifest = {
version: MANIFEST_VERSION,
middleware: {},
functions: {},
sortedMiddleware: []
};
const hasInstrumentationHook = compilation.entrypoints.has(_constants1.INSTRUMENTATION_HOOK_FILENAME);
// we only emit this entry for the edge runtime since it doesn't have access to a routes manifest
// and we don't need to provide the entire route manifest, just the interception routes.
const interceptionRewrites = JSON.stringify(opts.rewrites.beforeFiles.filter(_generateinterceptionroutesrewrites.isInterceptionRouteRewrite));
compilation.emitAsset(`${_constants.INTERCEPTION_ROUTE_REWRITE_MANIFEST}.js`, new _webpack.sources.RawSource(`self.__INTERCEPTION_ROUTE_REWRITE_MANIFEST=${JSON.stringify(interceptionRewrites)}`));
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) ? (0, _apppaths.normalizeAppPath)(page) : page;
const catchAll = !metadata.edgeSSR && !metadata.edgeApiFunction;
const { namedRegex } = (0, _routeregex.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 isEdgeFunction = !!(metadata.edgeApiFunction || metadata.edgeSSR);
const edgeFunctionDefinition = {
files: getEntryFiles(entrypoint.getFiles(), metadata, hasInstrumentationHook, 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
})),
env: opts.edgeEnvironments,
...metadata.regions && {
regions: metadata.regions
}
};
if (isEdgeFunction) {
middlewareManifest.functions[page] = edgeFunctionDefinition;
} else {
middlewareManifest.middleware[page] = edgeFunctionDefinition;
}
}
middlewareManifest.sortedMiddleware = (0, _utils.getSortedRoutes)(Object.keys(middlewareManifest.middleware));
compilation.emitAsset(_constants.MIDDLEWARE_MANIFEST, new _webpack.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 module1 = entryModule ?? (parser == null ? void 0 : parser.state.current);
if (module1) {
error.module = module1;
}
error.loc = loc;
return error;
}
function isInMiddlewareLayer(parser) {
var _parser_state_module;
const layer = (_parser_state_module = parser.state.module) == null ? void 0 : _parser_state_module.layer;
return layer === _constants1.WEBPACK_LAYERS.middleware || layer === _constants1.WEBPACK_LAYERS.apiEdge;
}
function isNodeJsModule(moduleName) {
return require('module').builtinModules.includes(moduleName);
}
function isBunModule(moduleName) {
return moduleName === 'bun' || moduleName.startsWith('bun:');
}
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.default.sep)))) {
return true;
}
const name = fileName.replace(rootDir ?? '', '');
return (0, _picomatch.default)((middlewareConfig == null ? void 0 : middlewareConfig.unstable_allowDynamic) ?? [], {
dot: true
})(name);
}
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 _constants.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 = (0, _getmodulebuildinfo.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: module1, source } = parser.state;
const buildInfo = (0, _getmodulebuildinfo.getModuleBuildInfo)(module1);
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: module1.identifier()
},
sourceContent: source.toString()
});
if (!dev && (isNodeJsModule(importedModule) || isBunModule(importedModule)) && !SUPPORTED_NATIVE_MODULES.includes(importedModule)) {
const isBun = isBunModule(importedModule);
compilation.warnings.push(buildWebpackError({
message: `A ${isBun ? 'Bun' : '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);
}
};
}
async function codeAnalyzerBySwc(compilation, modules, dev) {
const binding = require('../../swc');
for (const module1 of modules){
if (module1.layer !== _constants1.WEBPACK_LAYERS.middleware && module1.layer !== _constants1.WEBPACK_LAYERS.apiEdge) {
continue;
}
if (module1.constructor.name !== 'NormalModule') {
continue;
}
const normalModule = module1;
if (!normalModule.type.startsWith('javascript')) {
continue;
}
const originalSource = normalModule.originalSource();
if (!originalSource) {
continue;
}
const source = originalSource.source();
if (typeof source !== 'string') {
continue;
}
const diagnostics = await binding.warnForEdgeRuntime(source, !dev);
for (const diagnostic of diagnostics){
const webpackError = buildWebpackError({
message: diagnostic.message,
loc: diagnostic.loc,
compilation,
entryModule: module1
});
if (diagnostic.severity === 'Warning') {
compilation.warnings.push(webpackError);
} else {
compilation.errors.push(webpackError);
}
}
}
}
function getExtractMetadata(params) {
const { dev, compilation, metadataByEntry, compiler } = params;
const { webpack: wp } = compiler;
return async ()=>{
metadataByEntry.clear();
const telemetry = _shared.traceGlobals.get('telemetry');
for (const [entryName, entry] of compilation.entries){
var _entry_dependencies, _route_middlewareConfig;
if (entry.options.runtime !== _constants.EDGE_RUNTIME_WEBPACK) {
continue;
}
const entryDependency = (_entry_dependencies = entry.dependencies) == null ? void 0 : _entry_dependencies[0];
const resolvedModule = compilation.moduleGraph.getResolvedModule(entryDependency);
if (!resolvedModule) {
continue;
}
const { rootDir, route } = (0, _getmodulebuildinfo.getModuleBuildInfo)(resolvedModule);
const { moduleGraph } = compilation;
const modules = new Set();
const addEntriesFromDependency = (dependency)=>{
const module1 = moduleGraph.getModule(dependency);
if (module1) {
modules.add(module1);
}
};
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 module1 of modules){
const buildInfo = (0, _getmodulebuildinfo.getModuleBuildInfo)(module1);
/**
* Check if it uses the image generation feature.
*/ if (!dev) {
const resource = module1.resource;
const hasOGImageGeneration = resource && /[\\/]node_modules[\\/]@vercel[\\/]og[\\/]dist[\\/]index\.(edge|node)\.js$|[\\/]next[\\/]dist[\\/](esm[\\/])?server[\\/]og[\\/]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: module1,
moduleGraph,
runtime: wp.util.runtime.getEntryRuntime(compilation, entryName),
usingIndirectEval: buildInfo.usingIndirectEval,
wp
})) {
var _route_middlewareConfig1;
const id = module1.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_allowDynamic) {
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: module1.userRequest.replace(rootDir ?? '', '')
}
});
}
if (!isDynamicCodeEvaluationAllowed(module1.userRequest, route == null ? void 0 : route.middlewareConfig, rootDir)) {
const 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`;
compilation.errors.push((0, _parsedynamiccodeevaluationerror.getDynamicCodeEvaluationError)(message, module1, compilation, compiler));
}
}
/**
* 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 (0, _utils1.getModuleReferencesInOrder)(module1, moduleGraph)){
if (conn.module) {
modules.add(conn.module);
}
}
}
telemetry == null ? void 0 : telemetry.record({
eventName: _events.EVENT_BUILD_FEATURE_USAGE,
payload: {
featureName: 'vercelImageGeneration',
invocationCount: ogImageGenerationCount
}
});
metadataByEntry.set(entryName, entryMetadata);
}
};
}
class MiddlewarePlugin {
constructor({ dev, sriEnabled, rewrites, edgeEnvironments }){
this.dev = dev;
this.sriEnabled = sriEnabled;
this.rewrites = rewrites;
this.edgeEnvironments = edgeEnvironments;
}
apply(compiler) {
compiler.hooks.compilation.tap(NAME, (compilation, params)=>{
// parser hooks aren't available in rspack
if (process.env.NEXT_RSPACK) {
compilation.hooks.finishModules.tapPromise(NAME, async (modules)=>{
await codeAnalyzerBySwc(compilation, modules, this.dev);
});
} else {
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.webpack.Compilation.PROCESS_ASSETS_STAGE_ADDITIONS
}, getCreateAssets({
compilation,
metadataByEntry,
opts: {
sriEnabled: this.sriEnabled,
rewrites: this.rewrites,
edgeEnvironments: this.edgeEnvironments,
dev: this.dev
}
}));
});
}
}
const SUPPORTED_NATIVE_MODULES = [
'buffer',
'events',
'assert',
'util',
'async_hooks'
];
const supportedEdgePolyfills = new Set(SUPPORTED_NATIVE_MODULES);
function getEdgePolyfilledModules() {
const records = {};
for (const mod of SUPPORTED_NATIVE_MODULES){
records[mod] = `commonjs node:${mod}`;
records[`node:${mod}`] = `commonjs node:${mod}`;
}
return records;
}
async function handleWebpackExternalForEdgeRuntime({ request, context, contextInfo, getResolve }) {
if ((contextInfo.issuerLayer === _constants1.WEBPACK_LAYERS.middleware || contextInfo.issuerLayer === _constants1.WEBPACK_LAYERS.apiEdge) && (isNodeJsModule(request) || isBunModule(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,4 @@
import MiniCssExtractPlugin from 'next/dist/compiled/mini-css-extract-plugin';
export default class NextMiniCssExtractPlugin extends MiniCssExtractPlugin {
__next_css_remove: boolean;
}

View File

@@ -0,0 +1,24 @@
// @ts-ignore: TODO: remove when webpack 5 is stable
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "default", {
enumerable: true,
get: function() {
return NextMiniCssExtractPlugin;
}
});
const _minicssextractplugin = /*#__PURE__*/ _interop_require_default(require("next/dist/compiled/mini-css-extract-plugin"));
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
class NextMiniCssExtractPlugin extends _minicssextractplugin.default {
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"],"sourcesContent":["// @ts-ignore: TODO: remove when webpack 5 is stable\nimport MiniCssExtractPlugin from 'next/dist/compiled/mini-css-extract-plugin'\n\nexport default class NextMiniCssExtractPlugin extends MiniCssExtractPlugin {\n __next_css_remove = true\n}\n"],"names":["NextMiniCssExtractPlugin","MiniCssExtractPlugin","__next_css_remove"],"mappings":"AAAA,oDAAoD;;;;;+BAGpD;;;eAAqBA;;;6EAFY;;;;;;AAElB,MAAMA,iCAAiCC,6BAAoB;;QAA3D,qBACbC,oBAAoB;;AACtB","ignoreList":[0]}

View File

@@ -0,0 +1,13 @@
import { sources, type CacheFacade, type Compilation } from 'next/dist/compiled/webpack/webpack';
export declare class MinifyPlugin {
private options;
constructor(options: {
noMangling?: boolean;
disableCharFreq?: boolean;
});
optimize(compiler: any, compilation: Compilation, assets: any, cache: CacheFacade, { SourceMapSource, RawSource, }: {
SourceMapSource: typeof sources.SourceMapSource;
RawSource: typeof sources.RawSource;
}): Promise<void>;
apply(compiler: any): void;
}

View File

@@ -0,0 +1,188 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "MinifyPlugin", {
enumerable: true,
get: function() {
return MinifyPlugin;
}
});
const _webpack = require("next/dist/compiled/webpack/webpack");
const _plimit = /*#__PURE__*/ _interop_require_default(require("next/dist/compiled/p-limit"));
const _utils = require("../../../utils");
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
function buildError(error, file) {
if (error.line) {
return new _webpack.WebpackError(`${file} from Minifier\n${error.message} [${file}:${error.line},${error.col}]${error.stack ? `\n${error.stack.split('\n').slice(1).join('\n')}` : ''}`);
}
if (error.stack) {
return new _webpack.WebpackError(`${file} from Minifier\n${error.message}\n${error.stack}`);
}
return new _webpack.WebpackError(`${file} from Minifier\n${error.message}`);
}
const debugMinify = process.env.NEXT_DEBUG_MINIFY;
class MinifyPlugin {
constructor(options){
this.options = options;
}
async optimize(compiler, compilation, assets, cache, { SourceMapSource, RawSource }) {
const mangle = this.options.noMangling ? false : {
reserved: [
'AbortSignal'
],
disableCharFreq: !!this.options.disableCharFreq
};
const compilationSpan = (0, _utils.getCompilationSpan)(compilation) || (0, _utils.getCompilationSpan)(compiler);
const MinifierSpan = compilationSpan.traceChild('minify-webpack-plugin-optimize');
if (compilation.name) {
MinifierSpan.setAttribute('compilationName', compilation.name);
}
MinifierSpan.setAttribute('mangle', String(mangle));
return MinifierSpan.traceAsyncFn(async ()=>{
const assetsList = Object.keys(assets);
const assetsForMinify = await Promise.all(assetsList.filter((name)=>{
if (!_webpack.ModuleFilenameHelpers.matchObject.bind(undefined, {
test: /\.[cm]?js(\?.*)?$/i
})(name)) {
return false;
}
const res = compilation.getAsset(name);
if (!res) {
console.log(name);
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.mergeEtags(cache.getLazyHashedEtag(source), JSON.stringify(this.options));
const output = await cache.getPromise(name, eTag);
if (debugMinify && debugMinify === '1') {
console.log(JSON.stringify({
name,
source: source.source().toString()
}), {
breakLength: Infinity,
maxStringLength: Infinity
});
}
return {
name,
info,
inputSource: source,
output,
eTag
};
}));
let initializedWorker;
const getWorker = ()=>{
return {
minify: async (options)=>{
const result = await require('../../../../swc').minify(options.input, {
...options.inputSourceMap ? {
sourceMap: {
content: JSON.stringify(options.inputSourceMap)
}
} : {},
compress: {
inline: 2,
global_defs: {
'process.env.__NEXT_PRIVATE_MINIMIZE_MACRO_FALSE': false
},
keep_classnames: this.options.noMangling,
keep_fnames: this.options.noMangling
},
mangle,
module: 'unknown',
output: {
comments: false
}
});
return result;
}
};
};
// The limit in the SWC minifier will be handled by Node.js
const limit = (0, _plimit.default)(Infinity);
const scheduledTasks = [];
for (const asset of assetsForMinify){
scheduledTasks.push(limit(async ()=>{
const { name, inputSource, eTag } = asset;
let { output } = asset;
const minifySpan = MinifierSpan.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;
let minifiedOutput;
try {
minifiedOutput = await getWorker().minify({
input,
inputSourceMap
});
} catch (error) {
compilation.errors.push(buildError(error, name));
return;
}
const source = minifiedOutput.map ? new SourceMapSource(minifiedOutput.code, name, minifiedOutput.map, input, inputSourceMap, true) : new RawSource(minifiedOutput.code);
await cache.storePromise(name, eTag, {
source
});
output = {
source
};
}
const newInfo = {
minimized: true
};
compilation.updateAsset(name, output.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) || _webpack.sources;
const pluginName = this.constructor.name;
compiler.hooks.thisCompilation.tap(pluginName, (compilation)=>{
const cache = compilation.getCache('MinifierWebpackPlugin');
const handleHashForChunk = (hash, _chunk)=>{
// increment 'c' to invalidate cache
hash.update('c');
};
const JSModulesHooks = _webpack.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.webpack.Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE_SIZE
}, (assets)=>this.optimize(compiler, compilation, assets, cache, {
SourceMapSource,
RawSource
}));
compilation.hooks.statsPrinter.tap(pluginName, (stats)=>{
stats.hooks.print.for('asset.info.minimized').tap('minify-webpack-plugin', (minimized, { green, formatFlag })=>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,32 @@
import { webpack } from 'next/dist/compiled/webpack/webpack';
export type NextFontManifest = {
pages: {
[path: string]: string[];
};
app: {
[entry: string]: string[];
};
appUsingSizeAdjust: boolean;
pagesUsingSizeAdjust: boolean;
};
/**
* 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 declare class NextFontManifestPlugin {
private appDir;
constructor(options: {
appDir: undefined | string;
});
apply(compiler: webpack.Compiler): void;
}

View File

@@ -0,0 +1,120 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "NextFontManifestPlugin", {
enumerable: true,
get: function() {
return NextFontManifestPlugin;
}
});
const _webpack = require("next/dist/compiled/webpack/webpack");
const _getroutefromentrypoint = /*#__PURE__*/ _interop_require_default(require("../../../server/get-route-from-entrypoint"));
const _constants = require("../../../shared/lib/constants");
const _utils = require("../utils");
const _path = /*#__PURE__*/ _interop_require_default(require("path"));
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
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'));
}
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.webpack.Compilation.PROCESS_ASSETS_STAGE_ADDITIONS
}, ()=>{
const nextFontManifest = {
pages: {},
app: {},
appUsingSizeAdjust: false,
pagesUsingSizeAdjust: false
};
if (this.appDir) {
const appDirBase = _path.default.dirname(this.appDir) + _path.default.sep;
// After all modules are created, we collect the modules that was created by next-font-loader.
(0, _utils.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.default.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 = (0, _getroutefromentrypoint.default)(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
compilation.emitAsset(`server/${_constants.NEXT_FONT_MANIFEST}.js`, new _webpack.sources.RawSource(`self.__NEXT_FONT_MANIFEST=${JSON.stringify(manifest)}`));
// Create manifest for server
compilation.emitAsset(`server/${_constants.NEXT_FONT_MANIFEST}.json`, new _webpack.sources.RawSource(manifest));
});
});
return;
}
}
//# sourceMappingURL=next-font-manifest-plugin.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,57 @@
import type { Span } from '../../../trace';
import type { NodeFileTraceReasons } from 'next/dist/compiled/@vercel/nft';
import { type CompilerNameValues } from '../../../shared/lib/constants';
import { webpack } from 'next/dist/compiled/webpack/webpack';
import type { NextConfigComplete } from '../../../server/config-shared';
export declare const TRACE_IGNORES: string[];
export declare function getFilesMapFromReasons(fileList: Set<string>, reasons: NodeFileTraceReasons, ignoreFn?: (file: string, parent?: string) => Boolean): Map<string, Map<string, {
ignored: boolean;
}>>;
export interface TurbotraceAction {
action: 'print' | 'annotate';
input: string[];
contextDirectory: string;
processCwd: string;
showAll?: boolean;
memoryLimit?: number;
}
export interface BuildTraceContext {
entriesTrace?: {
action: TurbotraceAction;
appDir: string;
outputPath: string;
depModArray: string[];
entryNameMap: Record<string, string>;
absolutePathByEntryName: Record<string, string>;
};
chunksTrace?: {
action: TurbotraceAction;
outputPath: string;
entryNameFilesMap: Record<string, Array<string>>;
};
}
export declare class TraceEntryPointsPlugin implements webpack.WebpackPluginInstance {
buildTraceContext: BuildTraceContext;
private rootDir;
private appDir;
private pagesDir;
private appDirEnabled?;
private tracingRoot;
private entryTraces;
private traceIgnores;
private esmExternals?;
private compilerType;
constructor({ rootDir, appDir, pagesDir, compilerType, appDirEnabled, traceIgnores, esmExternals, outputFileTracingRoot, }: {
rootDir: string;
compilerType: CompilerNameValues;
appDir: string | undefined;
pagesDir: string | undefined;
appDirEnabled?: boolean;
traceIgnores?: string[];
outputFileTracingRoot?: string;
esmExternals?: NextConfigComplete['experimental']['esmExternals'];
});
createTraceAssets(compilation: webpack.Compilation, span: Span): Promise<void>;
tapfinishModules(compilation: webpack.Compilation, traceEntrypointsPluginSpan: Span, doResolve: (request: string, parent: string, job: import('@vercel/nft/out/node-file-trace').Job, isEsmRequested: boolean) => Promise<string>, readlink: any, stat: any): void;
apply(compiler: webpack.Compiler): void;
}

View File

@@ -0,0 +1,542 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
0 && (module.exports = {
TRACE_IGNORES: null,
TraceEntryPointsPlugin: null,
getFilesMapFromReasons: null
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
TRACE_IGNORES: function() {
return TRACE_IGNORES;
},
TraceEntryPointsPlugin: function() {
return TraceEntryPointsPlugin;
},
getFilesMapFromReasons: function() {
return getFilesMapFromReasons;
}
});
const _path = /*#__PURE__*/ _interop_require_default(require("path"));
const _iserror = /*#__PURE__*/ _interop_require_default(require("../../../lib/is-error"));
const _nft = require("next/dist/compiled/@vercel/nft");
const _constants = require("../../../shared/lib/constants");
const _webpack = require("next/dist/compiled/webpack/webpack");
const _webpackconfig = require("../../webpack-config");
const _picomatch = /*#__PURE__*/ _interop_require_default(require("next/dist/compiled/picomatch"));
const _getmodulebuildinfo = require("../loaders/get-module-build-info");
const _entries = require("../../entries");
const _handleexternals = require("../../handle-externals");
const _ismetadataroute = require("../../../lib/metadata/is-metadata-route");
const _utils = require("../utils");
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
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 Map();
parentFilesMap.set(parent, parentFiles);
}
const ignored = Boolean(ignoreFn == null ? void 0 : ignoreFn(file, parent));
parentFiles.set(file, {
ignored
});
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;
}
class TraceEntryPointsPlugin {
constructor({ rootDir, appDir, pagesDir, compilerType, appDirEnabled, traceIgnores, esmExternals, outputFileTracingRoot }){
this.buildTraceContext = {};
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.compilerType = compilerType;
}
// Here we output all traced assets and webpack chunks to a
// ${page}.js.nft.json file
async createTraceAssets(compilation, span) {
const outputPath = compilation.outputOptions.path || '';
await span.traceChild('create-trace-assets').traceAsyncFn(async ()=>{
const entryFilesMap = new Map();
const chunksToTrace = new Set();
const entryNameFilesMap = new Map();
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 = _path.default.join(outputPath, file);
chunksToTrace.add(filePath);
entryFiles.add(filePath);
}
}
for (const file of chunk.auxiliaryFiles){
if (isTraceable(file)) {
const filePath = _path.default.join(outputPath, file);
chunksToTrace.add(filePath);
entryFiles.add(filePath);
}
}
}
entryFilesMap.set(entrypoint, entryFiles);
entryNameFilesMap.set(entrypoint.name || '', [
...entryFiles
]);
}
// startTrace existed and callable
this.buildTraceContext.chunksTrace = {
action: {
action: 'annotate',
input: [
...chunksToTrace
],
contextDirectory: this.tracingRoot,
processCwd: this.rootDir
},
outputPath,
entryNameFilesMap: Object.fromEntries(entryNameFilesMap)
};
// server compiler outputs to `server/chunks` so we traverse up
// one, but edge-server does not so don't for that one
const outputPrefix = this.compilerType === 'server' ? '../' : '';
for (const [entrypoint, entryFiles] of entryFilesMap){
var _this_entryTraces_get;
const traceOutputName = `${outputPrefix}${entrypoint.name}.js.nft.json`;
const traceOutputPath = _path.default.dirname(_path.default.join(outputPath, traceOutputName));
// don't include the entry itself in the trace
entryFiles.delete(_path.default.join(outputPath, `${outputPrefix}${entrypoint.name}.js`));
if (entrypoint.name.startsWith('app/') && this.appDir) {
var _this_buildTraceContext_entriesTrace_absolutePathByEntryName_entrypoint_name, _this_buildTraceContext_entriesTrace;
const appDirRelativeEntryPath = (_this_buildTraceContext_entriesTrace = this.buildTraceContext.entriesTrace) == null ? void 0 : (_this_buildTraceContext_entriesTrace_absolutePathByEntryName_entrypoint_name = _this_buildTraceContext_entriesTrace.absolutePathByEntryName[entrypoint.name]) == null ? void 0 : _this_buildTraceContext_entriesTrace_absolutePathByEntryName_entrypoint_name.replace(this.appDir, '');
const entryIsStaticMetadataRoute = appDirRelativeEntryPath && (0, _ismetadataroute.isMetadataRouteFile)(appDirRelativeEntryPath, [], true);
// Include the client reference manifest in the trace, but not for
// static metadata routes, for which we don't generate those.
if (!entryIsStaticMetadataRoute) {
entryFiles.add(_path.default.join(outputPath, outputPrefix, entrypoint.name.replace(/%5F/g, '_') + '_' + _constants.CLIENT_REFERENCE_MANIFEST + '.js'));
}
}
const finalFiles = [];
await Promise.all([
...new Set([
...entryFiles,
...((_this_entryTraces_get = this.entryTraces.get(entrypoint.name)) == null ? void 0 : _this_entryTraces_get.keys()) || []
])
].map(async (file)=>{
var _this_entryTraces_get;
const fileInfo = (_this_entryTraces_get = this.entryTraces.get(entrypoint.name)) == null ? void 0 : _this_entryTraces_get.get(file);
const relativeFile = _path.default.relative(traceOutputPath, file).replace(/\\/g, '/');
if (file) {
if (!(fileInfo == null ? void 0 : fileInfo.bundled)) {
finalFiles.push(relativeFile);
}
}
}));
compilation.emitAsset(traceOutputName, new _webpack.sources.RawSource(JSON.stringify({
version: _constants.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 absolutePathByEntryName = new Map();
const depModMap = new Map();
await finishModulesSpan.traceChild('get-entries').traceAsyncFn(async ()=>{
for (const [name, entry] of compilation.entries.entries()){
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 = (0, _getmodulebuildinfo.getModuleBuildInfo)(entryMod);
// All loaders that are used to create entries have a `route` property on the buildInfo.
if (moduleBuildInfo.route) {
const absolutePath = (0, _entries.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);
absolutePathByEntryName.set(name, absolutePath);
}
}
// 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, _mod_originalSource1;
const mod = depModMap.get(path) || entryModMap.get(path);
// map the transpiled source when available to avoid
// parse errors in node-file-trace
let source = mod == null ? void 0 : (_mod_originalSource1 = mod.originalSource) == null ? void 0 : (_mod_originalSource = _mod_originalSource1.call(mod)) == null ? void 0 : _mod_originalSource.buffer();
return source || '';
};
const entryPaths = Array.from(entryModMap.keys());
const collectDependencies = async (mod, parent)=>{
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);
await collectDependencies(depMod, parent);
}
}
};
const entriesToTrace = [
...entryPaths
];
for (const entry of entryPaths){
await collectDependencies(entryModMap.get(entry), entry);
const entryName = entryNameMap.get(entry);
const curExtraEntries = additionalEntries.get(entryName);
if (curExtraEntries) {
entriesToTrace.push(...curExtraEntries.keys());
}
}
const contextDirectory = this.tracingRoot;
const chunks = [
...entriesToTrace
];
this.buildTraceContext.entriesTrace = {
action: {
action: 'print',
input: chunks,
contextDirectory,
processCwd: this.rootDir
},
appDir: this.rootDir,
depModArray: Array.from(depModMap.keys()),
entryNameMap: Object.fromEntries(entryNameMap),
absolutePathByEntryName: Object.fromEntries(absolutePathByEntryName),
outputPath: compilation.outputOptions.path
};
let fileList;
let reasons;
const ignores = [
...TRACE_IGNORES,
...this.traceIgnores,
'**/node_modules/**'
];
// pre-compile the ignore matcher to avoid repeating on every ignoreFn call
const isIgnoreMatcher = (0, _picomatch.default)(ignores, {
contains: true,
dot: true
});
const ignoreFn = (path)=>{
return isIgnoreMatcher(path);
};
await finishModulesSpan.traceChild('node-file-trace-plugin', {
traceEntryCount: entriesToTrace.length + ''
}).traceAsyncFn(async ()=>{
const result = await (0, _nft.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 = _path.default.join(this.tracingRoot, file);
const depMod = depModMap.get(file);
const isAsset = (_reasons_get = reasons.get(_path.default.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;
});
for (const entry of entryPaths){
var _parentFilesMap_get;
const entryName = entryNameMap.get(entry);
const normalizedEntry = _path.default.relative(this.tracingRoot, entry);
const curExtraEntries = additionalEntries.get(entryName);
const finalDeps = new Map();
// ensure we include entry source file as well for
// hash comparison
finalDeps.set(entry, {
bundled: true
});
for (const [dep, info] of ((_parentFilesMap_get = parentFilesMap.get(normalizedEntry)) == null ? void 0 : _parentFilesMap_get.entries()) || []){
finalDeps.set(_path.default.join(this.tracingRoot, dep), {
bundled: info.ignored
});
}
if (curExtraEntries) {
for (const extraEntry of curExtraEntries.keys()){
var _parentFilesMap_get1;
const normalizedExtraEntry = _path.default.relative(this.tracingRoot, extraEntry);
finalDeps.set(extraEntry, {
bundled: false
});
for (const [dep, info] of ((_parentFilesMap_get1 = parentFilesMap.get(normalizedExtraEntry)) == null ? void 0 : _parentFilesMap_get1.entries()) || []){
finalDeps.set(_path.default.join(this.tracingRoot, dep), {
bundled: info.ignored
});
}
}
}
this.entryTraces.set(entryName, finalDeps);
}
});
}).then(()=>callback(), (err)=>callback(err));
});
}
apply(compiler) {
compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation)=>{
const compilationSpan = (0, _utils.getCompilationSpan)(compilation) || (0, _utils.getCompilationSpan)(compiler);
const traceEntrypointsPluginSpan = compilationSpan.traceChild('next-trace-entrypoint-plugin');
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 ((0, _iserror.default)(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 ((0, _iserror.default)(e) && (e.code === 'ENOENT' || e.code === 'ENOTDIR')) {
return null;
}
throw e;
}
};
traceEntrypointsPluginSpan.traceFn(()=>{
compilation.hooks.processAssets.tapAsync({
name: PLUGIN_NAME,
stage: _webpack.webpack.Compilation.PROCESS_ASSETS_STAGE_SUMMARIZE
}, (_, callback)=>{
this.createTraceAssets(compilation, traceEntrypointsPluginSpan).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 = _path.default.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(Object.defineProperty(new Error('module not found'), "__NEXT_ERROR_CODE", {
value: "E512",
enumerable: false,
configurable: true
}));
}
// 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 (!_path.default.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) + _path.default.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 = {
..._webpackconfig.NODE_RESOLVE_OPTIONS,
fullySpecified: undefined,
modules: undefined,
extensions: undefined
};
const BASE_CJS_RESOLVE_OPTIONS = {
...CJS_RESOLVE_OPTIONS,
alias: false
};
const ESM_RESOLVE_OPTIONS = {
..._webpackconfig.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 = _path.default.dirname(parent);
// When in esm externals mode, and using import, we resolve with
// ESM resolving options.
const { res } = await (0, _handleexternals.resolveExternal)(this.rootDir, this.esmExternals, context, request, isEsmRequested, (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 Object.defineProperty(new Error(`failed to resolve ${request} from ${parent}`), "__NEXT_ERROR_CODE", {
value: "E361",
enumerable: false,
configurable: true
});
}
return res.replace(/\0/g, '');
};
this.tapfinishModules(compilation, traceEntrypointsPluginSpan, doResolve, readlink, stat);
});
});
}
}
//# sourceMappingURL=next-trace-entrypoints-plugin.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,33 @@
import type { Rewrite, Redirect } from '../../../../lib/load-custom-routes';
import { webpack } from 'next/dist/compiled/webpack/webpack';
import type { PageExtensions } from '../../../page-extensions-type';
type Rewrites = {
fallback: Rewrite[];
afterFiles: Rewrite[];
beforeFiles: Rewrite[];
};
interface Options {
dir: string;
distDir: string;
appDir: string;
dev: boolean;
isEdgeServer: boolean;
pageExtensions: PageExtensions;
originalRewrites: Rewrites | undefined;
originalRedirects: Redirect[] | undefined;
}
export declare class NextTypesPlugin {
dir: string;
distDir: string;
appDir: string;
dev: boolean;
isEdgeServer: boolean;
pageExtensions: string[];
pagesDir: string;
distDirAbsolutePath: string;
constructor(options: Options);
getRelativePathFromAppTypesDir(moduleRelativePathToAppDir: string): string;
collectPage(filePath: string): void;
apply(compiler: webpack.Compiler): void;
}
export {};

View File

@@ -0,0 +1,428 @@
// DO NOT ADD NEW FEATURES TO THIS PLUGIN
// DOING SO PREVENTS THEM FROM WORKING FOR TURBOPACK USERS.
// FOLLOW THE PATTERN OF TYPED-ROUTES AND CACHE-LIFE GENERATION
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "NextTypesPlugin", {
enumerable: true,
get: function() {
return NextTypesPlugin;
}
});
const _promises = /*#__PURE__*/ _interop_require_default(require("fs/promises"));
const _webpack = require("next/dist/compiled/webpack/webpack");
const _path = /*#__PURE__*/ _interop_require_default(require("path"));
const _constants = require("../../../../lib/constants");
const _denormalizepagepath = require("../../../../shared/lib/page-path/denormalize-page-path");
const _ensureleadingslash = require("../../../../shared/lib/page-path/ensure-leading-slash");
const _normalizepathsep = require("../../../../shared/lib/page-path/normalize-path-sep");
const _http = require("../../../../server/web/http");
const _utils = require("../../../../shared/lib/router/utils");
const _apppaths = require("../../../../shared/lib/router/utils/app-paths");
const _entries = require("../../../entries");
const _buildcontext = require("../../../build-context");
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
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, ResolvingViewport } from 'next/dist/lib/metadata/types/metadata-interface.js'`}
import type { PrefetchForTypeCheckInternal } from 'next/dist/build/segment-config/app/app-segment-config.js'
type TEntry = typeof import('${relativePath}.js')
type SegmentParams<T extends Object = any> = T extends Record<string, any>
? { [K in keyof T]: T[K] extends string ? string | string[] | undefined : never }
: T
// Check that the entry is a valid entry
checkFields<Diff<{
${options.type === 'route' ? _http.HTTP_METHODS.map((method)=>`${method}?: Function`).join('\n ') : 'default: Function'}
config?: {}
generateStaticParams?: Function
unstable_prefetch?: PrefetchForTypeCheckInternal
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
viewport?: any
generateViewport?: Function
`}
}, TEntry, ''>>()
${options.type === 'route' ? `type RouteContext = { params: Promise<SegmentParams> }` : ''}
${options.type === 'route' ? _http.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<RouteContext>,
{
__tag__: '${method}'
__param_position__: 'second'
__param_type__: SecondArg<MaybeField<TEntry, '${method}'>>
},
'${method}'
>
>()
${''}
checkFields<
Diff<
{
__tag__: '${method}',
__return_type__: Response | void | never | Promise<Response | void | never>
},
{
__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 generateViewport function
if ('generateViewport' in entry) {
checkFields<Diff<${options.type === 'page' ? 'PageProps' : 'LayoutProps'}, FirstArg<MaybeField<TEntry, 'generateViewport'>>, 'generateViewport'>>()
checkFields<Diff<ResolvingViewport, SecondArg<MaybeField<TEntry, 'generateViewport'>>, 'generateViewport'>>()
}
`}
// Check the arguments and return type of the generateStaticParams function
if ('generateStaticParams' in entry) {
checkFields<Diff<{ params: SegmentParams }, FirstArg<MaybeField<TEntry, 'generateStaticParams'>>, 'generateStaticParams'>>()
checkFields<Diff<{ __tag__: 'generateStaticParams', __return_type__: any[] | Promise<any[]> }, { __tag__: 'generateStaticParams', __return_type__: ReturnType<MaybeField<TEntry, 'generateStaticParams'>> }>>()
}
export interface PageProps {
params?: Promise<SegmentParams>
searchParams?: Promise<any>
}
export interface LayoutProps {
children?: React.ReactNode
${options.slots ? options.slots.map((slot)=>` ${slot}: React.ReactNode`).join('\n') : ''}
params?: Promise<SegmentParams>
}
// =============
// 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.default.dirname(layoutPath);
const items = await _promises.default.readdir(layoutDir, {
withFileTypes: true
});
const slots = [];
for (const item of items){
if (item.isDirectory() && item.name.startsWith('@') && // `@children slots are matched to the children prop, and should not be handled separately for type-checking
item.name !== '@children') {
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 pluginState = (0, _buildcontext.getProxiedPluginState)({
collectedRootParams: {},
routeTypes: {
edge: {
static: [],
dynamic: []
},
node: {
static: [],
dynamic: []
},
extra: {
static: [],
dynamic: []
}
}
});
function formatRouteToRouteType(route) {
const isDynamic = (0, _utils.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: route
};
}
function getRootParamsFromLayouts(layouts) {
// Sort layouts by depth (descending)
const sortedLayouts = Object.entries(layouts).sort((a, b)=>b[0].split('/').length - a[0].split('/').length);
if (!sortedLayouts.length) {
return [];
}
// we assume the shorted layout path is the root layout
let rootLayout = sortedLayouts[sortedLayouts.length - 1][0];
let rootParams = new Set();
let isMultipleRootLayouts = false;
for (const [layoutPath, params] of sortedLayouts){
const allSegmentsAreDynamic = layoutPath.split('/').slice(1, -1)// match dynamic params but not catch-all or optional catch-all
.every((segment)=>/^\[[^[.\]]+\]$/.test(segment));
if (allSegmentsAreDynamic) {
if (isSubpath(rootLayout, layoutPath)) {
// Current path is a subpath of the root layout, update root
rootLayout = layoutPath;
rootParams = new Set(params);
} else {
// Found another potential root layout
isMultipleRootLayouts = true;
// Add any new params
for (const param of params){
rootParams.add(param);
}
}
}
}
// Create result array
const result = Array.from(rootParams).map((param)=>({
param,
optional: isMultipleRootLayouts
}));
return result;
}
function isSubpath(parentLayoutPath, potentialChildLayoutPath) {
// we strip off the `layout` part of the path as those will always conflict with being a subpath
const parentSegments = parentLayoutPath.split('/').slice(1, -1);
const childSegments = potentialChildLayoutPath.split('/').slice(1, -1);
// child segments should be shorter or equal to parent segments to be a subpath
if (childSegments.length > parentSegments.length || !childSegments.length) return false;
// Verify all segment values are equal
return childSegments.every((childSegment, index)=>childSegment === parentSegments[index]);
}
function createServerDefinitions() {
return `
declare module 'next/server' {
import type { AsyncLocalStorage as NodeAsyncLocalStorage } from 'async_hooks'
declare global {
var AsyncLocalStorage: typeof NodeAsyncLocalStorage
}
export { NextFetchEvent } from 'next/dist/server/web/spec-extension/fetch-event'
export { NextRequest } from 'next/dist/server/web/spec-extension/request'
export { NextResponse } from 'next/dist/server/web/spec-extension/response'
export { NextMiddleware, MiddlewareConfig, NextProxy, ProxyConfig } from 'next/dist/server/web/types'
export { userAgentFromString } from 'next/dist/server/web/spec-extension/user-agent'
export { userAgent } from 'next/dist/server/web/spec-extension/user-agent'
export { URLPattern } from 'next/dist/compiled/@edge-runtime/primitives/url'
export { ImageResponse } from 'next/dist/server/web/spec-extension/image-response'
export type { ImageResponseOptions } from 'next/dist/compiled/@vercel/og/types'
export { after } from 'next/dist/server/after'
export { connection } from 'next/dist/server/request/connection'
}
`;
}
const appTypesBasePath = _path.default.join('types', 'app');
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.default.join(this.appDir, '..', 'pages');
this.distDirAbsolutePath = _path.default.join(this.dir, this.distDir);
}
getRelativePathFromAppTypesDir(moduleRelativePathToAppDir) {
const moduleAbsolutePath = _path.default.join(this.appDir, moduleRelativePathToAppDir);
const moduleInAppTypesAbsolutePath = _path.default.join(this.distDirAbsolutePath, appTypesBasePath, moduleRelativePathToAppDir);
return _path.default.relative(moduleInAppTypesAbsolutePath + '/..', moduleAbsolutePath);
}
collectPage(filePath) {
const isApp = filePath.startsWith(this.appDir + _path.default.sep);
const isPages = !isApp && filePath.startsWith(this.pagesDir + _path.default.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 ? _apppaths.normalizeAppPath : _denormalizepagepath.denormalizePagePath)((0, _ensureleadingslash.ensureLeadingSlash)((0, _entries.getPageFromPath)(_path.default.relative(isApp ? this.appDir : this.pagesDir, filePath), this.pageExtensions)));
const { isDynamic, routeType } = formatRouteToRouteType(route);
pluginState.routeTypes[this.isEdgeServer ? 'edge' : 'node'][isDynamic ? 'dynamic' : 'static'].push(routeType);
}
apply(compiler) {
// From asset root to dist root
const assetDirRelative = this.dev ? '..' : this.isEdgeServer ? '..' : '../..';
const handleModule = async (mod, compilation)=>{
if (!mod.resource) return;
const pageExtensionsRegex = new RegExp(`\\.(${this.pageExtensions.join('|')})$`);
if (!pageExtensionsRegex.test(mod.resource)) return;
if (!mod.resource.startsWith(this.appDir + _path.default.sep)) {
if (!this.dev) {
if (mod.resource.startsWith(this.pagesDir + _path.default.sep)) {
this.collectPage(mod.resource);
}
}
return;
}
if (mod.layer !== _constants.WEBPACK_LAYERS.reactServerComponents) return;
// skip for /app/_private dir convention
// matches <app-dir>/**/_*
const IS_PRIVATE = /(?:\/[^/]+)*\/_.*$/.test(mod.resource.replace(this.appDir, ''));
if (IS_PRIVATE) 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 IS_IMPORTABLE = /\.(js|jsx|ts|tsx|mjs|cjs)$/.test(mod.resource);
const relativePathToApp = _path.default.relative(this.appDir, mod.resource);
if (!this.dev) {
if (IS_PAGE || IS_ROUTE) {
this.collectPage(mod.resource);
}
}
const typePath = _path.default.join(appTypesBasePath, relativePathToApp.replace(pageExtensionsRegex, '.ts'));
const relativeImportPath = (0, _normalizepathsep.normalizePathSep)(_path.default.join(this.getRelativePathFromAppTypesDir(relativePathToApp)).replace(pageExtensionsRegex, ''));
const assetPath = _path.default.join(assetDirRelative, typePath);
// Typescript wont allow relative-importing (for example) a .mdx file using the .js extension
// so for now we only generate “type guard files” for files that typescript can transform
if (!IS_IMPORTABLE) return;
if (IS_LAYOUT) {
const rootLayoutPath = (0, _apppaths.normalizeAppPath)((0, _ensureleadingslash.ensureLeadingSlash)((0, _entries.getPageFromPath)(_path.default.relative(this.appDir, mod.resource), this.pageExtensions)));
const foundParams = Array.from(rootLayoutPath.matchAll(/\[(.*?)\]/g), (match)=>match[1]);
pluginState.collectedRootParams[rootLayoutPath] = foundParams;
const slots = await collectNamedSlots(mod.resource);
compilation.emitAsset(assetPath, new _webpack.sources.RawSource(createTypeGuardFile(mod.resource, relativeImportPath, {
type: 'layout',
slots
})));
} else if (IS_PAGE) {
compilation.emitAsset(assetPath, new _webpack.sources.RawSource(createTypeGuardFile(mod.resource, relativeImportPath, {
type: 'page'
})));
} else if (IS_ROUTE) {
compilation.emitAsset(assetPath, new _webpack.sources.RawSource(createTypeGuardFile(mod.resource, relativeImportPath, {
type: 'route'
})));
}
};
compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation)=>{
compilation.hooks.processAssets.tapAsync({
name: PLUGIN_NAME,
stage: _webpack.webpack.Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE_HASH
}, async (_, callback)=>{
const promises = [];
// Clear routes
if (this.isEdgeServer) {
pluginState.routeTypes.edge.dynamic = [];
pluginState.routeTypes.edge.static = [];
} else {
pluginState.routeTypes.node.dynamic = [];
pluginState.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, compilation));
// 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, compilation));
});
}
}
});
});
await Promise.all(promises);
const rootParams = getRootParamsFromLayouts(pluginState.collectedRootParams);
// If we discovered rootParams, we'll override the `next/server` types
// since we're able to determine the root params at build time.
if (rootParams.length > 0) {
const serverTypesPath = _path.default.join(assetDirRelative, 'types/server.d.ts');
compilation.emitAsset(serverTypesPath, new _webpack.sources.RawSource(createServerDefinitions()));
}
// Support `"moduleResolution": "Node16" | "NodeNext"` with `"type": "module"`
const packageJsonAssetPath = _path.default.join(assetDirRelative, 'types/package.json');
compilation.emitAsset(packageJsonAssetPath, new _webpack.sources.RawSource('{"type": "module"}'));
callback();
});
});
}
}
//# sourceMappingURL=index.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
export declare const devPageFiles: Set<string>;

View File

@@ -0,0 +1,14 @@
// TODO: Eliminate this singleton in the future.
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "devPageFiles", {
enumerable: true,
get: function() {
return devPageFiles;
}
});
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"],"sourcesContent":["// TODO: Eliminate this singleton in the future.\nexport const devPageFiles = new Set<string>()\n"],"names":["devPageFiles","Set"],"mappings":"AAAA,gDAAgD;;;;;+BACnCA;;;eAAAA;;;AAAN,MAAMA,eAAe,IAAIC","ignoreList":[0]}

View File

@@ -0,0 +1,12 @@
import type { webpack } from 'next/dist/compiled/webpack/webpack';
type Compiler = webpack.Compiler;
type WebpackPluginInstance = webpack.WebpackPluginInstance;
export declare class NextJsRequireCacheHotReloader implements WebpackPluginInstance {
prevAssets: any;
serverComponents: boolean;
constructor(opts: {
serverComponents: boolean;
});
apply(compiler: Compiler): void;
}
export {};

View File

@@ -0,0 +1,57 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "NextJsRequireCacheHotReloader", {
enumerable: true,
get: function() {
return NextJsRequireCacheHotReloader;
}
});
const _requirecache = require("../../../server/dev/require-cache");
const _sandbox = require("../../../server/web/sandbox");
const _path = /*#__PURE__*/ _interop_require_default(require("path"));
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
const RUNTIME_NAMES = [
'webpack-runtime',
'webpack-api-runtime'
];
const PLUGIN_NAME = 'NextJsRequireCacheHotReloader';
class NextJsRequireCacheHotReloader {
constructor(opts){
this.prevAssets = null;
this.serverComponents = opts.serverComponents;
}
apply(compiler) {
compiler.hooks.assetEmitted.tap(PLUGIN_NAME, (_file, { targetPath })=>{
// Clear module context in this process
(0, _sandbox.clearModuleContext)(targetPath);
(0, _requirecache.deleteCache)(targetPath);
});
compiler.hooks.afterEmit.tapPromise(PLUGIN_NAME, async (compilation)=>{
for (const name of RUNTIME_NAMES){
const runtimeChunkPath = _path.default.join(compilation.outputOptions.path, `${name}.js`);
(0, _requirecache.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
const entries = [
...compilation.entrypoints.keys()
].filter((entry)=>{
const isAppPath = entry.toString().startsWith('app/');
return entry.toString().startsWith('pages/') || isAppPath;
});
for (const page of entries){
const outputPath = _path.default.join(compilation.outputOptions.path, page + '.js');
(0, _requirecache.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"],"sourcesContent":["import type { webpack } from 'next/dist/compiled/webpack/webpack'\nimport { deleteCache } from '../../../server/dev/require-cache'\nimport { clearModuleContext } from '../../../server/web/sandbox'\nimport path from 'path'\n\ntype Compiler = webpack.Compiler\ntype WebpackPluginInstance = webpack.WebpackPluginInstance\n\nconst RUNTIME_NAMES = ['webpack-runtime', 'webpack-api-runtime']\nconst PLUGIN_NAME = 'NextJsRequireCacheHotReloader'\n\n// This plugin flushes require.cache after emitting the files. Providing 'hot reloading' of server files.\nexport class NextJsRequireCacheHotReloader implements WebpackPluginInstance {\n prevAssets: any = null\n serverComponents: boolean\n\n constructor(opts: { serverComponents: boolean }) {\n this.serverComponents = opts.serverComponents\n }\n\n apply(compiler: Compiler) {\n compiler.hooks.assetEmitted.tap(PLUGIN_NAME, (_file, { targetPath }) => {\n // Clear module context in this process\n clearModuleContext(targetPath)\n deleteCache(targetPath)\n })\n\n compiler.hooks.afterEmit.tapPromise(PLUGIN_NAME, async (compilation) => {\n for (const name of RUNTIME_NAMES) {\n const runtimeChunkPath = path.join(\n compilation.outputOptions.path!,\n `${name}.js`\n )\n deleteCache(runtimeChunkPath)\n }\n\n // we need to make sure to clear all server entries from cache\n // since they can have a stale webpack-runtime cache\n // which needs to always be in-sync\n const entries = [...compilation.entrypoints.keys()].filter((entry) => {\n const isAppPath = entry.toString().startsWith('app/')\n return entry.toString().startsWith('pages/') || isAppPath\n })\n\n for (const page of entries) {\n const outputPath = path.join(\n compilation.outputOptions.path!,\n page + '.js'\n )\n deleteCache(outputPath)\n }\n })\n }\n}\n"],"names":["NextJsRequireCacheHotReloader","RUNTIME_NAMES","PLUGIN_NAME","constructor","opts","prevAssets","serverComponents","apply","compiler","hooks","assetEmitted","tap","_file","targetPath","clearModuleContext","deleteCache","afterEmit","tapPromise","compilation","name","runtimeChunkPath","path","join","outputOptions","entries","entrypoints","keys","filter","entry","isAppPath","toString","startsWith","page","outputPath"],"mappings":";;;;+BAYaA;;;eAAAA;;;8BAXe;yBACO;6DAClB;;;;;;AAKjB,MAAMC,gBAAgB;IAAC;IAAmB;CAAsB;AAChE,MAAMC,cAAc;AAGb,MAAMF;IAIXG,YAAYC,IAAmC,CAAE;aAHjDC,aAAkB;QAIhB,IAAI,CAACC,gBAAgB,GAAGF,KAAKE,gBAAgB;IAC/C;IAEAC,MAAMC,QAAkB,EAAE;QACxBA,SAASC,KAAK,CAACC,YAAY,CAACC,GAAG,CAACT,aAAa,CAACU,OAAO,EAAEC,UAAU,EAAE;YACjE,uCAAuC;YACvCC,IAAAA,2BAAkB,EAACD;YACnBE,IAAAA,yBAAW,EAACF;QACd;QAEAL,SAASC,KAAK,CAACO,SAAS,CAACC,UAAU,CAACf,aAAa,OAAOgB;YACtD,KAAK,MAAMC,QAAQlB,cAAe;gBAChC,MAAMmB,mBAAmBC,aAAI,CAACC,IAAI,CAChCJ,YAAYK,aAAa,CAACF,IAAI,EAC9B,GAAGF,KAAK,GAAG,CAAC;gBAEdJ,IAAAA,yBAAW,EAACK;YACd;YAEA,8DAA8D;YAC9D,oDAAoD;YACpD,mCAAmC;YACnC,MAAMI,UAAU;mBAAIN,YAAYO,WAAW,CAACC,IAAI;aAAG,CAACC,MAAM,CAAC,CAACC;gBAC1D,MAAMC,YAAYD,MAAME,QAAQ,GAAGC,UAAU,CAAC;gBAC9C,OAAOH,MAAME,QAAQ,GAAGC,UAAU,CAAC,aAAaF;YAClD;YAEA,KAAK,MAAMG,QAAQR,QAAS;gBAC1B,MAAMS,aAAaZ,aAAI,CAACC,IAAI,CAC1BJ,YAAYK,aAAa,CAACF,IAAI,EAC9BW,OAAO;gBAETjB,IAAAA,yBAAW,EAACkB;YACd;QACF;IACF;AACF","ignoreList":[0]}

View File

@@ -0,0 +1,4 @@
import type { Resolver } from 'webpack';
export declare class OptionalPeerDependencyResolverPlugin {
apply(resolver: Resolver): void;
}

View File

@@ -0,0 +1,45 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "OptionalPeerDependencyResolverPlugin", {
enumerable: true,
get: function() {
return OptionalPeerDependencyResolverPlugin;
}
});
const pluginSymbol = Symbol('OptionalPeerDependencyResolverPlugin');
class OptionalPeerDependencyResolverPlugin {
apply(resolver) {
const target = resolver.ensureHook('raw-module');
target.tapAsync('OptionalPeerDependencyResolverPlugin', (request, resolveContext, callback)=>{
var // popping the stack to prevent the recursion check
_resolveContext_stack;
// if we've already recursed into this plugin, we want to skip it
if (request[pluginSymbol]) {
return callback();
}
(_resolveContext_stack = resolveContext.stack) == null ? void 0 : _resolveContext_stack.delete(Array.from(resolveContext.stack).pop());
resolver.doResolve(target, // when we call doResolve again, we need to make sure we don't
// recurse into this plugin again
{
...request,
[pluginSymbol]: true
}, null, resolveContext, (err, result)=>{
var _request_descriptionFileData;
if (!result && (request == null ? void 0 : (_request_descriptionFileData = request.descriptionFileData) == null ? void 0 : _request_descriptionFileData.peerDependenciesMeta) && request.request) {
const peerDependenciesMeta = request.descriptionFileData.peerDependenciesMeta;
const isOptional = peerDependenciesMeta && peerDependenciesMeta[request.request] && peerDependenciesMeta[request.request].optional;
if (isOptional) {
return callback(null, {
path: false
});
}
}
return callback(err, result);
});
});
}
}
//# sourceMappingURL=optional-peer-dependency-resolve-plugin.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../src/build/webpack/plugins/optional-peer-dependency-resolve-plugin.ts"],"sourcesContent":["import type { Resolver } from 'webpack'\n\nconst pluginSymbol = Symbol('OptionalPeerDependencyResolverPlugin')\n\nexport class OptionalPeerDependencyResolverPlugin {\n apply(resolver: Resolver) {\n const target = resolver.ensureHook('raw-module')\n target.tapAsync(\n 'OptionalPeerDependencyResolverPlugin',\n (request, resolveContext, callback) => {\n // if we've already recursed into this plugin, we want to skip it\n if ((request as any)[pluginSymbol]) {\n return callback()\n }\n\n // popping the stack to prevent the recursion check\n resolveContext.stack?.delete(Array.from(resolveContext.stack).pop()!)\n\n resolver.doResolve(\n target,\n // when we call doResolve again, we need to make sure we don't\n // recurse into this plugin again\n { ...request, [pluginSymbol]: true } as any,\n null,\n resolveContext,\n (err, result) => {\n if (\n !result &&\n request?.descriptionFileData?.peerDependenciesMeta &&\n request.request\n ) {\n const peerDependenciesMeta = request.descriptionFileData\n .peerDependenciesMeta as Record<string, { optional?: boolean }>\n\n const isOptional =\n peerDependenciesMeta &&\n peerDependenciesMeta[request.request] &&\n peerDependenciesMeta[request.request].optional\n\n if (isOptional) {\n return callback(null, {\n path: false,\n })\n }\n }\n\n return callback(err, result)\n }\n )\n }\n )\n }\n}\n"],"names":["OptionalPeerDependencyResolverPlugin","pluginSymbol","Symbol","apply","resolver","target","ensureHook","tapAsync","request","resolveContext","callback","stack","delete","Array","from","pop","doResolve","err","result","descriptionFileData","peerDependenciesMeta","isOptional","optional","path"],"mappings":";;;;+BAIaA;;;eAAAA;;;AAFb,MAAMC,eAAeC,OAAO;AAErB,MAAMF;IACXG,MAAMC,QAAkB,EAAE;QACxB,MAAMC,SAASD,SAASE,UAAU,CAAC;QACnCD,OAAOE,QAAQ,CACb,wCACA,CAACC,SAASC,gBAAgBC;gBAMxB,mDAAmD;YACnDD;YANA,iEAAiE;YACjE,IAAI,AAACD,OAAe,CAACP,aAAa,EAAE;gBAClC,OAAOS;YACT;aAGAD,wBAAAA,eAAeE,KAAK,qBAApBF,sBAAsBG,MAAM,CAACC,MAAMC,IAAI,CAACL,eAAeE,KAAK,EAAEI,GAAG;YAEjEX,SAASY,SAAS,CAChBX,QACA,8DAA8D;YAC9D,iCAAiC;YACjC;gBAAE,GAAGG,OAAO;gBAAE,CAACP,aAAa,EAAE;YAAK,GACnC,MACAQ,gBACA,CAACQ,KAAKC;oBAGFV;gBAFF,IACE,CAACU,WACDV,4BAAAA,+BAAAA,QAASW,mBAAmB,qBAA5BX,6BAA8BY,oBAAoB,KAClDZ,QAAQA,OAAO,EACf;oBACA,MAAMY,uBAAuBZ,QAAQW,mBAAmB,CACrDC,oBAAoB;oBAEvB,MAAMC,aACJD,wBACAA,oBAAoB,CAACZ,QAAQA,OAAO,CAAC,IACrCY,oBAAoB,CAACZ,QAAQA,OAAO,CAAC,CAACc,QAAQ;oBAEhD,IAAID,YAAY;wBACd,OAAOX,SAAS,MAAM;4BACpBa,MAAM;wBACR;oBACF;gBACF;gBAEA,OAAOb,SAASO,KAAKC;YACvB;QAEJ;IAEJ;AACF","ignoreList":[0]}

View File

@@ -0,0 +1,22 @@
import { webpack } from 'next/dist/compiled/webpack/webpack';
export type PagesManifest = {
[page: string]: string;
};
export declare let edgeServerPages: {};
export declare let nodeServerPages: {};
export declare let edgeServerAppPaths: {};
export declare let nodeServerAppPaths: {};
export default class PagesManifestPlugin implements webpack.WebpackPluginInstance {
dev: boolean;
distDir?: string;
isEdgeRuntime: boolean;
appDirEnabled: boolean;
constructor({ dev, distDir, isEdgeRuntime, appDirEnabled, }: {
dev: boolean;
distDir?: string;
isEdgeRuntime: boolean;
appDirEnabled: boolean;
});
createAssets(compilation: any): Promise<void>;
apply(compiler: webpack.Compiler): void;
}

View File

@@ -0,0 +1,146 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
0 && (module.exports = {
default: null,
edgeServerAppPaths: null,
edgeServerPages: null,
nodeServerAppPaths: null,
nodeServerPages: null
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
// 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
default: function() {
return PagesManifestPlugin;
},
edgeServerAppPaths: function() {
return edgeServerAppPaths;
},
edgeServerPages: function() {
return edgeServerPages;
},
nodeServerAppPaths: function() {
return nodeServerAppPaths;
},
nodeServerPages: function() {
return nodeServerPages;
}
});
const _path = /*#__PURE__*/ _interop_require_default(require("path"));
const _promises = /*#__PURE__*/ _interop_require_default(require("fs/promises"));
const _webpack = require("next/dist/compiled/webpack/webpack");
const _constants = require("../../../shared/lib/constants");
const _getroutefromentrypoint = /*#__PURE__*/ _interop_require_default(require("../../../server/get-route-from-entrypoint"));
const _normalizepathsep = require("../../../shared/lib/page-path/normalize-path-sep");
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
let edgeServerPages = {};
let nodeServerPages = {};
let edgeServerAppPaths = {};
let nodeServerAppPaths = {};
class PagesManifestPlugin {
constructor({ dev, distDir, isEdgeRuntime, appDirEnabled }){
this.dev = dev;
this.distDir = distDir;
this.isEdgeRuntime = isEdgeRuntime;
this.appDirEnabled = appDirEnabled;
}
async createAssets(compilation) {
const entrypoints = compilation.entrypoints;
const pages = {};
const appPaths = {};
for (const entrypoint of entrypoints.values()){
const pagePath = (0, _getroutefromentrypoint.default)(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 = (0, _normalizepathsep.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;
}
// handle parallel compilers writing to the same
// manifest path by merging existing manifest with new
const writeMergedManifest = async (manifestPath, entries)=>{
await _promises.default.mkdir(_path.default.dirname(manifestPath), {
recursive: true
});
await _promises.default.writeFile(manifestPath, JSON.stringify({
...await _promises.default.readFile(manifestPath, 'utf8').then((res)=>JSON.parse(res)).catch(()=>({})),
...entries
}, null, 2));
};
if (this.distDir) {
const pagesManifestPath = _path.default.join(this.distDir, 'server', _constants.PAGES_MANIFEST);
await writeMergedManifest(pagesManifestPath, {
...edgeServerPages,
...nodeServerPages
});
} else {
const pagesManifestPath = (!this.dev && !this.isEdgeRuntime ? '../' : '') + _constants.PAGES_MANIFEST;
compilation.emitAsset(pagesManifestPath, new _webpack.sources.RawSource(JSON.stringify({
...edgeServerPages,
...nodeServerPages
}, null, 2)));
}
if (this.appDirEnabled) {
if (this.distDir) {
const appPathsManifestPath = _path.default.join(this.distDir, 'server', _constants.APP_PATHS_MANIFEST);
await writeMergedManifest(appPathsManifestPath, {
...edgeServerAppPaths,
...nodeServerAppPaths
});
} else {
compilation.emitAsset((!this.dev && !this.isEdgeRuntime ? '../' : '') + _constants.APP_PATHS_MANIFEST, new _webpack.sources.RawSource(JSON.stringify({
...edgeServerAppPaths,
...nodeServerAppPaths
}, null, 2)));
}
}
}
apply(compiler) {
compiler.hooks.make.tap('NextJsPagesManifest', (compilation)=>{
compilation.hooks.processAssets.tapPromise({
name: 'NextJsPagesManifest',
stage: _webpack.webpack.Compilation.PROCESS_ASSETS_STAGE_ADDITIONS
}, ()=>this.createAssets(compilation));
});
}
}
//# sourceMappingURL=pages-manifest-plugin.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,22 @@
import type { Span } from '../../../trace';
import type { webpack } from 'next/dist/compiled/webpack/webpack';
export declare const spans: WeakMap<webpack.Compiler | webpack.Compilation, Span>;
export declare const webpackInvalidSpans: WeakMap<any, Span>;
export declare class ProfilingPlugin {
compiler: any;
runWebpackSpan: Span;
rootDir: string;
constructor({ runWebpackSpan, rootDir, }: {
runWebpackSpan: Span;
rootDir: string;
});
apply(compiler: any): void;
traceHookPair(spanName: string | (() => string), startHook: any, stopHook: any, { parentSpan, attrs, onStart, onStop, }?: {
parentSpan?: (...params: any[]) => Span;
attrs?: any;
onStart?: (span: Span, ...params: any[]) => void;
onStop?: (span: Span, ...params: any[]) => void;
}): void;
traceTopLevelHooks(compiler: any): void;
traceCompilationHooks(compiler: any): void;
}

View File

@@ -0,0 +1,282 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
0 && (module.exports = {
ProfilingPlugin: null,
spans: null,
webpackInvalidSpans: null
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
ProfilingPlugin: function() {
return ProfilingPlugin;
},
spans: function() {
return spans;
},
webpackInvalidSpans: function() {
return webpackInvalidSpans;
}
});
const _webpack = require("next/dist/compiled/webpack/webpack");
const _path = /*#__PURE__*/ _interop_require_default(require("path"));
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
const pluginName = 'ProfilingPlugin';
const spans = new WeakMap();
const moduleSpansByCompilation = new WeakMap();
const makeSpanByCompilation = new WeakMap();
const sealSpanByCompilation = new WeakMap();
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));
}
class ProfilingPlugin {
constructor({ runWebpackSpan, rootDir }){
this.runWebpackSpan = runWebpackSpan;
this.rootDir = rootDir;
}
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 ? _path.default.relative(this.rootDir, fileName).replaceAll(_path.default.sep, '/') : '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, (module1)=>{
var _compilation_moduleGraph;
const moduleType = (()=>{
const r = module1.userRequest;
if (!r || r.endsWith('!')) {
return '';
} else {
const resource = r.split('!').pop();
const match = /^[^?]+\.([^?]+)$/.exec(resource);
return match ? match[1] : '';
}
})();
const issuerModule = compilation == null ? void 0 : (_compilation_moduleGraph = compilation.moduleGraph) == null ? void 0 : _compilation_moduleGraph.getIssuer(module1);
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(module1)){
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', module1.userRequest);
span.setAttribute('layer', module1.layer);
moduleSpans.set(module1, span);
});
const moduleHooks = _webpack.NormalModule.getCompilationHooks(compilation);
moduleHooks.readResource.for(undefined).intercept({
register (tapInfo) {
const fn = tapInfo.fn;
tapInfo.fn = (loaderContext, callback)=>{
fn(loaderContext, (err, result)=>{
callback(err, result);
});
};
return tapInfo;
}
});
moduleHooks.loader.tap(pluginName, (loaderContext, module1)=>{
var _moduleSpansByCompilation_get;
const moduleSpan = (_moduleSpansByCompilation_get = moduleSpansByCompilation.get(compilation)) == null ? void 0 : _moduleSpansByCompilation_get.get(module1);
loaderContext.currentTraceSpan = moduleSpan;
});
compilation.hooks.succeedModule.tap(pluginName, (module1)=>{
var _moduleSpansByCompilation_get_get, _moduleSpansByCompilation_get;
moduleSpansByCompilation == null ? void 0 : (_moduleSpansByCompilation_get = moduleSpansByCompilation.get(compilation)) == null ? void 0 : (_moduleSpansByCompilation_get_get = _moduleSpansByCompilation_get.get(module1)) == null ? void 0 : _moduleSpansByCompilation_get_get.stop();
});
compilation.hooks.failedModule.tap(pluginName, (module1)=>{
var _moduleSpansByCompilation_get_get, _moduleSpansByCompilation_get;
moduleSpansByCompilation == null ? void 0 : (_moduleSpansByCompilation_get = moduleSpansByCompilation.get(compilation)) == null ? void 0 : (_moduleSpansByCompilation_get_get = _moduleSpansByCompilation_get.get(module1)) == 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,37 @@
/**
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
*/
import { webpack } from 'next/dist/compiled/webpack/webpack';
export declare class ReactLoadablePlugin {
private filename;
private pagesOrAppDir;
private isPagesDir;
private runtimeAsset?;
private dev;
constructor(opts: {
filename: string;
pagesDir?: string;
appDir?: string;
runtimeAsset?: string;
dev: boolean;
});
createAssets(compiler: any, compilation: any): void;
apply(compiler: webpack.Compiler): void;
}

View File

@@ -0,0 +1,169 @@
/**
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
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "ReactLoadablePlugin", {
enumerable: true,
get: function() {
return ReactLoadablePlugin;
}
});
const _path = /*#__PURE__*/ _interop_require_default(require("path"));
const _webpack = require("next/dist/compiled/webpack/webpack");
const _constants = require("../../../shared/lib/constants");
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
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, projectSrcDir, dev, shouldCreateDynamicCssManifest) {
if (!projectSrcDir) {
return {
reactLoadableManifest: {},
dynamicCssManifest: []
};
}
const dynamicCssManifestSet = new Set();
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.default.relative(projectSrcDir, 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);
if (shouldCreateDynamicCssManifest && file.endsWith('.css')) {
dynamicCssManifestSet.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 {
reactLoadableManifest: manifest,
dynamicCssManifest: Array.from(dynamicCssManifestSet)
};
}
class ReactLoadablePlugin {
constructor(opts){
this.filename = opts.filename;
this.pagesOrAppDir = opts.pagesDir || opts.appDir;
this.isPagesDir = Boolean(opts.pagesDir);
this.runtimeAsset = opts.runtimeAsset;
this.dev = opts.dev;
}
createAssets(compiler, compilation) {
const projectSrcDir = this.pagesOrAppDir ? _path.default.dirname(this.pagesOrAppDir) : undefined;
const shouldCreateDynamicCssManifest = !this.dev && this.isPagesDir;
const { reactLoadableManifest, dynamicCssManifest } = buildManifest(compiler, compilation, projectSrcDir, this.dev, shouldCreateDynamicCssManifest);
compilation.emitAsset(this.filename, new _webpack.sources.RawSource(JSON.stringify(reactLoadableManifest, null, 2)));
if (this.runtimeAsset) {
compilation.emitAsset(this.runtimeAsset, new _webpack.sources.RawSource(`self.__REACT_LOADABLE_MANIFEST=${JSON.stringify(JSON.stringify(reactLoadableManifest))}`));
}
// This manifest prevents removing server rendered <link> tags after client
// navigation. This is only needed under Pages dir && Production && Webpack.
// x-ref: https://github.com/vercel/next.js/pull/72959
if (shouldCreateDynamicCssManifest) {
compilation.emitAsset(`${_constants.DYNAMIC_CSS_MANIFEST}.json`, new _webpack.sources.RawSource(JSON.stringify(dynamicCssManifest, null, 2)));
// This is for edge runtime.
compilation.emitAsset(`server/${_constants.DYNAMIC_CSS_MANIFEST}.js`, new _webpack.sources.RawSource(`self.__DYNAMIC_CSS_MANIFEST=${JSON.stringify(JSON.stringify(dynamicCssManifest))}`));
}
}
apply(compiler) {
compiler.hooks.make.tap('ReactLoadableManifest', (compilation)=>{
compilation.hooks.processAssets.tap({
name: 'ReactLoadableManifest',
stage: _webpack.webpack.Compilation.PROCESS_ASSETS_STAGE_ADDITIONS
}, ()=>{
this.createAssets(compiler, compilation);
});
});
}
}
//# sourceMappingURL=react-loadable-plugin.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,36 @@
import type { Compiler } from '@rspack/core';
type Actions = {
[actionId: string]: {
workers: {
[name: string]: {
moduleId: string | number;
async: boolean;
};
};
layer: {
[name: string]: string;
};
};
};
export type ActionManifest = {
encryptionKey: string;
node: Actions;
edge: Actions;
};
export interface ModuleInfo {
moduleId: string | number;
async: boolean;
}
interface Options {
dev: boolean;
appDir: string;
isEdgeServer: boolean;
encryptionKey: string;
}
export declare class RspackFlightClientEntryPlugin {
plugin: any;
compiler?: Compiler;
constructor(options: Options);
apply(compiler: Compiler): void;
}
export {};

View File

@@ -0,0 +1,97 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "RspackFlightClientEntryPlugin", {
enumerable: true,
get: function() {
return RspackFlightClientEntryPlugin;
}
});
const _ondemandentryhandler = require("../../../server/dev/on-demand-entry-handler");
const _constants = require("../../../shared/lib/constants");
const _buildcontext = require("../../build-context");
const _pagetypes = require("../../../lib/page-types");
const _getrspack = require("../../../shared/lib/get-rspack");
const pluginState = (0, _buildcontext.getProxiedPluginState)({
// A map to track "action" -> "list of bundles".
serverActions: {},
edgeServerActions: {},
serverActionModules: {},
edgeServerActionModules: {},
ssrModules: {},
edgeSsrModules: {},
rscModules: {},
edgeRscModules: {},
injectedClientEntries: {}
});
class RspackFlightClientEntryPlugin {
constructor(options){
const { FlightClientEntryPlugin } = (0, _getrspack.getRspackCore)();
this.plugin = new FlightClientEntryPlugin({
...options,
builtinAppLoader: !!process.env.BUILTIN_SWC_LOADER,
shouldInvalidateCb: ({ bundlePath, entryName, absolutePagePath, clientBrowserLoader })=>{
let shouldInvalidate = false;
const compiler = this.compiler;
const entries = (0, _ondemandentryhandler.getEntries)(compiler.outputPath);
const pageKey = (0, _ondemandentryhandler.getEntryKey)(_constants.COMPILER_NAMES.client, _pagetypes.PAGE_TYPES.APP, bundlePath);
if (!entries[pageKey]) {
entries[pageKey] = {
type: _ondemandentryhandler.EntryTypes.CHILD_ENTRY,
parentEntries: new Set([
entryName
]),
absoluteEntryFilePath: absolutePagePath,
bundlePath,
request: clientBrowserLoader,
dispose: false,
lastActiveTime: Date.now()
};
shouldInvalidate = true;
} else {
const entryData = entries[pageKey];
// New version of the client loader
if (entryData.request !== clientBrowserLoader) {
entryData.request = clientBrowserLoader;
shouldInvalidate = true;
}
if (entryData.type === _ondemandentryhandler.EntryTypes.CHILD_ENTRY) {
entryData.parentEntries.add(entryName);
}
entryData.dispose = false;
entryData.lastActiveTime = Date.now();
}
return shouldInvalidate;
},
invalidateCb: ()=>{
const compiler = this.compiler;
// Invalidate in development to trigger recompilation
const invalidator = (0, _ondemandentryhandler.getInvalidator)(compiler.outputPath);
// Check if any of the entry injections need an invalidation
if (invalidator) {
invalidator.invalidate([
_constants.COMPILER_NAMES.client
]);
}
},
stateCb: (state)=>{
Object.assign(pluginState.serverActions, state.serverActions);
Object.assign(pluginState.edgeServerActions, state.edgeServerActions);
Object.assign(pluginState.serverActionModules, state.serverActionModules);
Object.assign(pluginState.edgeServerActionModules, state.edgeServerActionModules);
Object.assign(pluginState.ssrModules, state.ssrModules);
Object.assign(pluginState.edgeSsrModules, state.edgeSsrModules);
Object.assign(pluginState.rscModules, state.rscModules);
Object.assign(pluginState.edgeRscModules, state.edgeRscModules);
Object.assign(pluginState.injectedClientEntries, state.injectedClientEntries);
}
});
}
apply(compiler) {
this.compiler = compiler;
this.plugin.apply(compiler);
}
}
//# sourceMappingURL=rspack-flight-client-entry-plugin.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,9 @@
import type { Span } from '../../../trace';
export declare const compilationSpans: WeakMap<any, Span>;
export declare class RspackProfilingPlugin {
runWebpackSpan: Span;
constructor({ runWebpackSpan }: {
runWebpackSpan: Span;
});
apply(compiler: any): void;
}

View File

@@ -0,0 +1,62 @@
// A basic implementation to allow loaders access to loaderContext.currentTraceSpan
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
0 && (module.exports = {
RspackProfilingPlugin: null,
compilationSpans: null
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
RspackProfilingPlugin: function() {
return RspackProfilingPlugin;
},
compilationSpans: function() {
return compilationSpans;
}
});
const _getrspack = require("../../../shared/lib/get-rspack");
const pluginName = 'RspackProfilingPlugin';
const moduleSpansByCompilation = new WeakMap();
const compilationSpans = new WeakMap();
class RspackProfilingPlugin {
constructor({ runWebpackSpan }){
this.runWebpackSpan = runWebpackSpan;
}
apply(compiler) {
compiler.hooks.thisCompilation.tap({
name: pluginName,
stage: -Infinity
}, (compilation)=>{
const rspack = (0, _getrspack.getRspackCore)();
moduleSpansByCompilation.set(compilation, new WeakMap());
compilationSpans.set(compilation, this.runWebpackSpan.traceChild('compilation-' + compilation.name));
const compilationSpan = this.runWebpackSpan.traceChild(`compilation-${compilation.name}`);
const moduleHooks = rspack.NormalModule.getCompilationHooks(compilation);
moduleHooks.loader.tap(pluginName, (loaderContext, module1)=>{
var _moduleSpansByCompilation_get;
const moduleSpan = (_moduleSpansByCompilation_get = moduleSpansByCompilation.get(compilation)) == null ? void 0 : _moduleSpansByCompilation_get.get(module1);
loaderContext.currentTraceSpan = moduleSpan;
});
compilation.hooks.buildModule.tap(pluginName, (module1)=>{
var _moduleSpansByCompilation_get;
const span = compilationSpan.traceChild('build-module');
span.setAttribute('name', module1.userRequest);
span.setAttribute('layer', module1.layer);
moduleSpansByCompilation == null ? void 0 : (_moduleSpansByCompilation_get = moduleSpansByCompilation.get(compilation)) == null ? void 0 : _moduleSpansByCompilation_get.set(module1, span);
});
compilation.hooks.succeedModule.tap(pluginName, (module1)=>{
var _moduleSpansByCompilation_get_get, _moduleSpansByCompilation_get;
moduleSpansByCompilation == null ? void 0 : (_moduleSpansByCompilation_get = moduleSpansByCompilation.get(compilation)) == null ? void 0 : (_moduleSpansByCompilation_get_get = _moduleSpansByCompilation_get.get(module1)) == null ? void 0 : _moduleSpansByCompilation_get_get.stop();
});
});
}
}
//# sourceMappingURL=rspack-profiling-plugin.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../src/build/webpack/plugins/rspack-profiling-plugin.ts"],"sourcesContent":["// A basic implementation to allow loaders access to loaderContext.currentTraceSpan\n\nimport type { Span } from '../../../trace'\n\nimport { getRspackCore } from '../../../shared/lib/get-rspack'\n\nconst pluginName = 'RspackProfilingPlugin'\nconst moduleSpansByCompilation = new WeakMap()\nexport const compilationSpans: WeakMap<any, Span> = new WeakMap()\n\nexport class RspackProfilingPlugin {\n runWebpackSpan: Span\n\n constructor({ runWebpackSpan }: { runWebpackSpan: Span }) {\n this.runWebpackSpan = runWebpackSpan\n }\n\n apply(compiler: any) {\n compiler.hooks.thisCompilation.tap(\n { name: pluginName, stage: -Infinity },\n (compilation: any) => {\n const rspack = getRspackCore()\n\n moduleSpansByCompilation.set(compilation, new WeakMap())\n compilationSpans.set(\n compilation,\n this.runWebpackSpan.traceChild('compilation-' + compilation.name)\n )\n\n const compilationSpan = this.runWebpackSpan.traceChild(\n `compilation-${compilation.name}`\n )\n\n const moduleHooks = rspack.NormalModule.getCompilationHooks(compilation)\n moduleHooks.loader.tap(\n pluginName,\n (loaderContext: any, module: any) => {\n const moduleSpan = moduleSpansByCompilation\n .get(compilation)\n ?.get(module)\n loaderContext.currentTraceSpan = moduleSpan\n }\n )\n\n compilation.hooks.buildModule.tap(pluginName, (module: any) => {\n const span = compilationSpan.traceChild('build-module')\n span.setAttribute('name', module.userRequest)\n span.setAttribute('layer', module.layer)\n\n moduleSpansByCompilation?.get(compilation)?.set(module, span)\n })\n\n compilation.hooks.succeedModule.tap(pluginName, (module: any) => {\n moduleSpansByCompilation?.get(compilation)?.get(module)?.stop()\n })\n }\n )\n }\n}\n"],"names":["RspackProfilingPlugin","compilationSpans","pluginName","moduleSpansByCompilation","WeakMap","constructor","runWebpackSpan","apply","compiler","hooks","thisCompilation","tap","name","stage","Infinity","compilation","rspack","getRspackCore","set","traceChild","compilationSpan","moduleHooks","NormalModule","getCompilationHooks","loader","loaderContext","module","moduleSpan","get","currentTraceSpan","buildModule","span","setAttribute","userRequest","layer","succeedModule","stop"],"mappings":"AAAA,mFAAmF;;;;;;;;;;;;;;;;IAUtEA,qBAAqB;eAArBA;;IAFAC,gBAAgB;eAAhBA;;;2BAJiB;AAE9B,MAAMC,aAAa;AACnB,MAAMC,2BAA2B,IAAIC;AAC9B,MAAMH,mBAAuC,IAAIG;AAEjD,MAAMJ;IAGXK,YAAY,EAAEC,cAAc,EAA4B,CAAE;QACxD,IAAI,CAACA,cAAc,GAAGA;IACxB;IAEAC,MAAMC,QAAa,EAAE;QACnBA,SAASC,KAAK,CAACC,eAAe,CAACC,GAAG,CAChC;YAAEC,MAAMV;YAAYW,OAAO,CAACC;QAAS,GACrC,CAACC;YACC,MAAMC,SAASC,IAAAA,wBAAa;YAE5Bd,yBAAyBe,GAAG,CAACH,aAAa,IAAIX;YAC9CH,iBAAiBiB,GAAG,CAClBH,aACA,IAAI,CAACT,cAAc,CAACa,UAAU,CAAC,iBAAiBJ,YAAYH,IAAI;YAGlE,MAAMQ,kBAAkB,IAAI,CAACd,cAAc,CAACa,UAAU,CACpD,CAAC,YAAY,EAAEJ,YAAYH,IAAI,EAAE;YAGnC,MAAMS,cAAcL,OAAOM,YAAY,CAACC,mBAAmB,CAACR;YAC5DM,YAAYG,MAAM,CAACb,GAAG,CACpBT,YACA,CAACuB,eAAoBC;oBACAvB;gBAAnB,MAAMwB,cAAaxB,gCAAAA,yBAChByB,GAAG,CAACb,iCADYZ,8BAEfyB,GAAG,CAACF;gBACRD,cAAcI,gBAAgB,GAAGF;YACnC;YAGFZ,YAAYN,KAAK,CAACqB,WAAW,CAACnB,GAAG,CAACT,YAAY,CAACwB;oBAK7CvB;gBAJA,MAAM4B,OAAOX,gBAAgBD,UAAU,CAAC;gBACxCY,KAAKC,YAAY,CAAC,QAAQN,QAAOO,WAAW;gBAC5CF,KAAKC,YAAY,CAAC,SAASN,QAAOQ,KAAK;gBAEvC/B,6CAAAA,gCAAAA,yBAA0ByB,GAAG,CAACb,iCAA9BZ,8BAA4Ce,GAAG,CAACQ,SAAQK;YAC1D;YAEAhB,YAAYN,KAAK,CAAC0B,aAAa,CAACxB,GAAG,CAACT,YAAY,CAACwB;oBAC/CvB,mCAAAA;gBAAAA,6CAAAA,gCAAAA,yBAA0ByB,GAAG,CAACb,kCAA9BZ,oCAAAA,8BAA4CyB,GAAG,CAACF,6BAAhDvB,kCAAyDiC,IAAI;YAC/D;QACF;IAEJ;AACF","ignoreList":[0]}

View File

@@ -0,0 +1,12 @@
import type { Compiler } from 'webpack';
import type { CompilerNameValues } from '../../../shared/lib/constants';
interface ModuleBuildTimeAnalyzerOptions {
compilerType: CompilerNameValues;
buildTimeThresholdMs: number;
}
export default class SlowModuleDetectionPlugin {
private options;
constructor(options: ModuleBuildTimeAnalyzerOptions);
apply: (compiler: Compiler) => void;
}
export {};

View File

@@ -0,0 +1,190 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "default", {
enumerable: true,
get: function() {
return SlowModuleDetectionPlugin;
}
});
const _picocolors = require("../../../lib/picocolors");
const PLUGIN_NAME = 'SlowModuleDetectionPlugin';
const TreeSymbols = {
VERTICAL_LINE: '│ ',
BRANCH: '├─ '
};
const PATH_TRUNCATION_LENGTH = 120;
// Matches node_modules paths, including pnpm-style paths
const NODE_MODULES_PATH_PATTERN = /node_modules(?:\/\.pnpm)?\/(.*)/;
const getModuleIdentifier = (module)=>{
const debugId = module.debugId;
return String(debugId);
};
const getModuleDisplayName = (module)=>{
const resourcePath = 'resource' in module && typeof module.resource === 'string' ? module.resource : undefined;
if (!resourcePath) {
return undefined;
}
let displayPath = resourcePath.replace(process.cwd(), '.');
const nodeModulesMatch = displayPath.match(NODE_MODULES_PATH_PATTERN);
if (nodeModulesMatch) {
return nodeModulesMatch[1];
}
return displayPath;
};
/**
* Truncates a path to a maximum length. If the path exceeds this length,
* it will be truncated in the middle and replaced with '...'.
*/ function truncatePath(path, maxLength) {
// If the path length is within the limit, return it as is
if (path.length <= maxLength) return path;
// Calculate the available length for the start and end segments after accounting for '...'
const availableLength = maxLength - 3;
const startSegmentLength = Math.ceil(availableLength / 2);
const endSegmentLength = Math.floor(availableLength / 2);
// Extract the start and end segments of the path
const startSegment = path.slice(0, startSegmentLength);
const endSegment = path.slice(-endSegmentLength);
// Return the truncated path with '...' in the middle
return `${startSegment}...${endSegment}`;
}
class ModuleBuildTimeAnalyzer {
constructor(options){
this.options = options;
this.pendingModules = [];
this.modules = new Map();
this.moduleParents = new Map();
this.moduleChildren = new Map();
this.isFinalized = false;
this.moduleBuildTimes = new WeakMap();
this.buildTimeThresholdMs = options.buildTimeThresholdMs;
}
recordModuleBuildTime(module, duration) {
// Webpack guarantees that no more modules will be built after finishModules hook is called,
// where we generate the report. This check is just a defensive measure.
if (this.isFinalized) {
throw Object.defineProperty(new Error(`Invariant (SlowModuleDetectionPlugin): Module is recorded after the report is generated. This is a Next.js internal bug.`), "__NEXT_ERROR_CODE", {
value: "E630",
enumerable: false,
configurable: true
});
}
if (duration < this.buildTimeThresholdMs) {
return; // Skip fast modules
}
this.moduleBuildTimes.set(module, duration);
this.pendingModules.push(module);
}
/**
* For each slow module, traverses up the dependency chain to find all ancestor modules.
* Builds a directed graph where:
* 1. Each slow module and its ancestors become nodes
* 2. Edges represent "imported by" relationships
* 3. Root nodes are entry points with no parents
*
* The resulting graph allows us to visualize the import chains that led to slow builds.
*/ prepareReport(compilation) {
for (const module of this.pendingModules){
const chain = new Set();
// Walk up the module graph until we hit a root module (no issuer) to populate the chain
{
let currentModule = module;
chain.add(currentModule);
while(true){
const issuerModule = compilation.moduleGraph.getIssuer(currentModule);
if (!issuerModule) break;
if (chain.has(issuerModule)) {
throw Object.defineProperty(new Error(`Invariant (SlowModuleDetectionPlugin): Circular dependency detected in module graph. This is a Next.js internal bug.`), "__NEXT_ERROR_CODE", {
value: "E631",
enumerable: false,
configurable: true
});
}
chain.add(issuerModule);
currentModule = issuerModule;
}
}
// Add all visited modules to our graph and create parent-child relationships
let previousModule = null;
for (const currentModule of chain){
const moduleId = getModuleIdentifier(currentModule);
if (!this.modules.has(moduleId)) {
this.modules.set(moduleId, currentModule);
}
if (previousModule) {
this.moduleParents.set(previousModule, currentModule);
let parentChildren = this.moduleChildren.get(currentModule);
if (!parentChildren) {
parentChildren = new Map();
this.moduleChildren.set(currentModule, parentChildren);
}
parentChildren.set(getModuleIdentifier(previousModule), previousModule);
}
previousModule = currentModule;
}
}
this.isFinalized = true;
}
generateReport(compilation) {
if (!this.isFinalized) {
this.prepareReport(compilation);
}
// Find root modules (those with no parents)
const rootModules = [
...this.modules.values()
].filter((node)=>!this.moduleParents.has(node));
const formatModuleNode = (node, depth)=>{
const moduleName = getModuleDisplayName(node) || '';
if (!moduleName) {
return formatChildModules(node, depth);
}
const prefix = ' ' + TreeSymbols.VERTICAL_LINE.repeat(depth) + TreeSymbols.BRANCH;
const moduleText = (0, _picocolors.blue)(truncatePath(moduleName, PATH_TRUNCATION_LENGTH - prefix.length));
const buildTimeMs = this.moduleBuildTimes.get(node);
const duration = buildTimeMs ? (0, _picocolors.yellow)(` (${Math.ceil(buildTimeMs)}ms)`) : '';
return prefix + moduleText + duration + '\n' + formatChildModules(node, depth + 1);
};
const formatChildModules = (node, depth)=>{
const children = this.moduleChildren.get(node);
if (!children) return '';
return [
...children
].map(([_, child])=>formatModuleNode(child, depth)).join('');
};
const report = rootModules.map((root)=>formatModuleNode(root, 0)).join('');
if (report) {
console.log((0, _picocolors.green)(`🐌 Detected slow modules while compiling ${this.options.compilerType}:`) + '\n' + report);
}
}
}
class SlowModuleDetectionPlugin {
constructor(options){
this.options = options;
this.apply = (compiler)=>{
compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation)=>{
const analyzer = new ModuleBuildTimeAnalyzer(this.options);
const moduleBuildStartTimes = new WeakMap();
compilation.hooks.buildModule.tap(PLUGIN_NAME, (module)=>{
moduleBuildStartTimes.set(module, performance.now());
});
compilation.hooks.succeedModule.tap(PLUGIN_NAME, (module)=>{
const startTime = moduleBuildStartTimes.get(module);
if (!startTime) {
throw Object.defineProperty(new Error(`Invariant (SlowModuleDetectionPlugin): Unable to find the start time for a module build. This is a Next.js internal bug.`), "__NEXT_ERROR_CODE", {
value: "E629",
enumerable: false,
configurable: true
});
}
analyzer.recordModuleBuildTime(module, performance.now() - startTime);
});
compilation.hooks.finishModules.tap(PLUGIN_NAME, ()=>{
analyzer.generateReport(compilation);
});
});
};
}
}
//# sourceMappingURL=slow-module-detection-plugin.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,7 @@
import { webpack } from 'next/dist/compiled/webpack/webpack';
export type SubresourceIntegrityAlgorithm = 'sha256' | 'sha384' | 'sha512';
export declare class SubresourceIntegrityPlugin {
private readonly algorithm;
constructor(algorithm: SubresourceIntegrityAlgorithm);
apply(compiler: webpack.Compiler): void;
}

View File

@@ -0,0 +1,62 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "SubresourceIntegrityPlugin", {
enumerable: true,
get: function() {
return SubresourceIntegrityPlugin;
}
});
const _webpack = require("next/dist/compiled/webpack/webpack");
const _crypto = /*#__PURE__*/ _interop_require_default(require("crypto"));
const _constants = require("../../../shared/lib/constants");
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
const PLUGIN_NAME = 'SubresourceIntegrityPlugin';
class SubresourceIntegrityPlugin {
constructor(algorithm){
this.algorithm = algorithm;
}
apply(compiler) {
compiler.hooks.make.tap(PLUGIN_NAME, (compilation)=>{
compilation.hooks.afterProcessAssets.tap({
name: PLUGIN_NAME,
stage: _webpack.webpack.Compilation.PROCESS_ASSETS_STAGE_ADDITIONS
}, ()=>{
// 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 = compilation.getAsset(file);
if (!asset) {
throw Object.defineProperty(new Error(`could not get asset: ${file}`), "__NEXT_ERROR_CODE", {
value: "E349",
enumerable: false,
configurable: true
});
}
// Get the buffer for the asset.
const buffer = asset.source.buffer();
// Create the hash for the content.
const hash = _crypto.default.createHash(this.algorithm).update(buffer).digest().toString('base64');
hashes[file] = `${this.algorithm}-${hash}`;
}
const json = JSON.stringify(hashes, null, 2);
const file = 'server/' + _constants.SUBRESOURCE_INTEGRITY_MANIFEST;
compilation.emitAsset(file + '.js', new _webpack.sources.RawSource(`self.__SUBRESOURCE_INTEGRITY_MANIFEST=${JSON.stringify(json)}`));
compilation.emitAsset(file + '.json', new _webpack.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"],"sourcesContent":["import { webpack, sources } from 'next/dist/compiled/webpack/webpack'\nimport crypto from 'crypto'\nimport { SUBRESOURCE_INTEGRITY_MANIFEST } from '../../../shared/lib/constants'\n\nconst PLUGIN_NAME = 'SubresourceIntegrityPlugin'\n\nexport type SubresourceIntegrityAlgorithm = 'sha256' | 'sha384' | 'sha512'\n\nexport class SubresourceIntegrityPlugin {\n constructor(private readonly algorithm: SubresourceIntegrityAlgorithm) {}\n\n public apply(compiler: webpack.Compiler) {\n compiler.hooks.make.tap(PLUGIN_NAME, (compilation) => {\n compilation.hooks.afterProcessAssets.tap(\n {\n name: PLUGIN_NAME,\n stage: webpack.Compilation.PROCESS_ASSETS_STAGE_ADDITIONS,\n },\n () => {\n // Collect all the assets.\n let files = new Set<string>()\n for (const asset of compilation.getAssets()) {\n files.add(asset.name)\n }\n\n // For each file, deduped, calculate the file hash.\n const hashes: Record<string, string> = {}\n for (const file of files.values()) {\n // Get the buffer for the asset.\n const asset = compilation.getAsset(file)\n if (!asset) {\n throw new Error(`could not get asset: ${file}`)\n }\n\n // Get the buffer for the asset.\n const buffer = asset.source.buffer()\n\n // Create the hash for the content.\n const hash = crypto\n .createHash(this.algorithm)\n .update(buffer)\n .digest()\n .toString('base64')\n\n hashes[file] = `${this.algorithm}-${hash}`\n }\n\n const json = JSON.stringify(hashes, null, 2)\n const file = 'server/' + SUBRESOURCE_INTEGRITY_MANIFEST\n compilation.emitAsset(\n file + '.js',\n new sources.RawSource(\n `self.__SUBRESOURCE_INTEGRITY_MANIFEST=${JSON.stringify(json)}`\n // Work around webpack 4 type of RawSource being used\n // TODO: use webpack 5 type by default\n ) as unknown as webpack.sources.RawSource\n )\n compilation.emitAsset(\n file + '.json',\n new sources.RawSource(\n json\n // Work around webpack 4 type of RawSource being used\n // TODO: use webpack 5 type by default\n ) as unknown as webpack.sources.RawSource\n )\n }\n )\n })\n }\n}\n"],"names":["SubresourceIntegrityPlugin","PLUGIN_NAME","constructor","algorithm","apply","compiler","hooks","make","tap","compilation","afterProcessAssets","name","stage","webpack","Compilation","PROCESS_ASSETS_STAGE_ADDITIONS","files","Set","asset","getAssets","add","hashes","file","values","getAsset","Error","buffer","source","hash","crypto","createHash","update","digest","toString","json","JSON","stringify","SUBRESOURCE_INTEGRITY_MANIFEST","emitAsset","sources","RawSource"],"mappings":";;;;+BAQaA;;;eAAAA;;;yBARoB;+DACd;2BAC4B;;;;;;AAE/C,MAAMC,cAAc;AAIb,MAAMD;IACXE,YAAY,AAAiBC,SAAwC,CAAE;aAA1CA,YAAAA;IAA2C;IAEjEC,MAAMC,QAA0B,EAAE;QACvCA,SAASC,KAAK,CAACC,IAAI,CAACC,GAAG,CAACP,aAAa,CAACQ;YACpCA,YAAYH,KAAK,CAACI,kBAAkB,CAACF,GAAG,CACtC;gBACEG,MAAMV;gBACNW,OAAOC,gBAAO,CAACC,WAAW,CAACC,8BAA8B;YAC3D,GACA;gBACE,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,QAAQT,YAAYe,QAAQ,CAACF;oBACnC,IAAI,CAACJ,OAAO;wBACV,MAAM,qBAAyC,CAAzC,IAAIO,MAAM,CAAC,qBAAqB,EAAEH,MAAM,GAAxC,qBAAA;mCAAA;wCAAA;0CAAA;wBAAwC;oBAChD;oBAEA,gCAAgC;oBAChC,MAAMI,SAASR,MAAMS,MAAM,CAACD,MAAM;oBAElC,mCAAmC;oBACnC,MAAME,OAAOC,eAAM,CAChBC,UAAU,CAAC,IAAI,CAAC3B,SAAS,EACzB4B,MAAM,CAACL,QACPM,MAAM,GACNC,QAAQ,CAAC;oBAEZZ,MAAM,CAACC,KAAK,GAAG,GAAG,IAAI,CAACnB,SAAS,CAAC,CAAC,EAAEyB,MAAM;gBAC5C;gBAEA,MAAMM,OAAOC,KAAKC,SAAS,CAACf,QAAQ,MAAM;gBAC1C,MAAMC,OAAO,YAAYe,yCAA8B;gBACvD5B,YAAY6B,SAAS,CACnBhB,OAAO,OACP,IAAIiB,gBAAO,CAACC,SAAS,CACnB,CAAC,sCAAsC,EAAEL,KAAKC,SAAS,CAACF,OAAO;gBAKnEzB,YAAY6B,SAAS,CACnBhB,OAAO,SACP,IAAIiB,gBAAO,CAACC,SAAS,CACnBN;YAKN;QAEJ;IACF;AACF","ignoreList":[0]}

View File

@@ -0,0 +1,35 @@
import type { webpack } from 'next/dist/compiled/webpack/webpack';
import { type UseCacheTrackerKey } from './use-cache-tracker-utils';
/**
* List of target triples next-swc native binary supports.
*/
export type SWC_TARGET_TRIPLE = 'x86_64-apple-darwin' | 'x86_64-unknown-linux-gnu' | 'x86_64-pc-windows-msvc' | 'i686-pc-windows-msvc' | 'aarch64-unknown-linux-gnu' | 'armv7-unknown-linux-gnueabihf' | 'aarch64-apple-darwin' | 'aarch64-linux-android' | 'arm-linux-androideabi' | 'x86_64-unknown-freebsd' | 'x86_64-unknown-linux-musl' | 'aarch64-unknown-linux-musl' | 'aarch64-pc-windows-msvc';
export type Feature = 'next/image' | 'next/future/image' | 'next/legacy/image' | 'next/script' | 'next/dynamic' | '@next/font/google' | '@next/font/local' | 'next/font/google' | 'next/font/local' | 'swcLoader' | 'swcRelay' | 'swcStyledComponents' | 'swcReactRemoveProperties' | 'swcExperimentalDecorators' | 'swcRemoveConsole' | 'swcImportSource' | 'swcEmotion' | `swc/target/${SWC_TARGET_TRIPLE}` | 'turbotrace' | 'transpilePackages' | 'skipProxyUrlNormalize' | 'skipTrailingSlashRedirect' | 'modularizeImports' | 'esmExternals' | 'webpackPlugins' | UseCacheTrackerKey;
interface FeatureUsage {
featureName: Feature;
invocationCount: number;
}
export type TelemetryLoaderContext = {
eliminatedPackages?: Set<string>;
useCacheTracker?: Map<UseCacheTrackerKey, number>;
};
/**
* 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 declare class TelemetryPlugin implements webpack.WebpackPluginInstance {
private usageTracker;
constructor(buildFeaturesMap: Map<Feature, boolean>);
addUsage(featureName: Feature, invocationCount: FeatureUsage['invocationCount']): void;
apply(compiler: webpack.Compiler): void;
usages(): FeatureUsage[];
packagesUsedInServerSideProps(): string[];
getUseCacheTracker(): Record<UseCacheTrackerKey, number>;
}
export type TelemetryPluginState = {
usages: ReturnType<TelemetryPlugin['usages']>;
packagesUsedInServerSideProps: ReturnType<TelemetryPlugin['packagesUsedInServerSideProps']>;
useCacheTracker: ReturnType<TelemetryPlugin['getUseCacheTracker']>;
};
export {};

View File

@@ -0,0 +1,188 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "TelemetryPlugin", {
enumerable: true,
get: function() {
return TelemetryPlugin;
}
});
const _usecachetrackerutils = require("./use-cache-tracker-utils");
// 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',
'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',
'skipProxyUrlNormalize',
'skipTrailingSlashRedirect',
'modularizeImports',
'esmExternals',
'webpackPlugins'
];
const eliminatedPackages = new Set();
const useCacheTracker = (0, _usecachetrackerutils.createUseCacheTracker)();
/**
* Determine if there is a feature of interest in the specified 'module'.
*/ function findFeatureInModule(module) {
if (module.type !== 'javascript/auto') {
return;
}
for (const [feature, path] of FEATURE_MODULE_MAP){
var _module_resource;
// imports like "http" will be undefined resource in rspack
if ((_module_resource = module.resource) == null ? void 0 : _module_resource.endsWith(path)) {
return feature;
}
}
const normalizedIdentifier = module.identifier().replace(/\\/g, '/');
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;
}
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
});
}
}
addUsage(featureName, invocationCount) {
this.usageTracker.set(featureName, {
featureName,
invocationCount
});
}
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.thisCompilation.tap(TelemetryPlugin.name, (compilation)=>{
const moduleHooks = compiler.webpack.NormalModule.getCompilationHooks(compilation);
moduleHooks.loader.tap(TelemetryPlugin.name, (loaderContext)=>{
;
loaderContext.eliminatedPackages = eliminatedPackages;
loaderContext.useCacheTracker = useCacheTracker;
});
});
}
}
usages() {
return [
...this.usageTracker.values()
];
}
packagesUsedInServerSideProps() {
return Array.from(eliminatedPackages);
}
getUseCacheTracker() {
return Object.fromEntries(useCacheTracker);
}
}
//# sourceMappingURL=telemetry-plugin.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,6 @@
import type { TelemetryLoaderContext } from './telemetry-plugin';
export type SwcTransformTelemetryOutput = {
eliminatedPackages?: string;
useCacheTelemetryTracker?: string;
};
export declare function updateTelemetryLoaderCtxFromTransformOutput(ctx: TelemetryLoaderContext, output: SwcTransformTelemetryOutput): void;

View File

@@ -0,0 +1,28 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "updateTelemetryLoaderCtxFromTransformOutput", {
enumerable: true,
get: function() {
return updateTelemetryLoaderCtxFromTransformOutput;
}
});
function updateTelemetryLoaderCtxFromTransformOutput(ctx, output) {
if (output.eliminatedPackages && ctx.eliminatedPackages) {
for (const pkg of JSON.parse(output.eliminatedPackages)){
ctx.eliminatedPackages.add(pkg);
}
}
if (output.useCacheTelemetryTracker && ctx.useCacheTracker) {
for (const [key, value] of JSON.parse(output.useCacheTelemetryTracker)){
const prefixedKey = `useCache/${key}`;
const numericValue = Number(value);
if (!isNaN(numericValue)) {
ctx.useCacheTracker.set(prefixedKey, (ctx.useCacheTracker.get(prefixedKey) || 0) + numericValue);
}
}
}
}
//# sourceMappingURL=update-telemetry-loader-context-from-swc.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../../src/build/webpack/plugins/telemetry-plugin/update-telemetry-loader-context-from-swc.ts"],"sourcesContent":["import type { TelemetryLoaderContext } from './telemetry-plugin'\nexport type SwcTransformTelemetryOutput = {\n eliminatedPackages?: string\n useCacheTelemetryTracker?: string\n}\n\nexport function updateTelemetryLoaderCtxFromTransformOutput(\n ctx: TelemetryLoaderContext,\n output: SwcTransformTelemetryOutput\n) {\n if (output.eliminatedPackages && ctx.eliminatedPackages) {\n for (const pkg of JSON.parse(output.eliminatedPackages)) {\n ctx.eliminatedPackages.add(pkg)\n }\n }\n\n if (output.useCacheTelemetryTracker && ctx.useCacheTracker) {\n for (const [key, value] of JSON.parse(output.useCacheTelemetryTracker)) {\n const prefixedKey = `useCache/${key}` as const\n const numericValue = Number(value)\n if (!isNaN(numericValue)) {\n ctx.useCacheTracker.set(\n prefixedKey,\n (ctx.useCacheTracker.get(prefixedKey) || 0) + numericValue\n )\n }\n }\n }\n}\n"],"names":["updateTelemetryLoaderCtxFromTransformOutput","ctx","output","eliminatedPackages","pkg","JSON","parse","add","useCacheTelemetryTracker","useCacheTracker","key","value","prefixedKey","numericValue","Number","isNaN","set","get"],"mappings":";;;;+BAMgBA;;;eAAAA;;;AAAT,SAASA,4CACdC,GAA2B,EAC3BC,MAAmC;IAEnC,IAAIA,OAAOC,kBAAkB,IAAIF,IAAIE,kBAAkB,EAAE;QACvD,KAAK,MAAMC,OAAOC,KAAKC,KAAK,CAACJ,OAAOC,kBAAkB,EAAG;YACvDF,IAAIE,kBAAkB,CAACI,GAAG,CAACH;QAC7B;IACF;IAEA,IAAIF,OAAOM,wBAAwB,IAAIP,IAAIQ,eAAe,EAAE;QAC1D,KAAK,MAAM,CAACC,KAAKC,MAAM,IAAIN,KAAKC,KAAK,CAACJ,OAAOM,wBAAwB,EAAG;YACtE,MAAMI,cAAc,CAAC,SAAS,EAAEF,KAAK;YACrC,MAAMG,eAAeC,OAAOH;YAC5B,IAAI,CAACI,MAAMF,eAAe;gBACxBZ,IAAIQ,eAAe,CAACO,GAAG,CACrBJ,aACA,AAACX,CAAAA,IAAIQ,eAAe,CAACQ,GAAG,CAACL,gBAAgB,CAAA,IAAKC;YAElD;QACF;IACF;AACF","ignoreList":[0]}

View File

@@ -0,0 +1,12 @@
export type UseCacheTrackerKey = `useCache/${string}`;
export declare const createUseCacheTracker: () => Map<`useCache/${string}`, number>;
/**
* Example usage:
*
* const tracker1 = { 'useCache/file1': 1, 'useCache/file2': 2 };
* const tracker2 = { 'useCache/file2': 3, 'useCache/file3': 4 };
* const merged = mergeUseCacheTrackers(tracker1, tracker2);
*
* // Result: { 'useCache/file1': 1, 'useCache/file2': 5, 'useCache/file3': 4 }
*/
export declare const mergeUseCacheTrackers: (tracker1: Record<UseCacheTrackerKey, number> | undefined, tracker2: Record<UseCacheTrackerKey, number> | undefined) => Record<UseCacheTrackerKey, number>;

View File

@@ -0,0 +1,43 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
0 && (module.exports = {
createUseCacheTracker: null,
mergeUseCacheTrackers: null
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
createUseCacheTracker: function() {
return createUseCacheTracker;
},
mergeUseCacheTrackers: function() {
return mergeUseCacheTrackers;
}
});
const createUseCacheTracker = ()=>new Map();
const mergeUseCacheTrackers = (tracker1, tracker2)=>{
const mergedTracker = {
...tracker1
};
if (tracker2) {
for(const key in tracker2){
if (Object.prototype.hasOwnProperty.call(tracker2, key)) {
const typedKey = key;
if (mergedTracker[typedKey] !== undefined) {
mergedTracker[typedKey] += tracker2[typedKey];
} else {
mergedTracker[typedKey] = tracker2[typedKey];
}
}
}
}
return mergedTracker;
};
//# sourceMappingURL=use-cache-tracker-utils.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../../src/build/webpack/plugins/telemetry-plugin/use-cache-tracker-utils.ts"],"sourcesContent":["export type UseCacheTrackerKey = `useCache/${string}`\n\nexport const createUseCacheTracker = () => new Map<UseCacheTrackerKey, number>()\n\n/**\n * Example usage:\n *\n * const tracker1 = { 'useCache/file1': 1, 'useCache/file2': 2 };\n * const tracker2 = { 'useCache/file2': 3, 'useCache/file3': 4 };\n * const merged = mergeUseCacheTrackers(tracker1, tracker2);\n *\n * // Result: { 'useCache/file1': 1, 'useCache/file2': 5, 'useCache/file3': 4 }\n */\nexport const mergeUseCacheTrackers = (\n tracker1: Record<UseCacheTrackerKey, number> | undefined,\n tracker2: Record<UseCacheTrackerKey, number> | undefined\n): Record<UseCacheTrackerKey, number> => {\n const mergedTracker: Record<UseCacheTrackerKey, number> = { ...tracker1 }\n\n if (tracker2) {\n for (const key in tracker2) {\n if (Object.prototype.hasOwnProperty.call(tracker2, key)) {\n const typedKey = key as UseCacheTrackerKey\n if (mergedTracker[typedKey] !== undefined) {\n mergedTracker[typedKey] += tracker2[typedKey]\n } else {\n mergedTracker[typedKey] = tracker2[typedKey]\n }\n }\n }\n }\n\n return mergedTracker\n}\n"],"names":["createUseCacheTracker","mergeUseCacheTrackers","Map","tracker1","tracker2","mergedTracker","key","Object","prototype","hasOwnProperty","call","typedKey","undefined"],"mappings":";;;;;;;;;;;;;;;IAEaA,qBAAqB;eAArBA;;IAWAC,qBAAqB;eAArBA;;;AAXN,MAAMD,wBAAwB,IAAM,IAAIE;AAWxC,MAAMD,wBAAwB,CACnCE,UACAC;IAEA,MAAMC,gBAAoD;QAAE,GAAGF,QAAQ;IAAC;IAExE,IAAIC,UAAU;QACZ,IAAK,MAAME,OAAOF,SAAU;YAC1B,IAAIG,OAAOC,SAAS,CAACC,cAAc,CAACC,IAAI,CAACN,UAAUE,MAAM;gBACvD,MAAMK,WAAWL;gBACjB,IAAID,aAAa,CAACM,SAAS,KAAKC,WAAW;oBACzCP,aAAa,CAACM,SAAS,IAAIP,QAAQ,CAACO,SAAS;gBAC/C,OAAO;oBACLN,aAAa,CAACM,SAAS,GAAGP,QAAQ,CAACO,SAAS;gBAC9C;YACF;QACF;IACF;IAEA,OAAON;AACT","ignoreList":[0]}

View File

@@ -0,0 +1,10 @@
import type { webpack } from 'next/dist/compiled/webpack/webpack';
export declare function formatModuleTrace(compiler: webpack.Compiler, moduleTrace: any[]): {
lastInternalFileName: string;
invalidImportMessage: string;
formattedModuleTrace: string;
};
export declare function getModuleTrace(module: any, compilation: webpack.Compilation, compiler: webpack.Compiler): {
moduleTrace: any[];
isPagesDir: boolean;
};

View File

@@ -0,0 +1,89 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
0 && (module.exports = {
formatModuleTrace: null,
getModuleTrace: null
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
formatModuleTrace: function() {
return formatModuleTrace;
},
getModuleTrace: function() {
return getModuleTrace;
}
});
const _loaderutils3 = /*#__PURE__*/ _interop_require_default(require("next/dist/compiled/loader-utils3"));
const _path = require("path");
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
function formatModule(compiler, module1) {
const relativePath = (0, _path.relative)(compiler.context, module1.resource).replace(/\?.+$/, '');
return _loaderutils3.default.isUrlRequest(relativePath) ? _loaderutils3.default.urlToRequest(relativePath) : relativePath;
}
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')
};
}
function getModuleTrace(module1, 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 = module1;
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

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,4 @@
import type { webpack } from 'next/dist/compiled/webpack/webpack';
export declare class WellKnownErrorsPlugin {
apply(compiler: webpack.Compiler): void;
}

View File

@@ -0,0 +1,43 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "WellKnownErrorsPlugin", {
enumerable: true,
get: function() {
return WellKnownErrorsPlugin;
}
});
const _webpackModuleError = require("./webpackModuleError");
const NAME = 'WellKnownErrorsPlugin';
class WellKnownErrorsPlugin {
apply(compiler) {
compiler.hooks.compilation.tap(NAME, (compilation)=>{
compilation.hooks.afterSeal.tapPromise(NAME, async ()=>{
var _compilation_warnings, _compilation_errors;
if ((_compilation_warnings = compilation.warnings) == null ? void 0 : _compilation_warnings.length) {
await Promise.all(compilation.warnings.map(async (warn, i)=>{
var _warn_module_context, _warn_module;
if (warn.name === 'ModuleDependencyWarning' && ((_warn_module = warn.module) == null ? void 0 : (_warn_module_context = _warn_module.context) == null ? void 0 : _warn_module_context.includes('node_modules'))) {
compilation.warnings.splice(i, 1);
}
}));
}
if ((_compilation_errors = compilation.errors) == null ? void 0 : _compilation_errors.length) {
await Promise.all(compilation.errors.map(async (err, i)=>{
try {
const moduleError = await (0, _webpackModuleError.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"],"sourcesContent":["import type { webpack } from 'next/dist/compiled/webpack/webpack'\n\nimport { getModuleBuildError } from './webpackModuleError'\n\nconst NAME = 'WellKnownErrorsPlugin'\nexport class WellKnownErrorsPlugin {\n apply(compiler: webpack.Compiler) {\n compiler.hooks.compilation.tap(NAME, (compilation) => {\n compilation.hooks.afterSeal.tapPromise(NAME, async () => {\n if (compilation.warnings?.length) {\n await Promise.all(\n compilation.warnings.map(async (warn, i) => {\n if (\n warn.name === 'ModuleDependencyWarning' &&\n warn.module?.context?.includes('node_modules')\n ) {\n compilation.warnings.splice(i, 1)\n }\n })\n )\n }\n\n if (compilation.errors?.length) {\n await Promise.all(\n compilation.errors.map(async (err, i) => {\n try {\n const moduleError = await getModuleBuildError(\n compiler,\n compilation,\n err\n )\n if (moduleError !== false) {\n compilation.errors[i] = moduleError\n }\n } catch (e) {\n console.log(e)\n }\n })\n )\n }\n })\n })\n }\n}\n"],"names":["WellKnownErrorsPlugin","NAME","apply","compiler","hooks","compilation","tap","afterSeal","tapPromise","warnings","length","Promise","all","map","warn","i","name","module","context","includes","splice","errors","err","moduleError","getModuleBuildError","e","console","log"],"mappings":";;;;+BAKaA;;;eAAAA;;;oCAHuB;AAEpC,MAAMC,OAAO;AACN,MAAMD;IACXE,MAAMC,QAA0B,EAAE;QAChCA,SAASC,KAAK,CAACC,WAAW,CAACC,GAAG,CAACL,MAAM,CAACI;YACpCA,YAAYD,KAAK,CAACG,SAAS,CAACC,UAAU,CAACP,MAAM;oBACvCI,uBAaAA;gBAbJ,KAAIA,wBAAAA,YAAYI,QAAQ,qBAApBJ,sBAAsBK,MAAM,EAAE;oBAChC,MAAMC,QAAQC,GAAG,CACfP,YAAYI,QAAQ,CAACI,GAAG,CAAC,OAAOC,MAAMC;4BAGlCD,sBAAAA;wBAFF,IACEA,KAAKE,IAAI,KAAK,+BACdF,eAAAA,KAAKG,MAAM,sBAAXH,uBAAAA,aAAaI,OAAO,qBAApBJ,qBAAsBK,QAAQ,CAAC,kBAC/B;4BACAd,YAAYI,QAAQ,CAACW,MAAM,CAACL,GAAG;wBACjC;oBACF;gBAEJ;gBAEA,KAAIV,sBAAAA,YAAYgB,MAAM,qBAAlBhB,oBAAoBK,MAAM,EAAE;oBAC9B,MAAMC,QAAQC,GAAG,CACfP,YAAYgB,MAAM,CAACR,GAAG,CAAC,OAAOS,KAAKP;wBACjC,IAAI;4BACF,MAAMQ,cAAc,MAAMC,IAAAA,uCAAmB,EAC3CrB,UACAE,aACAiB;4BAEF,IAAIC,gBAAgB,OAAO;gCACzBlB,YAAYgB,MAAM,CAACN,EAAE,GAAGQ;4BAC1B;wBACF,EAAE,OAAOE,GAAG;4BACVC,QAAQC,GAAG,CAACF;wBACd;oBACF;gBAEJ;YACF;QACF;IACF;AACF","ignoreList":[0]}

View File

@@ -0,0 +1,3 @@
import type { webpack } from 'next/dist/compiled/webpack/webpack';
import { SimpleWebpackError } from './simpleWebpackError';
export declare function getDynamicCodeEvaluationError(message: string, module: webpack.NormalModule, compilation: webpack.Compilation, compiler: webpack.Compiler): SimpleWebpackError;

Some files were not shown because too many files have changed in this diff Show More