@@ -51,13 +51,17 @@ export interface PageStaticInfo {
5151
5252const CLIENT_MODULE_LABEL =
5353 / \/ \* _ _ n e x t _ i n t e r n a l _ c l i e n t _ e n t r y _ d o _ n o t _ u s e _ _ ( [ ^ ] * ) ( c j s | a u t o ) \* \/ /
54+
5455const ACTION_MODULE_LABEL =
5556 / \/ \* _ _ n e x t _ i n t e r n a l _ a c t i o n _ e n t r y _ d o _ n o t _ u s e _ _ ( [ ^ ] + ) \* \/ /
5657
58+ const CLIENT_DIRECTIVE = 'use client'
59+ const SERVER_ACTION_DIRECTIVE = 'use server'
60+
5761export type RSCModuleType = 'server' | 'client'
5862export function getRSCModuleInformation (
5963 source : string ,
60- isServerLayer = true
64+ isServerLayer : boolean
6165) : RSCMeta {
6266 const actions = source . match ( ACTION_MODULE_LABEL ) ?. [ 1 ] ?. split ( ',' )
6367 const clientInfoMatch = source . match ( CLIENT_MODULE_LABEL )
@@ -75,14 +79,13 @@ export function getRSCModuleInformation(
7579 const clientEntryType = clientInfoMatch ?. [ 2 ] as 'cjs' | 'auto'
7680
7781 const type = clientRefs ? RSC_MODULE_TYPES . client : RSC_MODULE_TYPES . server
78- const hasUseClientDirective = / ^ \s * [ ' " ] u s e c l i e n t [ ' " ] / . test ( source )
82+
7983 return {
8084 type,
8185 actions,
8286 clientRefs,
8387 clientEntryType,
8488 isClientRef,
85- hasUseClientDirective,
8689 }
8790}
8891
@@ -124,6 +127,7 @@ function checkExports(
124127 generateSitemaps ?: boolean
125128 generateStaticParams : boolean
126129 extraProperties ?: Set < string >
130+ directives ?: Set < string >
127131} {
128132 const exportsSet = new Set < string > ( [
129133 'getStaticProps' ,
@@ -142,8 +146,27 @@ function checkExports(
142146 let generateSitemaps : boolean = false
143147 let generateStaticParams = false
144148 let extraProperties = new Set < string > ( )
149+ let directives = new Set < string > ( )
150+ let hasLeadingNonDirectiveNode = false
145151
146152 for ( const node of swcAST . body ) {
153+ // There should be no non-string literals nodes before directives
154+ if (
155+ node . type === 'ExpressionStatement' &&
156+ node . expression . type === 'StringLiteral'
157+ ) {
158+ if ( ! hasLeadingNonDirectiveNode ) {
159+ const directive = node . expression . value
160+ if ( CLIENT_DIRECTIVE === directive ) {
161+ directives . add ( 'client' )
162+ }
163+ if ( SERVER_ACTION_DIRECTIVE === directive ) {
164+ directives . add ( 'server' )
165+ }
166+ }
167+ } else {
168+ hasLeadingNonDirectiveNode = true
169+ }
147170 if (
148171 node . type === 'ExportDeclaration' &&
149172 node . declaration ?. type === 'VariableDeclaration'
@@ -240,6 +263,7 @@ function checkExports(
240263 generateSitemaps,
241264 generateStaticParams,
242265 extraProperties,
266+ directives,
243267 }
244268 } catch ( err ) { }
245269 }
@@ -253,6 +277,7 @@ function checkExports(
253277 generateSitemaps : false ,
254278 generateStaticParams : false ,
255279 extraProperties : undefined ,
280+ directives : undefined ,
256281 }
257282}
258283
@@ -467,8 +492,9 @@ export async function getPageStaticInfo(params: {
467492 preferredRegion,
468493 generateStaticParams,
469494 extraProperties,
495+ directives,
470496 } = checkExports ( swcAST , pageFilePath )
471- const rscInfo = getRSCModuleInformation ( fileContent )
497+ const rscInfo = getRSCModuleInformation ( fileContent , true )
472498 const rsc = rscInfo . type
473499
474500 // default / failsafe value for config
@@ -575,7 +601,7 @@ export async function getPageStaticInfo(params: {
575601
576602 if (
577603 pageType === 'app' &&
578- rscInfo . hasUseClientDirective &&
604+ directives ?. has ( 'client' ) &&
579605 generateStaticParams
580606 ) {
581607 throw new Error (
0 commit comments