UNPKG

next

Version:

The React Framework

751 lines (750 loc) • 38.9 kB
"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 _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"); 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: {} }); 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 = [ 'template', 'layout' ].indexOf(aName); const indexB = [ 'template', 'layout' ].indexOf(bName); if (indexA === -1) return 1; if (indexB === -1) return -1; return indexA - indexB; }); const dedupedCSSImports = {}; const trackedCSSImports = new Set(); for (const [entryName, cssImports] of sortedCSSImports){ for (const cssImport of cssImports){ if (trackedCSSImports.has(cssImport)) continue; // Only track CSS imports that are in files that can inherit CSS. const filename = _path.default.parse(entryName).name; if ([ 'template', 'layout' ].includes(filename)) { trackedCSSImports.add(cssImport); } if (!dedupedCSSImports[entryName]) { dedupedCSSImports[entryName] = []; } dedupedCSSImports[entryName].push(cssImport); } } return dedupedCSSImports; } class FlightClientEntryPlugin { constructor(options){ this.dev = options.dev; this.appDir = 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 = {}; for (const connection of (0, _utils1.getModuleReferencesInOrder)(entryModule, compilation.moduleGraph)){ // 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); // Next.js internals are put into a separate entry. if (!isAbsoluteRequest) { Object.keys(clientComponentImports).forEach((value)=>internalClientComponentEntryImports[value] = new Set()); continue; } // TODO-APP: Enable these lines. This ensures no entrypoint is created for layout/page when there are no client components. // Currently disabled because it causes test failures in CI. // if (clientImports.length === 0 && actionImports.length === 0) { // continue // } const relativeRequest = isAbsoluteRequest ? _path.default.relative(compilation.options.context, entryRequest) : entryRequest; // Replace file suffix as `.js` will be added. 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. if ((0, _ismetadataroute.isMetadataRoute)(bundlePath)) { 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${_constants1.UNDERSCORE_NOT_FOUND_ROUTE_ENTRY}` && bundlePath === 'app/not-found') { clientEntriesToInject.push({ compiler, compilation, entryName: name, clientComponentImports: {}, bundlePath: `app${_constants1.UNDERSCORE_NOT_FOUND_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 }))); } // 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 })) ]); } 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 }) { 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 = _webpack.webpack.EntryPlugin.createDependency(clientServerLoader, { name: bundlePath }); const clientComponentRSCEntryDep = _webpack.webpack.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 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 } of actionsFromModule){ if (typeof currentCompilerServerActions[id] === 'undefined') { currentCompilerServerActions[id] = { workers: {}, layer: {} }; } 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 = _webpack.webpack.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