Skip to content

Commit

Permalink
refactor code
Browse files Browse the repository at this point in the history
  • Loading branch information
huozhi committed Sep 26, 2022
1 parent a53d84a commit 2eef220
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 73 deletions.
56 changes: 37 additions & 19 deletions packages/next-swc/crates/core/src/react_server_components.rs
Expand Up @@ -161,29 +161,47 @@ impl<C: Comments> ReactServerComponents<C> {
prepend_stmts(
&mut module.body,
vec![
ModuleItem::ModuleDecl(ModuleDecl::Import(ImportDecl {
ModuleItem::Stmt(Stmt::Decl(Decl::Var(Box::new(VarDecl {
span: DUMMY_SP,
specifiers: vec![ImportSpecifier::Named(ImportNamedSpecifier {
kind: VarDeclKind::Const,
decls: vec![VarDeclarator {
span: DUMMY_SP,
local: proxy_ident.clone(),
imported: None,
is_type_only: false,
})],
src: Box::new(Str {
span: DUMMY_SP,
raw: None,
value: "private-next-rsc-mod-ref-proxy".into(),
}),
type_only: Default::default(),
asserts: Default::default(),
})),
ModuleItem::ModuleDecl(ModuleDecl::ExportDefaultExpr(ExportDefaultExpr {
name: Pat::Object(ObjectPat {
span: DUMMY_SP,
props: vec![ObjectPatProp::Assign(AssignPatProp {
span: DUMMY_SP,
key: proxy_ident,
value: None,
})],
optional: false,
type_ann: None,
}),
init: Some(Box::new(Expr::Call(CallExpr {
span: DUMMY_SP,
callee: quote_ident!("require").as_callee(),
args: vec![quote_str!("private-next-rsc-mod-ref-proxy").as_arg()],
type_args: Default::default(),
}))),
definite: false,
}],
declare: false,
})))),
ModuleItem::Stmt(Stmt::Expr(ExprStmt {
span: DUMMY_SP,
expr: Box::new(Expr::Call(CallExpr {
expr: Box::new(Expr::Assign(AssignExpr {
span: DUMMY_SP,
callee: proxy_ident.clone().as_callee(),
args: vec![filepath.as_arg()],
type_args: None,
left: PatOrExpr::Expr(Box::new(Expr::Member(MemberExpr {
span: DUMMY_SP,
obj: Box::new(Expr::Ident(quote_ident!("module"))),
prop: MemberProp::Ident(quote_ident!("exports")),
}))),
op: op!("="),
right: Box::new(Expr::Call(CallExpr {
span: DUMMY_SP,
callee: quote_ident!("createProxy").as_callee(),
args: vec![filepath.as_arg()],
type_args: Default::default(),
})),
})),
})),
]
Expand Down
33 changes: 8 additions & 25 deletions packages/next/build/webpack/plugins/flight-client-entry-plugin.ts
Expand Up @@ -16,7 +16,7 @@ import {
COMPILER_NAMES,
FLIGHT_SERVER_CSS_MANIFEST,
} from '../../../shared/lib/constants'
import type { FlightCSSManifest } from './flight-manifest-plugin'
import { FlightCSSManifest, traverseModules } from './flight-manifest-plugin'
import { ASYNC_CLIENT_MODULES } from './flight-manifest-plugin'
import { isClientComponentModule } from '../loaders/utils'

Expand Down Expand Up @@ -64,15 +64,15 @@ export class FlightClientEntryPlugin {
})

compiler.hooks.afterCompile.tap(PLUGIN_NAME, (compilation) => {
;(compilation.moduleGraph._moduleMap as any).forEach(
(_: any, mod: any) => {
if (mod.request && mod.resource && !mod.buildInfo.rsc) {
if (compilation.moduleGraph.isAsync(mod)) {
ASYNC_CLIENT_MODULES.add(mod.resource)
}
traverseModules(compilation, (mod) => {
// The module must has request, and resource so it's not a new entry created with loader.
// Using the client layer module, which doesn't have `rsc` tag in buildInfo.
if (mod.request && mod.resource && !mod.buildInfo.rsc) {
if (compilation.moduleGraph.isAsync(mod)) {
ASYNC_CLIENT_MODULES.add(mod.resource)
}
}
)
})
})
}

Expand All @@ -92,13 +92,6 @@ export class FlightClientEntryPlugin {

const request = entryDependency.request

console.log('------', request)
// if (modRequest.includes('random')) {
// globalThis.__G = compilation.moduleGraph
// globalThis.__R = mod
// console.log(modRequest, '->', compilation.moduleGraph.isAsync(mod))
// }

if (
!request.startsWith('next-edge-ssr-loader?') &&
!request.startsWith('next-app-loader?')
Expand Down Expand Up @@ -393,16 +386,6 @@ export class FlightClientEntryPlugin {
return reject(err)
}

// console.log(entry);

// [...module.dependencies].forEach(m => {
// if (m.request && m.request.includes('random')) {
// globalThis.__G = compilation.moduleGraph
// globalThis.__R = m
// console.log(m.request, '->', compilation.moduleGraph.isAsync(m), Object.keys(m))
// }
// })

compilation.hooks.succeedEntry.call(entry, options, module)
return resolve(module)
}
Expand Down
62 changes: 35 additions & 27 deletions packages/next/build/webpack/plugins/flight-manifest-plugin.ts
Expand Up @@ -65,8 +65,37 @@ export type FlightCSSManifest = {

const PLUGIN_NAME = 'FlightManifestPlugin'

// Collect modules from server/edge compiler in client layer,
// and detect if it's been used, and mark it as `async: true` for react.
// So that react could unwrap the async module from promise and render module itself.
export const ASYNC_CLIENT_MODULES = new Set<string>()

export function traverseModules(
compilation: webpack.Compilation,
callback: (
mod: any,
chunk: webpack.Chunk,
chunkGroup: typeof compilation.chunkGroups[0]
) => any
) {
compilation.chunkGroups.forEach((chunkGroup) => {
chunkGroup.chunks.forEach((chunk: webpack.Chunk) => {
const chunkModules = compilation.chunkGraph.getChunkModulesIterable(
chunk
// TODO: Update type so that it doesn't have to be cast.
) as Iterable<webpack.NormalModule>
for (const mod of chunkModules) {
callback(mod, chunk, chunkGroup)
const anyModule = mod as any
if (anyModule.modules) {
for (const subMod of anyModule.modules)
callback(subMod, chunk, chunkGroup)
}
}
})
})
}

export class FlightManifestPlugin {
dev: Options['dev'] = false

Expand Down Expand Up @@ -124,21 +153,7 @@ export class FlightManifestPlugin {
}
}

compilation.chunkGroups.forEach((chunkGroup) => {
chunkGroup.chunks.forEach((chunk: webpack.Chunk) => {
const chunkModules = compilation.chunkGraph.getChunkModulesIterable(
chunk
// TODO: Update type so that it doesn't have to be cast.
) as Iterable<webpack.NormalModule>
for (const mod of chunkModules) {
collectClientRequest(mod)
const anyModule = mod as any
if (anyModule.modules) {
for (const subMod of anyModule.modules) collectClientRequest(subMod)
}
}
})
})
traverseModules(compilation, (mod) => collectClientRequest(mod))

compilation.chunkGroups.forEach((chunkGroup) => {
const cssResourcesInChunkGroup = new Set<string>()
Expand Down Expand Up @@ -215,16 +230,7 @@ export class FlightManifestPlugin {
}

const exportsInfo = compilation.moduleGraph.getExportsInfo(mod)
const isAsync = false // ASYNC_CLIENT_MODULES.has(mod.resource) // compilation.moduleGraph.isAsync(mod)

if (isAsync) {
console.log('!!!!!!', mod.resource)
}

// if (mod.resource.includes('random')) {
// console.log('!!!!!!!', mod.resource, isAsync, compilation.moduleGraph._getModuleGraphModule(mod).async, compilation.moduleGraph.isAsync)
// console.log('???????', mod.resource, ASYNC_CLIENT_MODULES.has(mod.resource))
// }
const isAsyncModule = ASYNC_CLIENT_MODULES.has(mod.resource)

const cjsExports = [
...new Set([
Expand Down Expand Up @@ -278,8 +284,10 @@ export class FlightManifestPlugin {
id,
name,
chunks: requiredChunks,
// Forcing the chunk to be `async` for esm compatible
async: isAsync,
// E.g.
// page (server) -> local module (client) -> package (esm)
// The esm package will bubble up to make the entire chain till the client entry as async module.
async: isAsyncModule,
}
}

Expand Down
4 changes: 2 additions & 2 deletions test/e2e/app-dir/rsc-basic/app/page.js
@@ -1,6 +1,6 @@
import Nav from '../components/nav'
import { headers } from 'next/dist/client/components/hooks-server'
// import { name } from 'random-module-instance'
import { name } from 'random-module-instance'

const envVar = process.env.ENV_VAR_TEST
const headerKey = 'x-next-test-client'
Expand All @@ -14,7 +14,7 @@ export default function Index() {
<h1>{`component:index.server`}</h1>
<div>{'env:' + envVar}</div>
<div>{'header:' + header}</div>
{/* <p>{name}</p> */}
<p>{name}</p>
<Nav />
</div>
)
Expand Down

0 comments on commit 2eef220

Please sign in to comment.