Skip to content

Commit

Permalink
Simplify the client manifest structure (#51183)
Browse files Browse the repository at this point in the history
Both of our bundlers won't split different exports of a module into different chunks, we can rely on facebook/react#26624 to simplify the structure. This reduces the size of the client reference manifest by ~70%.
  • Loading branch information
shuding authored Jun 13, 2023
1 parent bfbfa87 commit 9ffea84
Showing 1 changed file with 10 additions and 67 deletions.
77 changes: 10 additions & 67 deletions packages/next/src/build/webpack/plugins/flight-manifest-plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -240,38 +240,8 @@ export class ClientReferenceManifestPlugin {
return
}

const exportsInfo = compilation.moduleGraph.getExportsInfo(mod)
const isAsyncModule = this.ASYNC_CLIENT_MODULES.has(mod.resource)

const cjsExports = [
...new Set(
[
...mod.dependencies.map((dep) => {
// Match CommonJsSelfReferenceDependency
if (dep.type === 'cjs self exports reference') {
// @ts-expect-error: TODO: Fix Dependency type
if (dep.base === 'module.exports') {
return 'default'
}

// `exports.foo = ...`, `exports.default = ...`
// @ts-expect-error: TODO: Fix Dependency type
if (dep.base === 'exports') {
// @ts-expect-error: TODO: Fix Dependency type
return dep.names.filter(
(name: any) => name !== '__esModule'
)
}
}
return null
}),
...(mod.buildInfo?.rsc?.clientRefs || []),
]
.filter(Boolean)
.flat()
),
]

// 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)
Expand All @@ -281,31 +251,28 @@ export class ClientReferenceManifestPlugin {
)
: null

function addClientReference(name: string) {
const exportName = getClientReferenceModuleKey(resource, name)
function addClientReference() {
const exportName = resource
manifest.clientModules[exportName] = {
id,
name,
name: '*',
chunks: requiredChunks,
async: isAsyncModule,
}
if (esmResource) {
const edgeExportName = getClientReferenceModuleKey(
esmResource,
name
)
const edgeExportName = esmResource
manifest.clientModules[edgeExportName] =
manifest.clientModules[exportName]
}
}

function addSSRIdMapping(name: string) {
const exportName = getClientReferenceModuleKey(resource, name)
function addSSRIdMapping() {
const exportName = resource
if (
typeof pluginState.serverModuleIds[ssrNamedModuleId] !== 'undefined'
) {
moduleIdMapping[id] = moduleIdMapping[id] || {}
moduleIdMapping[id][name] = {
moduleIdMapping[id]['*'] = {
...manifest.clientModules[exportName],
// During SSR, we don't have external chunks to load on the server
// side with our architecture of Webpack / Turbopack. We can keep
Expand All @@ -320,7 +287,7 @@ export class ClientReferenceManifestPlugin {
'undefined'
) {
edgeModuleIdMapping[id] = edgeModuleIdMapping[id] || {}
edgeModuleIdMapping[id][name] = {
edgeModuleIdMapping[id]['*'] = {
...manifest.clientModules[exportName],
// During SSR, we don't have external chunks to load on the server
// side with our architecture of Webpack / Turbopack. We can keep
Expand All @@ -331,32 +298,8 @@ export class ClientReferenceManifestPlugin {
}
}

addClientReference('*')
addClientReference('')
addSSRIdMapping('*')
addSSRIdMapping('')

const moduleExportedKeys = [
...[...exportsInfo.exports]
.filter((exportInfo) => exportInfo.provided)
.map((exportInfo) => exportInfo.name),
...cjsExports,
].filter((name) => name !== null)

moduleExportedKeys.forEach((name) => {
const key = getClientReferenceModuleKey(resource, name)

// If the chunk is from `app/` chunkGroup, use it first.
// This make sure not to load the overlapped chunk from `pages/` chunkGroup
if (
!manifest.clientModules[key] ||
(chunkGroup.name && /^app[\\/]/.test(chunkGroup.name))
) {
addClientReference(name)
}

addSSRIdMapping(name)
})
addClientReference()
addSSRIdMapping()

manifest.clientModules = moduleReferences
manifest.ssrModuleMapping = moduleIdMapping
Expand Down

0 comments on commit 9ffea84

Please sign in to comment.