From 22536620fc37be44fa9927a82fb7cfab18682ccc Mon Sep 17 00:00:00 2001 From: wangyiming Date: Thu, 2 Jan 2025 14:11:07 +0800 Subject: [PATCH] feat: try rspack and fix entry problems --- .../cli/uni-builder/src/shared/rsc/common.ts | 16 ++- .../shared/rsc/plugins/rsc-rsbuild-plugin.ts | 24 ++-- .../shared/rsc/plugins/rsc-server-plugin.ts | 100 ++++++++++++---- .../rsc/plugins/rspack-rsc-client-plugin.ts | 28 ----- .../rsc/plugins/rspack-rsc-server-plugin.ts | 107 ++++++++++++------ .../src/shared/rsc/rsc-server-loader.ts | 11 -- 6 files changed, 173 insertions(+), 113 deletions(-) diff --git a/packages/cli/uni-builder/src/shared/rsc/common.ts b/packages/cli/uni-builder/src/shared/rsc/common.ts index 8f78b8d8afc..3a754d4d335 100644 --- a/packages/cli/uni-builder/src/shared/rsc/common.ts +++ b/packages/cli/uni-builder/src/shared/rsc/common.ts @@ -32,6 +32,7 @@ import type { Compilation, LoaderDefinitionFunction, ModuleGraph, + NormalModule, Module as WebpackModule, } from 'webpack'; @@ -332,11 +333,16 @@ export function getServerActions(ast: Module): ServerAction[] { return collector.getServerActions(); } -export function findRootIssuer(module: WebpackModule): WebpackModule { - let currentModule = module; - while (currentModule?.issuer) { - currentModule = currentModule.issuer; +export function findRootIssuer( + modulegraph: ModuleGraph, + module: NormalModule, +): NormalModule { + const currentModule = module; + const issuer = modulegraph.getIssuer(currentModule); + + if (!issuer) { + return currentModule; } - return currentModule; + return findRootIssuer(modulegraph, issuer as NormalModule); } diff --git a/packages/cli/uni-builder/src/shared/rsc/plugins/rsc-rsbuild-plugin.ts b/packages/cli/uni-builder/src/shared/rsc/plugins/rsc-rsbuild-plugin.ts index d8fad37268b..b978c06a7f7 100644 --- a/packages/cli/uni-builder/src/shared/rsc/plugins/rsc-rsbuild-plugin.ts +++ b/packages/cli/uni-builder/src/shared/rsc/plugins/rsc-rsbuild-plugin.ts @@ -17,17 +17,17 @@ export const rscRsbuildPlugin = ({ setup(api) { api.modifyBundlerChain({ handler: async (chain, { isServer, CHAIN_ID }) => { + const entryPath2Name = new Map(); + + for (const [name, entry] of Object.entries( + chain.entryPoints.entries(), + )) { + entry.values().forEach(value => { + entryPath2Name.set(value as unknown as string, name); + }); + } const jsHandler = () => { const originalJsRule = chain.module.rules.get(CHAIN_ID.RULE.JS); - const entryPath2Name = new Map(); - - for (const [name, entry] of Object.entries( - chain.entryPoints.entries(), - )) { - entry.values().forEach(value => { - entryPath2Name.set(value as unknown as string, name); - }); - } const useBabel = originalJsRule.uses.has(CHAIN_ID.USE.BABEL); @@ -112,7 +112,11 @@ export const rscRsbuildPlugin = ({ const ServerPlugin = isRspack ? RspackRscServerPlugin : RscServerPlugin; - chain.plugin('rsc-server-plugin').use(ServerPlugin); + chain.plugin('rsc-server-plugin').use(ServerPlugin, [ + { + entryPath2Name, + }, + ]); }; const addRscClientLoader = () => { diff --git a/packages/cli/uni-builder/src/shared/rsc/plugins/rsc-server-plugin.ts b/packages/cli/uni-builder/src/shared/rsc/plugins/rsc-server-plugin.ts index 55207ade60d..22a56b989ef 100644 --- a/packages/cli/uni-builder/src/shared/rsc/plugins/rsc-server-plugin.ts +++ b/packages/cli/uni-builder/src/shared/rsc/plugins/rsc-server-plugin.ts @@ -1,4 +1,10 @@ import type Webpack from 'webpack'; +import { + type Compilation, + Module, + type ModuleGraph, + NormalModule, +} from 'webpack'; import { type ServerManifest, type ServerReferencesMap, @@ -13,6 +19,7 @@ import type { ClientReferencesMap } from '../common'; export interface RscServerPluginOptions { readonly serverManifestFilename?: string; + readonly entryPath2Name: Map; } export interface ModuleExportsInfo { @@ -20,24 +27,72 @@ export interface ModuleExportsInfo { readonly exportName: string; } -const resourcePath2Entry = new Map< +const resourcePath2Entries = new Map< string, { entryName: string; entryPath: string; - } + }[] >(); + export class RscServerPlugin { private clientReferencesMap: ClientReferencesMap = new Map(); private serverReferencesMap: ServerReferencesMap = new Map(); private serverManifest: ServerManifest = {}; private serverManifestFilename: string; + private entryPath2Name = new Map(); private styles: Set; constructor(options: RscServerPluginOptions) { this.styles = new Set(); this.serverManifestFilename = options?.serverManifestFilename || `react-server-manifest.json`; + + this.entryPath2Name = options?.entryPath2Name || new Map(); + } + + private findModuleEntries( + module: NormalModule, + compilation: Compilation, + resourcePath2Entries: Map< + string, + Array<{ entryName: string; entryPath: string }> + >, + visited = new Set(), + ): Array<{ entryName: string; entryPath: string }> { + if (!module?.resource || visited.has(module.resource)) { + return []; + } + visited.add(module.resource); + + const currentEntries = resourcePath2Entries.get(module.resource); + if (currentEntries && currentEntries?.length > 0) { + return currentEntries; + } + + const issuer = findRootIssuer(compilation.moduleGraph, module); + if (!issuer) { + return []; + } + + const issuerEntries = this.findModuleEntries( + issuer, + compilation, + resourcePath2Entries, + visited, + ); + if (issuerEntries.length > 0) { + return issuerEntries; + } + + if (issuer.resource) { + const entryName = this.entryPath2Name.get(issuer.resource); + if (entryName) { + return [{ entryName, entryPath: issuer.resource }]; + } + } + + return []; } apply(compiler: Webpack.Compiler): void { @@ -79,7 +134,7 @@ export class RscServerPlugin { const includeModule = async ( compilation: Webpack.Compilation, resource: string, - resourceEntryName?: string, + resourceEntryNames?: string[], layer?: string, ) => { const entries = Array.from(compilation.entries.entries()); @@ -93,7 +148,7 @@ export class RscServerPlugin { } const includePromises = entries - .filter(([entryName]) => entryName === resourceEntryName) + .filter(([entryName]) => resourceEntryNames?.includes(entryName)) .map(([entryName]) => { const dependency = EntryPlugin.createDependency(resource, { name: resource, @@ -181,39 +236,38 @@ export class RscServerPlugin { ); } - let entryName = buildInfo.__entryName; - let entryPath = buildInfo.__entryPath; - // server component -> client -component(react-server layer) -> client component(default layer) -> server action(default layer) -> server action(react-server layer) - if (!entryName) { - const entryModule = findRootIssuer(module); - const entryModuleBuildInfo = getRscBuildInfo(entryModule); - entryName = entryModuleBuildInfo.__entryName; - entryPath = entryModuleBuildInfo.__entryPath; + if (module instanceof NormalModule) { + // server component -> client -component(react-server layer) -> client component(default layer) -> server action(default layer) -> server action(react-server layer) + const entries = this.findModuleEntries( + module, + compilation, + resourcePath2Entries, + ); + if (entries.length > 0) { + resourcePath2Entries.set(module.resource, entries); + } } - - resourcePath2Entry.set(buildInfo.resourcePath, { - entryName, - entryPath, - }); } return hasChangeReference; }; this.serverManifest = {}; - let hasChangeReference = processModules(compilation.modules); const clientReferences = [...this.clientReferencesMap.keys()]; const serverReferences = [...this.serverReferencesMap.keys()]; const referencesBefore = [...clientReferences, ...serverReferences]; + let hasChangeReference = false; await Promise.all([ ...clientReferences.map(async resource => { try { await includeModule( compilation, resource, - resourcePath2Entry.get(resource)?.entryName || '', + resourcePath2Entries + .get(resource) + ?.map(entry => entry.entryName) || [], ); } catch (error) { console.error(error); @@ -226,7 +280,9 @@ export class RscServerPlugin { await includeModule( compilation, resource, - resourcePath2Entry.get(resource)?.entryName || '', + resourcePath2Entries + .get(resource) + ?.map(entry => entry.entryName) || [], webpackRscLayerName, ); } catch (error) { @@ -237,8 +293,7 @@ export class RscServerPlugin { }), ]); - hasChangeReference = - processModules(compilation.modules) || hasChangeReference; + hasChangeReference = processModules(compilation.modules); const referencesAfter = [ ...this.clientReferencesMap.keys(), @@ -260,7 +315,6 @@ export class RscServerPlugin { compiler.hooks.done.tap(RscServerPlugin.name, () => { sharedData.set('serverReferencesMap', this.serverReferencesMap); sharedData.set('clientReferencesMap', this.clientReferencesMap); - sharedData.set('resourcePath2Entry', resourcePath2Entry); sharedData.set('styles', this.styles); }); diff --git a/packages/cli/uni-builder/src/shared/rsc/plugins/rspack-rsc-client-plugin.ts b/packages/cli/uni-builder/src/shared/rsc/plugins/rspack-rsc-client-plugin.ts index 75195747333..831d859981f 100644 --- a/packages/cli/uni-builder/src/shared/rsc/plugins/rspack-rsc-client-plugin.ts +++ b/packages/cli/uni-builder/src/shared/rsc/plugins/rspack-rsc-client-plugin.ts @@ -55,7 +55,6 @@ export class RspackRscClientPlugin { const getEntryModule = (compilation: Webpack.Compilation): Module[] => { const entryModules: Webpack.Module[] = []; - console.log('eeeeeeeeeeeee', compilation.entries); for (const [, entryValue] of compilation.entries.entries()) { // const entryDependency = entryValue.dependencies.find( // dependency => dependency.constructor.name === `EntryDependency`, @@ -73,15 +72,11 @@ export class RspackRscClientPlugin { const resolvedModule = compilation.moduleGraph.getModule(entryDependency); - console.log('resolvedModule1111111', resolvedModule); - if (resolvedModule) { entryModules.push(resolvedModule); } } - console.log('2222222222', entryModules.length); - if (entryModules.length === 0) { compilation.errors.push( new WebpackError(`Could not find any entries in the compilation.`), @@ -89,7 +84,6 @@ export class RspackRscClientPlugin { return []; } - console.log('3333333333'); return entryModules; }; @@ -105,7 +99,6 @@ export class RspackRscClientPlugin { }); promises.push( new Promise((resolve, reject) => { - console.log('before addInclude'); compilation.addInclude( compiler.context, dependency, @@ -119,7 +112,6 @@ export class RspackRscClientPlugin { } }, ); - console.log('after addInclude'); }), ); }); @@ -131,7 +123,6 @@ export class RspackRscClientPlugin { }); promises.push( new Promise((resolve, reject) => { - console.log('before addInclude'); compilation.addInclude( compiler.context, dependency, @@ -145,7 +136,6 @@ export class RspackRscClientPlugin { } }, ); - console.log('after addInclude'); }), ); } @@ -178,9 +168,7 @@ export class RspackRscClientPlugin { // } // } - console.log('aaaaaaaaaaaa'); const entryModules = getEntryModule(compilation); - console.log('bbbbbbbbbbbb', entryModules); for (const entryModule of entryModules) { // Remove stale client references. // entryModule.blocks = entryModule.blocks.filter(block => @@ -192,7 +180,6 @@ export class RspackRscClientPlugin { // ); // }), // ); - if (entryModule) { addClientReferencesChunks(compilation, entryModule, callback); } @@ -295,15 +282,6 @@ export class RspackRscClientPlugin { ? this.clientReferencesMap.get(resourcePath) : undefined; - if (resourcePath?.includes('Counter')) { - console.log( - 'clientReferences2222222222', - this.clientReferencesMap, - resourcePath, - clientReferences, - ); - } - if (clientReferences) { const moduleId = chunkGraph.getModuleId(module); @@ -321,18 +299,12 @@ export class RspackRscClientPlugin { chunksSet.add(chunk); } - console.log( - 'ccccccccccc', - chunkGraph.getModuleChunksIterable(module), - ); - for (const connection of moduleGraph.getOutgoingConnections( module, )) { for (const chunk of chunkGraph.getModuleChunksIterable( connection.module, )) { - console.log('aaaaaaaaaaaa'); chunksSet.add(chunk); } } diff --git a/packages/cli/uni-builder/src/shared/rsc/plugins/rspack-rsc-server-plugin.ts b/packages/cli/uni-builder/src/shared/rsc/plugins/rspack-rsc-server-plugin.ts index da5eeeab902..68d3f3dc917 100644 --- a/packages/cli/uni-builder/src/shared/rsc/plugins/rspack-rsc-server-plugin.ts +++ b/packages/cli/uni-builder/src/shared/rsc/plugins/rspack-rsc-server-plugin.ts @@ -1,4 +1,5 @@ import type Webpack from 'webpack'; +import type { Compilation, ModuleGraph, NormalModule } from 'webpack'; import { type ServerManifest, type ServerReferencesMap, @@ -13,6 +14,7 @@ import type { ClientReferencesMap } from '../common'; export interface RscServerPluginOptions { readonly serverManifestFilename?: string; + readonly entryPath2Name: Map; } export interface ModuleExportsInfo { @@ -20,24 +22,71 @@ export interface ModuleExportsInfo { readonly exportName: string; } -const resourcePath2Entry = new Map< +const resourcePath2Entries = new Map< string, { entryName: string; entryPath: string; - } + }[] >(); export class RscServerPlugin { private clientReferencesMap: ClientReferencesMap = new Map(); private serverReferencesMap: ServerReferencesMap = new Map(); private serverManifest: ServerManifest = {}; private serverManifestFilename: string; + private entryPath2Name = new Map(); private styles: Set; constructor(options: RscServerPluginOptions) { this.styles = new Set(); this.serverManifestFilename = options?.serverManifestFilename || `react-server-manifest.json`; + + this.entryPath2Name = options?.entryPath2Name || new Map(); + } + + private findModuleEntries( + module: NormalModule, + compilation: Compilation, + resourcePath2Entries: Map< + string, + Array<{ entryName: string; entryPath: string }> + >, + visited = new Set(), + ): Array<{ entryName: string; entryPath: string }> { + if (!module?.resource || visited.has(module.resource)) { + return []; + } + visited.add(module.resource); + + const currentEntries = resourcePath2Entries.get(module.resource); + if (currentEntries && currentEntries?.length > 0) { + return currentEntries; + } + + const issuer = findRootIssuer(compilation.moduleGraph, module); + if (!issuer) { + return []; + } + + const issuerEntries = this.findModuleEntries( + issuer, + compilation, + resourcePath2Entries, + visited, + ); + if (issuerEntries.length > 0) { + return issuerEntries; + } + + if (issuer.resource) { + const entryName = this.entryPath2Name.get(issuer.resource); + if (entryName) { + return [{ entryName, entryPath: issuer.resource }]; + } + } + + return []; } apply(compiler: Webpack.Compiler): void { @@ -79,7 +128,7 @@ export class RscServerPlugin { const includeModule = async ( compilation: Webpack.Compilation, resource: string, - resourceEntryName?: string, + resourceEntryNames?: string[], layer?: string, ) => { const entries = Array.from(compilation.entries.entries()); @@ -92,12 +141,9 @@ export class RscServerPlugin { return; } - console.log('entries11111111', entries, resourceEntryName); - const includePromises = entries - .filter(([entryName]) => entryName === resourceEntryName) + .filter(([entryName]) => resourceEntryNames?.includes(entryName)) .map(([entryName]) => { - console.log('111111111111', entryName); const dependency = EntryPlugin.createDependency(resource, { name: resource, }); @@ -184,50 +230,39 @@ export class RscServerPlugin { ); } - let entryName = buildInfo.__entryName; - let entryPath = buildInfo.__entryPath; // server component -> client -component(react-server layer) -> client component(default layer) -> server action(default layer) -> server action(react-server layer) - if (!entryName) { - const entryModule = findRootIssuer(module); - const entryModuleBuildInfo = getRscBuildInfo(entryModule); - entryName = entryModuleBuildInfo.__entryName; - entryPath = entryModuleBuildInfo.__entryPath; - } - - console.log( - 'resourcePath2Entryssssssssssss', - buildInfo.resourcePath, + const entries = this.findModuleEntries( + module as NormalModule, + compilation, + resourcePath2Entries, ); - - resourcePath2Entry.set(buildInfo.resourcePath, { - entryName, - entryPath, - }); + if (entries.length > 0) { + resourcePath2Entries.set( + (module as NormalModule).resource, + entries, + ); + } } return hasChangeReference; }; this.serverManifest = {}; - let hasChangeReference = processModules(compilation.modules); const clientReferences = [...this.clientReferencesMap.keys()]; const serverReferences = [...this.serverReferencesMap.keys()]; const referencesBefore = [...clientReferences, ...serverReferences]; + let hasChangeReference = false; await Promise.all([ ...clientReferences.map(async resource => { try { - console.log( - 'resource11111111111', - resource, - resourcePath2Entry.get(resource)?.entryName, - resourcePath2Entry, - ); await includeModule( compilation, resource, - resourcePath2Entry.get(resource)?.entryName || '', + resourcePath2Entries + .get(resource) + ?.map(entry => entry.entryName) || [], ); } catch (error) { console.error(error); @@ -240,7 +275,9 @@ export class RscServerPlugin { await includeModule( compilation, resource, - resourcePath2Entry.get(resource)?.entryName || '', + resourcePath2Entries + .get(resource) + ?.map(entry => entry.entryName) || [], webpackRscLayerName, ); } catch (error) { @@ -251,8 +288,7 @@ export class RscServerPlugin { }), ]); - hasChangeReference = - processModules(compilation.modules) || hasChangeReference; + hasChangeReference = processModules(compilation.modules); const referencesAfter = [ ...this.clientReferencesMap.keys(), @@ -274,7 +310,6 @@ export class RscServerPlugin { compiler.hooks.done.tap(RscServerPlugin.name, () => { sharedData.set('serverReferencesMap', this.serverReferencesMap); sharedData.set('clientReferencesMap', this.clientReferencesMap); - sharedData.set('resourcePath2Entry', resourcePath2Entry); sharedData.set('styles', this.styles); }); diff --git a/packages/cli/uni-builder/src/shared/rsc/rsc-server-loader.ts b/packages/cli/uni-builder/src/shared/rsc/rsc-server-loader.ts index 3363d58e799..9247dc87f7d 100644 --- a/packages/cli/uni-builder/src/shared/rsc/rsc-server-loader.ts +++ b/packages/cli/uni-builder/src/shared/rsc/rsc-server-loader.ts @@ -4,7 +4,6 @@ import type { LoaderContext, Module } from 'webpack'; import { type ClientReference, type SourceMap, - findRootIssuer, getExportNames, isClientModule, parseSource, @@ -62,15 +61,10 @@ function createClientReferenceProxy(exportName) { .join('\n'); if (clientReferences.length > 0) { - const entryPath = (findRootIssuer(this._module!) as any) - .resource as string; - const entryName = entryPath2Name.get(entryPath); setRscBuildInfo(this._module!, { type: 'client', resourcePath, clientReferences, - __entryName: entryName, - __entryPath: entryPath, }); } @@ -84,15 +78,10 @@ function createClientReferenceProxy(exportName) { .filter(Boolean) as string[]; if (serverReferenceExportNames.length > 0) { - const entryPath = (findRootIssuer(this._module!) as any) - .resource as string; - const entryName = entryPath2Name.get(entryPath); setRscBuildInfo(this._module!, { type: 'server', resourcePath, exportNames: serverReferenceExportNames, - __entryName: entryName, - __entryPath: entryPath, }); }